am 1242af06: am 32cfe2bb: am d37afa37: Merge "docs: Unbuntu troubleshooting link to CamelCase ID" into klp-modular-docs * commit '1242af060bec63ec3a37512ebbbdbe545bd9f0f7': docs: Unbuntu troubleshooting link to CamelCase ID
diff --git a/Android.mk b/Android.mk index 8f0869c..6a9da2f 100644 --- a/Android.mk +++ b/Android.mk
@@ -31,6 +31,10 @@ # So we first build the framework as a monolithic static library then split it # up into smaller pieces. # ============================================================ + +# embedded builds use nothing in frameworks/base +ifneq ($(ANDROID_BUILD_EMBEDDED),true) + include $(CLEAR_VARS) # FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk @@ -64,6 +68,7 @@ core/java/android/app/IActivityController.aidl \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IAlarmManager.aidl \ + core/java/android/app/IAppTask.aidl \ core/java/android/app/IBackupAgent.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ core/java/android/app/INotificationManager.aidl \ @@ -72,8 +77,9 @@ core/java/android/app/ISearchManagerCallback.aidl \ core/java/android/app/IServiceConnection.aidl \ core/java/android/app/IStopUserCallback.aidl \ - core/java/android/app/IThumbnailReceiver.aidl \ - core/java/android/app/IThumbnailRetriever.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/IUiAutomationConnection.aidl \ core/java/android/app/IUiModeManager.aidl \ @@ -81,12 +87,17 @@ core/java/android/app/IWallpaperManager.aidl \ core/java/android/app/IWallpaperManagerCallback.aidl \ core/java/android/app/admin/IDevicePolicyManager.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/IFullBackupRestoreObserver.aidl \ core/java/android/app/backup/IRestoreObserver.aidl \ core/java/android/app/backup/IRestoreSession.aidl \ + core/java/android/app/usage/IUsageStatsManager.aidl \ core/java/android/bluetooth/IBluetooth.aidl \ core/java/android/bluetooth/IBluetoothA2dp.aidl \ + core/java/android/bluetooth/IBluetoothA2dpSink.aidl \ + core/java/android/bluetooth/IBluetoothAvrcpController.aidl \ core/java/android/bluetooth/IBluetoothCallback.aidl \ core/java/android/bluetooth/IBluetoothHeadset.aidl \ core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \ @@ -99,6 +110,7 @@ core/java/android/bluetooth/IBluetoothPbap.aidl \ core/java/android/bluetooth/IBluetoothMap.aidl \ core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \ + core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ @@ -107,13 +119,21 @@ core/java/android/content/IIntentReceiver.aidl \ core/java/android/content/IIntentSender.aidl \ core/java/android/content/IOnPrimaryClipChangedListener.aidl \ - core/java/android/content/IAnonymousSyncAdapter.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/pm/ILauncherApps.aidl \ + core/java/android/content/pm/IOnAppsChangedListener.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/IPackageInstallObserver.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 \ core/java/android/content/pm/IPackageMoveObserver.aidl \ core/java/android/content/pm/IPackageStatsObserver.aidl \ @@ -130,20 +150,35 @@ core/java/android/hardware/ISerialManager.aidl \ core/java/android/hardware/display/IDisplayManager.aidl \ core/java/android/hardware/display/IDisplayManagerCallback.aidl \ - core/java/android/hardware/hdmi/IHdmiCecListener.aidl \ - core/java/android/hardware/hdmi/IHdmiCecService.aidl \ + core/java/android/hardware/display/IVirtualDisplayCallback.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/location/IActivityRecognitionHardware.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/soundtrigger/IRecognitionStatusCallback.aidl \ core/java/android/hardware/usb/IUsbManager.aidl \ core/java/android/net/IConnectivityManager.aidl \ + core/java/android/net/IEthernetManager.aidl \ core/java/android/net/INetworkManagementEventObserver.aidl \ core/java/android/net/INetworkPolicyListener.aidl \ core/java/android/net/INetworkPolicyManager.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/nsd/INsdManager.aidl \ @@ -152,11 +187,14 @@ core/java/android/nfc/INfcAdapterExtras.aidl \ core/java/android/nfc/INfcTag.aidl \ core/java/android/nfc/INfcCardEmulation.aidl \ + core/java/android/nfc/INfcLockscreenDispatch.aidl \ + core/java/android/nfc/INfcUnlockHandler.aidl \ core/java/android/os/IBatteryPropertiesListener.aidl \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ core/java/android/os/IHardwareService.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/IPowerManager.aidl \ @@ -167,6 +205,8 @@ core/java/android/os/IVibratorService.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/print/ILayoutResultCallback.aidl \ core/java/android/print/IPrinterDiscoveryObserver.aidl \ core/java/android/print/IPrintDocumentAdapter.aidl \ @@ -179,9 +219,16 @@ core/java/android/print/IWriteResultCallback.aidl \ core/java/android/printservice/IPrintService.aidl \ core/java/android/printservice/IPrintServiceClient.aidl \ - core/java/android/service/dreams/IDozeHardware.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ + core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \ + core/java/android/service/fingerprint/IFingerprintService.aidl \ + core/java/android/service/fingerprint/IFingerprintServiceReceiver.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 \ @@ -191,7 +238,6 @@ core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \ core/java/android/view/IApplicationToken.aidl \ core/java/android/view/IAssetAtlas.aidl \ - core/java/android/view/IMagnificationCallbacks.aidl \ core/java/android/view/IInputFilter.aidl \ core/java/android/view/IInputFilterHost.aidl \ core/java/android/view/IOnKeyguardExitResult.aidl \ @@ -201,6 +247,8 @@ 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 \ @@ -209,7 +257,10 @@ core/java/com/android/internal/app/IAppOpsService.aidl \ core/java/com/android/internal/app/IBatteryStats.aidl \ core/java/com/android/internal/app/IProcessStats.aidl \ - core/java/com/android/internal/app/IUsageStats.aidl \ + core/java/com/android/internal/app/IVoiceInteractionManagerService.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/appwidget/IAppWidgetService.aidl \ core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \ @@ -221,6 +272,7 @@ core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \ core/java/com/android/internal/policy/IKeyguardService.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/statusbar/IStatusBar.aidl \ core/java/com/android/internal/statusbar/IStatusBarService.aidl \ @@ -237,6 +289,7 @@ core/java/com/android/internal/view/IInputMethodSession.aidl \ core/java/com/android/internal/view/IInputSessionCallback.aidl \ core/java/com/android/internal/widget/ILockSettings.aidl \ + core/java/com/android/internal/widget/ILockSettingsObserver.aidl \ core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \ core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \ keystore/java/android/security/IKeyChainAliasCallback.aidl \ @@ -246,6 +299,8 @@ location/java/android/location/IFusedProvider.aidl \ location/java/android/location/IGeocodeProvider.aidl \ location/java/android/location/IGeofenceProvider.aidl \ + location/java/android/location/IGpsMeasurementsListener.aidl \ + location/java/android/location/IGpsNavigationMessageListener.aidl \ location/java/android/location/IGpsStatusListener.aidl \ location/java/android/location/IGpsStatusProvider.aidl \ location/java/android/location/ILocationListener.aidl \ @@ -257,6 +312,8 @@ 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/IMediaRouterClient.aidl \ media/java/android/media/IMediaRouterService.aidl \ media/java/android/media/IMediaScannerListener.aidl \ @@ -265,17 +322,64 @@ media/java/android/media/IRemoteControlDisplay.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/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/ISessionController.aidl \ + media/java/android/media/session/ISessionControllerCallback.aidl \ + media/java/android/media/session/ISession.aidl \ + media/java/android/media/session/ISessionCallback.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/service/media/IMediaBrowserService.aidl \ + media/java/android/service/media/IMediaBrowserServiceCallbacks.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/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/IImsService.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/ImsConfigListener.aidl \ telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \ telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \ telephony/java/com/android/internal/telephony/ITelephony.aidl \ - telephony/java/com/android/internal/telephony/ITelephonyListener.aidl \ telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \ telephony/java/com/android/internal/telephony/ISms.aidl \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ + telephony/java/com/android/internal/telephony/ISub.aidl \ + telephony/java/com/android/internal/telephony/IMms.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ wifi/java/android/net/wifi/p2p/IWifiP2pManager.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 \ @@ -291,30 +395,11 @@ LOCAL_NO_STANDARD_LIBRARIES := true LOCAL_JAVA_LIBRARIES := core-libart conscrypt okhttp core-junit bouncycastle ext -LOCAL_MODULE := framework-base - -LOCAL_JAR_EXCLUDE_FILES := none - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# 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 -$(full_classes_compiled_jar): $(framework_res_R_stamp) - -# Build part 1 of the framework library. -# ============================================================ -include $(CLEAR_VARS) - LOCAL_MODULE := framework -LOCAL_MODULE_CLASS := JAVA_LIBRARIES -LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_STATIC_JAVA_LIBRARIES := framework-base -LOCAL_DX_FLAGS := --core-library -# Packages to include, use \* wildcard to include descendants. -LOCAL_JAR_PACKAGES := android\* +LOCAL_DX_FLAGS := --core-library --multi-dex + +LOCAL_RMTYPEDEFS := true # List of classes and interfaces which should be loaded by the Zygote. LOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/preloaded-classes @@ -322,28 +407,15 @@ include $(BUILD_JAVA_LIBRARY) framework_module := $(LOCAL_INSTALLED_MODULE) -# Build part 2 of the framework library. -# ============================================================ -include $(CLEAR_VARS) +# 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 +$(full_classes_compiled_jar): $(framework_res_R_stamp) -LOCAL_MODULE := framework2 -LOCAL_MODULE_CLASS := JAVA_LIBRARIES -LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_STATIC_JAVA_LIBRARIES := framework-base -LOCAL_DX_FLAGS := --core-library - -# Packages to include, use \* wildcard to include descendants. -LOCAL_JAR_PACKAGES := com\* javax\* - -include $(BUILD_JAVA_LIBRARY) -framework2_module := $(LOCAL_INSTALLED_MODULE) - -# Make sure that all framework modules are installed when framework is. -# ============================================================ $(framework_module): | $(dir $(framework_module))framework-res.apk -$(framework_module): | $(dir $(framework_module))framework2.jar -framework_built := $(call java-lib-deps,framework framework2) +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. @@ -378,10 +450,25 @@ frameworks/base/core/java/android/os/DropBoxManager.aidl \ frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \ frameworks/base/core/java/android/os/ParcelUuid.aidl \ + frameworks/base/core/java/android/os/PersistableBundle.aidl \ + frameworks/base/core/java/android/print/PrinterInfo.aidl \ + frameworks/base/core/java/android/print/PageRange.aidl \ + frameworks/base/core/java/android/print/PrintAttributes.aidl \ + frameworks/base/core/java/android/print/PrinterCapabilitiesInfo.aidl \ + frameworks/base/core/java/android/print/PrinterId.aidl \ + frameworks/base/core/java/android/print/PrintJobId.aidl \ + frameworks/base/core/java/android/print/PrintJobInfo.aidl \ + frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \ + frameworks/base/core/java/android/view/accessibility/AccessibilityEvent.aidl \ + frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.aidl \ + frameworks/base/core/java/android/view/accessibility/AccessibilityRecord.aidl \ + frameworks/base/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl \ frameworks/base/core/java/android/view/KeyEvent.aidl \ frameworks/base/core/java/android/view/MotionEvent.aidl \ frameworks/base/core/java/android/view/Surface.aidl \ frameworks/base/core/java/android/view/WindowManager.aidl \ + frameworks/base/core/java/android/view/WindowAnimationFrameStats.aidl \ + frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \ frameworks/base/core/java/android/widget/RemoteViews.aidl \ frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \ frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \ @@ -403,6 +490,13 @@ frameworks/base/location/java/android/location/FusedBatchOptions.aidl \ frameworks/base/location/java/com/android/internal/location/ProviderProperties.aidl \ frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \ + frameworks/base/media/java/android/media/AudioAttributes.aidl \ + frameworks/base/media/java/android/media/MediaDescription.aidl \ + frameworks/base/media/java/android/media/MediaMetadata.aidl \ + frameworks/base/media/java/android/media/Rating.aidl \ + frameworks/base/media/java/android/media/browse/MediaBrowser.aidl \ + frameworks/base/media/java/android/media/session/MediaSession.aidl \ + frameworks/base/media/java/android/media/session/PlaybackState.aidl \ frameworks/base/telephony/java/android/telephony/ServiceState.aidl \ frameworks/base/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \ frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl \ @@ -501,8 +595,6 @@ okhttp \ ext \ framework \ - framework2 \ - mms-common \ telephony-common \ voip-common @@ -514,8 +606,12 @@ framework_docs_LOCAL_DROIDDOC_HTML_DIR := docs/html # The since flag (-since N.xml API_LEVEL) is used to add API Level information # to the reference documentation. Must be in order of oldest to newest. +# +# Conscrypt (com.android.org.conscrypt) is an implementation detail and should +# not be referenced in the documentation. framework_docs_LOCAL_DROIDDOC_OPTIONS := \ -knowntags ./frameworks/base/docs/knowntags.txt \ + -hidePackage com.android.org.conscrypt \ -since $(SRC_API_DIR)/1.xml 1 \ -since $(SRC_API_DIR)/2.xml 2 \ -since $(SRC_API_DIR)/3.xml 3 \ @@ -536,11 +632,11 @@ -since $(SRC_API_DIR)/18.txt 18 \ -since $(SRC_API_DIR)/19.txt 19 \ -since $(SRC_API_DIR)/20.txt 20 \ - -werror -hide 113 \ + -werror -hide 111 -hide 113 \ -overview $(LOCAL_PATH)/core/java/overview.html framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR:= \ - $(call intermediates-dir-for,JAVA_LIBRARIES,framework-base,,COMMON) + $(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON) framework_docs_LOCAL_ADDITIONAL_JAVA_DIR:= \ $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR) \ @@ -596,6 +692,7 @@ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_stubs_current_intermediates/src \ -api $(INTERNAL_PLATFORM_API_FILE) \ + -removedApi $(INTERNAL_PLATFORM_REMOVED_API_FILE) \ -nodocs LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk @@ -609,7 +706,7 @@ $(INTERNAL_PLATFORM_API_FILE): $(full_target) $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE)) -# ==== the private api stubs =================================== +# ==== the system api stubs =================================== include $(CLEAR_VARS) LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES) @@ -621,12 +718,14 @@ LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR) LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) -LOCAL_MODULE := private-api-stubs +LOCAL_MODULE := system-api-stubs LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ - -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_private_stubs_current_intermediates/src \ - -showAnnotation android.annotation.PrivateApi \ + -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_system_stubs_current_intermediates/src \ + -showAnnotation android.annotation.SystemApi \ + -api $(INTERNAL_PLATFORM_SYSTEM_API_FILE) \ + -removedApi $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) \ -nodocs LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk @@ -663,8 +762,9 @@ $(full_target): $(framework_built) $(gen) # Run this for checkbuild -.PHONY: checkbuild checkbuild: doc-comment-check-docs +# Check comment when you are updating the API +update-api: doc-comment-check-docs # ==== static html in the sdk ================================== include $(CLEAR_VARS) @@ -730,6 +830,41 @@ include $(BUILD_DROIDDOC) +# ==== docs for the web (on the androiddevdocs app engine server) ======================= +# TODO: Fix the System API docs build. +ifneq ($(filter online-system-api-sdk-docs,$(MAKECMDGOALS)),) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES) +LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES) +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) +LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH) +LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR) +LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR) +LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) +LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl / + +LOCAL_MODULE := online-system-api-sdk + +LOCAL_DROIDDOC_OPTIONS:= \ + $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -showAnnotation android.annotation.SystemApi \ + -title "Android SDK - Including system APIs." \ + -toroot / \ + -hdf android.whichdoc online \ + $(sample_groups) \ + -hdf android.hasSamples true \ + -samplesdir $(samples_dir) + +LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk +# Don't build by default +LOCAL_UNINSTALLABLE_MODULE := true + +include $(BUILD_DROIDDOC) +endif # online-system-api-sdk-docs in make command line. + # ==== docs for the web (on the devsite app engine server) ======================= include $(CLEAR_VARS) LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES) @@ -821,3 +956,5 @@ ifeq (,$(ONE_SHOT_MAKEFILE)) include $(call first-makefiles-under,$(LOCAL_PATH)) endif + +endif # ANDROID_BUILD_EMBEDDED
diff --git a/CleanSpec.mk b/CleanSpec.mk index 82651bd..28c2172 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk
@@ -34,9 +34,9 @@ # made today requires touching the same file, just copy the old # touch step and add it to the end of the list. # -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ +# ***************************************************************** +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER +# ***************************************************************** # For example: #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) @@ -171,6 +171,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/printservice/) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/packages/services/Proxy/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoverySessionObserver.*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoverySessionClient.*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/os/IBattery*) @@ -185,8 +186,45 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrintClient.*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/IMedia*) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/view/IMagnificationCallbacks*) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/wearable) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/ITv*) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/classes/android/app/task) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app/task) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/classes/android/app/TaskManager) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app/maintenance) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/classes/android/app/maintenance) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes/android/app/maintenance) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes/android/app/maintenance) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/maintenance) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/ims-common_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework2_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/telecomm/java/com/android/internal/telecom) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework.* $(PRODUCT_OUT)/system/framework2.*) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/docs/api-stubs-timestamp) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/inputflinger $(PRODUCT_OUT)/symbols/system/bin/inputflinger) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/RsFountainFbo_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/telecomm/java/com/android/internal/telecomm) -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ +# ****************************************************************** +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER +# ******************************************************************
diff --git a/api/current.txt b/api/current.txt index 9db066a..eb7891a 100644 --- a/api/current.txt +++ b/api/current.txt
@@ -21,12 +21,15 @@ field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET"; field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN"; + field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE"; field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE"; field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"; field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE"; field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS"; field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE"; + field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT"; + field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION"; field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE"; field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER"; field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH"; @@ -99,10 +102,11 @@ field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"; field public static final java.lang.String READ_PROFILE = "android.permission.READ_PROFILE"; field public static final java.lang.String READ_SMS = "android.permission.READ_SMS"; - field public static final java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM"; + field public static final deprecated java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM"; field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS"; field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS"; field public static final java.lang.String READ_USER_DICTIONARY = "android.permission.READ_USER_DICTIONARY"; + field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL"; field public static final java.lang.String REBOOT = "android.permission.REBOOT"; field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED"; field public static final java.lang.String RECEIVE_MMS = "android.permission.RECEIVE_MMS"; @@ -149,9 +153,10 @@ field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS"; field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS"; field public static final java.lang.String WRITE_SMS = "android.permission.WRITE_SMS"; - field public static final java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM"; + field public static final deprecated java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM"; field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS"; field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission.WRITE_USER_DICTIONARY"; + field public static final java.lang.String WRITE_VOICEMAIL = "com.android.voicemail.permission.WRITE_VOICEMAIL"; } public static final class Manifest.permission_group { @@ -237,12 +242,14 @@ field public static final int action = 16842797; // 0x101002d field public static final int actionBarDivider = 16843675; // 0x101039b field public static final int actionBarItemBackground = 16843676; // 0x101039c + field public static final int actionBarPopupTheme = 16843917; // 0x101048d field public static final int actionBarSize = 16843499; // 0x10102eb field public static final int actionBarSplitStyle = 16843656; // 0x1010388 field public static final int actionBarStyle = 16843470; // 0x10102ce field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4 field public static final int actionBarTabStyle = 16843507; // 0x10102f3 field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5 + field public static final int actionBarTheme = 16843825; // 0x1010431 field public static final int actionBarWidgetTheme = 16843671; // 0x1010397 field public static final int actionButtonStyle = 16843480; // 0x10102d8 field public static final int actionDropDownStyle = 16843479; // 0x10102d7 @@ -254,11 +261,15 @@ field public static final int actionModeCloseDrawable = 16843484; // 0x10102dc field public static final int actionModeCopyDrawable = 16843538; // 0x1010312 field public static final int actionModeCutDrawable = 16843537; // 0x1010311 + field public static final int actionModeFindDrawable = 16843898; // 0x101047a field public static final int actionModePasteDrawable = 16843539; // 0x1010313 field public static final int actionModeSelectAllDrawable = 16843646; // 0x101037e + field public static final int actionModeShareDrawable = 16843897; // 0x1010479 field public static final int actionModeSplitBackground = 16843677; // 0x101039d field public static final int actionModeStyle = 16843668; // 0x1010394 + field public static final int actionModeWebSearchDrawable = 16843899; // 0x101047b field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6 + field public static final int actionOverflowMenuStyle = 16843844; // 0x1010444 field public static final int actionProviderClass = 16843657; // 0x1010389 field public static final int actionViewClass = 16843516; // 0x10102fc field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd @@ -285,6 +296,9 @@ field public static final int alphabeticShortcut = 16843235; // 0x10101e3 field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef field public static final int alwaysRetainTaskState = 16843267; // 0x1010203 + field public static final int amPmBackgroundColor = 16843941; // 0x10104a5 + field public static final int amPmTextColor = 16843940; // 0x10104a4 + field public static final int ambientShadowAlpha = 16843966; // 0x10104be field public static final int angle = 16843168; // 0x10101a0 field public static final int animateFirstView = 16843477; // 0x10102d5 field public static final int animateLayoutChanges = 16843506; // 0x10102f2 @@ -304,6 +318,7 @@ field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b field public static final int autoLink = 16842928; // 0x10100b0 field public static final int autoMirrored = 16843754; // 0x10103ea + field public static final int autoRemoveFromRecents = 16843847; // 0x1010447 field public static final int autoStart = 16843445; // 0x10102b5 field public static final deprecated int autoText = 16843114; // 0x101016a field public static final int autoUrlDetect = 16843404; // 0x101028c @@ -312,7 +327,10 @@ field public static final int backgroundDimEnabled = 16843295; // 0x101021f field public static final int backgroundSplit = 16843659; // 0x101038b field public static final int backgroundStacked = 16843658; // 0x101038a + field public static final int backgroundTint = 16843883; // 0x101046b + field public static final int backgroundTintMode = 16843884; // 0x101046c field public static final int backupAgent = 16843391; // 0x101027f + field public static final int banner = 16843762; // 0x10103f2 field public static final int baseline = 16843548; // 0x101031c field public static final int baselineAlignBottom = 16843042; // 0x1010122 field public static final int baselineAligned = 16843046; // 0x1010126 @@ -330,12 +348,18 @@ field public static final int bufferType = 16843086; // 0x101014e field public static final int button = 16843015; // 0x1010107 field public static final int buttonBarButtonStyle = 16843567; // 0x101032f + field public static final int buttonBarNegativeButtonStyle = 16843915; // 0x101048b + field public static final int buttonBarNeutralButtonStyle = 16843914; // 0x101048a + field public static final int buttonBarPositiveButtonStyle = 16843913; // 0x1010489 field public static final int buttonBarStyle = 16843566; // 0x101032e field public static final int buttonStyle = 16842824; // 0x1010048 field public static final int buttonStyleInset = 16842826; // 0x101004a field public static final int buttonStyleSmall = 16842825; // 0x1010049 field public static final int buttonStyleToggle = 16842827; // 0x101004b + field public static final int buttonTint = 16843887; // 0x101046f + field public static final int buttonTintMode = 16843888; // 0x1010470 field public static final int cacheColorHint = 16843009; // 0x1010101 + field public static final int calendarTextColor = 16843931; // 0x101049b field public static final int calendarViewShown = 16843596; // 0x101034c field public static final int calendarViewStyle = 16843613; // 0x101035d field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8 @@ -353,6 +377,8 @@ field public static final int centerY = 16843171; // 0x10101a3 field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f field public static final int checkMark = 16843016; // 0x1010108 + field public static final int checkMarkTint = 16843943; // 0x10104a7 + field public static final int checkMarkTintMode = 16843944; // 0x10104a8 field public static final int checkable = 16843237; // 0x10101e5 field public static final int checkableBehavior = 16843232; // 0x10101e0 field public static final int checkboxStyle = 16842860; // 0x101006c @@ -371,22 +397,32 @@ field public static final int clipChildren = 16842986; // 0x10100ea field public static final int clipOrientation = 16843274; // 0x101020a field public static final int clipToPadding = 16842987; // 0x10100eb + field public static final int closeIcon = 16843905; // 0x1010481 field public static final int codes = 16843330; // 0x1010242 field public static final int collapseColumns = 16843083; // 0x101014b field public static final int color = 16843173; // 0x10101a5 + field public static final int colorAccent = 16843829; // 0x1010435 field public static final int colorActivatedHighlight = 16843664; // 0x1010390 field public static final int colorBackground = 16842801; // 0x1010031 field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab + field public static final int colorButtonNormal = 16843819; // 0x101042b + field public static final int colorControlActivated = 16843818; // 0x101042a + field public static final int colorControlHighlight = 16843820; // 0x101042c + field public static final int colorControlNormal = 16843817; // 0x1010429 + field public static final int colorEdgeEffect = 16843982; // 0x10104ce field public static final int colorFocusedHighlight = 16843663; // 0x101038f field public static final int colorForeground = 16842800; // 0x1010030 field public static final int colorForegroundInverse = 16843270; // 0x1010206 field public static final int colorLongPressedHighlight = 16843662; // 0x101038e field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391 field public static final int colorPressedHighlight = 16843661; // 0x101038d + field public static final int colorPrimary = 16843827; // 0x1010433 + field public static final int colorPrimaryDark = 16843828; // 0x1010434 field public static final int columnCount = 16843639; // 0x1010377 field public static final int columnDelay = 16843215; // 0x10101cf field public static final int columnOrderPreserved = 16843640; // 0x1010378 field public static final int columnWidth = 16843031; // 0x1010117 + field public static final int commitIcon = 16843909; // 0x1010485 field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365 field public static final int completionHint = 16843122; // 0x1010172 field public static final int completionHintView = 16843123; // 0x1010173 @@ -395,8 +431,18 @@ field public static final int configure = 16843357; // 0x101025d field public static final int constantSize = 16843158; // 0x1010196 field public static final int content = 16843355; // 0x101025b + field public static final int contentAgeHint = 16843961; // 0x10104b9 field public static final int contentAuthority = 16843408; // 0x1010290 field public static final int contentDescription = 16843379; // 0x1010273 + field public static final int contentInsetEnd = 16843860; // 0x1010454 + field public static final int contentInsetLeft = 16843861; // 0x1010455 + field public static final int contentInsetRight = 16843862; // 0x1010456 + field public static final int contentInsetStart = 16843859; // 0x1010453 + field public static final int controlX1 = 16843772; // 0x10103fc + field public static final int controlX2 = 16843774; // 0x10103fe + field public static final int controlY1 = 16843773; // 0x10103fd + field public static final int controlY2 = 16843775; // 0x10103ff + field public static final int country = 16843962; // 0x10104ba field public static final int cropToPadding = 16843043; // 0x1010123 field public static final int cursorVisible = 16843090; // 0x1010152 field public static final int customNavigationLayout = 16843474; // 0x10102d2 @@ -405,8 +451,12 @@ field public static final int dashGap = 16843175; // 0x10101a7 field public static final int dashWidth = 16843174; // 0x10101a6 field public static final int data = 16842798; // 0x101002e + field public static final int datePickerDialogTheme = 16843948; // 0x10104ac + field public static final int datePickerMode = 16843955; // 0x10104b3 field public static final int datePickerStyle = 16843612; // 0x101035c field public static final int dateTextAppearance = 16843593; // 0x1010349 + field public static final int dayOfWeekBackground = 16843924; // 0x1010494 + field public static final int dayOfWeekTextAppearance = 16843925; // 0x1010495 field public static final int debuggable = 16842767; // 0x101000f field public static final int defaultValue = 16843245; // 0x10101ed field public static final int delay = 16843212; // 0x10101cc @@ -437,6 +487,7 @@ field public static final int dividerHorizontal = 16843564; // 0x101032c field public static final int dividerPadding = 16843562; // 0x101032a field public static final int dividerVertical = 16843530; // 0x101030a + field public static final int documentLaunchMode = 16843845; // 0x1010445 field public static final int drawSelectorOnTop = 16843004; // 0x10100fc field public static final int drawable = 16843161; // 0x1010199 field public static final int drawableBottom = 16843118; // 0x101016e @@ -465,6 +516,8 @@ field public static final int editTextStyle = 16842862; // 0x101006e field public static final deprecated int editable = 16843115; // 0x101016b field public static final int editorExtras = 16843300; // 0x1010224 + field public static final int elegantTextHeight = 16843869; // 0x101045d + field public static final int elevation = 16843840; // 0x1010440 field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ems = 16843096; // 0x1010158 field public static final int enabled = 16842766; // 0x101000e @@ -474,7 +527,10 @@ field public static final int entries = 16842930; // 0x10100b2 field public static final int entryValues = 16843256; // 0x10101f8 field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d + field public static final int excludeClass = 16843842; // 0x1010442 field public static final int excludeFromRecents = 16842775; // 0x1010017 + field public static final int excludeId = 16843841; // 0x1010441 + field public static final int excludeName = 16843854; // 0x101044e field public static final int exitFadeDuration = 16843533; // 0x101030d field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052 field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053 @@ -499,11 +555,14 @@ field public static final int fastScrollOverlayPosition = 16843578; // 0x101033a field public static final int fastScrollPreviewBackgroundLeft = 16843575; // 0x1010337 field public static final int fastScrollPreviewBackgroundRight = 16843576; // 0x1010338 + field public static final int fastScrollStyle = 16843767; // 0x10103f7 field public static final int fastScrollTextColor = 16843609; // 0x1010359 field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336 field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339 field public static final int fillAfter = 16843197; // 0x10101bd + field public static final int fillAlpha = 16843980; // 0x10104cc field public static final int fillBefore = 16843196; // 0x10101bc + field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b @@ -517,27 +576,40 @@ field public static final int focusableInTouchMode = 16842971; // 0x10100db field public static final int focusedMonthDateColor = 16843587; // 0x1010343 field public static final int fontFamily = 16843692; // 0x10103ac + field public static final int fontFeatureSettings = 16843959; // 0x10104b7 field public static final int footerDividersEnabled = 16843311; // 0x101022f field public static final int foreground = 16843017; // 0x1010109 field public static final int foregroundGravity = 16843264; // 0x1010200 + field public static final int foregroundTint = 16843885; // 0x101046d + field public static final int foregroundTintMode = 16843886; // 0x101046e field public static final int format = 16843013; // 0x1010105 field public static final int format12Hour = 16843722; // 0x10103ca field public static final int format24Hour = 16843723; // 0x10103cb field public static final int fragment = 16843491; // 0x10102e3 + field public static final int fragmentAllowEnterTransitionOverlap = 16843976; // 0x10104c8 + field public static final int fragmentAllowReturnTransitionOverlap = 16843977; // 0x10104c9 field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7 field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8 + field public static final int fragmentEnterTransition = 16843971; // 0x10104c3 + field public static final int fragmentExitTransition = 16843970; // 0x10104c2 field public static final int fragmentFadeEnterAnimation = 16843497; // 0x10102e9 field public static final int fragmentFadeExitAnimation = 16843498; // 0x10102ea field public static final int fragmentOpenEnterAnimation = 16843493; // 0x10102e5 field public static final int fragmentOpenExitAnimation = 16843494; // 0x10102e6 + field public static final int fragmentReenterTransition = 16843975; // 0x10104c7 + field public static final int fragmentReturnTransition = 16843973; // 0x10104c5 + field public static final int fragmentSharedElementEnterTransition = 16843972; // 0x10104c4 + field public static final int fragmentSharedElementReturnTransition = 16843974; // 0x10104c6 field public static final int freezesText = 16843116; // 0x101016c field public static final int fromAlpha = 16843210; // 0x10101ca field public static final int fromDegrees = 16843187; // 0x10101b3 + field public static final int fromId = 16843850; // 0x101044a field public static final int fromScene = 16843741; // 0x10103dd field public static final int fromXDelta = 16843206; // 0x10101c6 field public static final int fromXScale = 16843202; // 0x10101c2 field public static final int fromYDelta = 16843208; // 0x10101c8 field public static final int fromYScale = 16843204; // 0x10101c4 + field public static final int fullBackupOnly = 16843891; // 0x1010473 field public static final int fullBright = 16842954; // 0x10100ca field public static final int fullDark = 16842950; // 0x10100c6 field public static final int functionalTest = 16842787; // 0x1010023 @@ -550,6 +622,7 @@ field public static final int gestureStrokeType = 16843385; // 0x1010279 field public static final int gestureStrokeWidth = 16843380; // 0x1010274 field public static final int glEsVersion = 16843393; // 0x1010281 + field public static final int goIcon = 16843906; // 0x1010482 field public static final int gradientRadius = 16843172; // 0x10101a4 field public static final int grantUriPermissions = 16842779; // 0x101001b field public static final int gravity = 16842927; // 0x10100af @@ -562,9 +635,15 @@ field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e field public static final int hardwareAccelerated = 16843475; // 0x10102d3 field public static final int hasCode = 16842764; // 0x101000c + field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0 field public static final int headerBackground = 16843055; // 0x101012f + field public static final int headerDayOfMonthTextAppearance = 16843927; // 0x1010497 field public static final int headerDividersEnabled = 16843310; // 0x101022e + field public static final int headerMonthTextAppearance = 16843926; // 0x1010496 + field public static final int headerTimeTextAppearance = 16843935; // 0x101049f + field public static final int headerYearTextAppearance = 16843928; // 0x1010498 field public static final int height = 16843093; // 0x1010155 + field public static final int hideOnContentScroll = 16843843; // 0x1010443 field public static final int hint = 16843088; // 0x1010150 field public static final int homeAsUpIndicator = 16843531; // 0x101030b field public static final int homeLayout = 16843549; // 0x101031d @@ -600,6 +679,8 @@ field public static final int indeterminateDuration = 16843069; // 0x101013d field public static final int indeterminateOnly = 16843066; // 0x101013a field public static final int indeterminateProgressStyle = 16843544; // 0x1010318 + field public static final int indeterminateTint = 16843881; // 0x1010469 + field public static final int indeterminateTintMode = 16843882; // 0x101046a field public static final int indicatorEnd = 16843730; // 0x10103d2 field public static final int indicatorLeft = 16843021; // 0x101010d field public static final int indicatorRight = 16843022; // 0x101010e @@ -612,6 +693,7 @@ field public static final int innerRadiusRatio = 16843163; // 0x101019b field public static final deprecated int inputMethod = 16843112; // 0x1010168 field public static final int inputType = 16843296; // 0x1010220 + field public static final int inset = 16843957; // 0x10104b5 field public static final int insetBottom = 16843194; // 0x10101ba field public static final int insetLeft = 16843191; // 0x10101b7 field public static final int insetRight = 16843192; // 0x10101b8 @@ -622,6 +704,7 @@ field public static final int isAsciiCapable = 16843753; // 0x10103e9 field public static final int isAuxiliary = 16843647; // 0x101037f field public static final int isDefault = 16843297; // 0x1010221 + field public static final int isGame = 16843764; // 0x10103f4 field public static final int isIndicator = 16843079; // 0x1010147 field public static final int isModifier = 16843334; // 0x1010246 field public static final int isRepeatable = 16843336; // 0x1010248 @@ -658,6 +741,8 @@ field public static final int largeScreens = 16843398; // 0x1010286 field public static final int largestWidthLimitDp = 16843622; // 0x1010366 field public static final int launchMode = 16842781; // 0x101001d + field public static final int launchTaskBehindSourceAnimation = 16843922; // 0x1010492 + field public static final int launchTaskBehindTargetAnimation = 16843921; // 0x1010491 field public static final int layerType = 16843604; // 0x1010354 field public static final int layout = 16842994; // 0x10100f2 field public static final int layoutAnimation = 16842988; // 0x10100ec @@ -684,6 +769,7 @@ field public static final int layout_centerVertical = 16843153; // 0x1010191 field public static final int layout_column = 16843084; // 0x101014c field public static final int layout_columnSpan = 16843645; // 0x101037d + field public static final int layout_columnWeight = 16843865; // 0x1010459 field public static final int layout_gravity = 16842931; // 0x10100b3 field public static final int layout_height = 16842997; // 0x10100f5 field public static final int layout_margin = 16842998; // 0x10100f6 @@ -695,6 +781,7 @@ field public static final int layout_marginTop = 16843000; // 0x10100f8 field public static final int layout_row = 16843643; // 0x101037b field public static final int layout_rowSpan = 16843644; // 0x101037c + field public static final int layout_rowWeight = 16843864; // 0x1010458 field public static final int layout_scale = 16843155; // 0x1010193 field public static final int layout_span = 16843085; // 0x101014d field public static final int layout_toEndOf = 16843704; // 0x10103b8 @@ -706,6 +793,7 @@ field public static final int layout_x = 16843135; // 0x101017f field public static final int layout_y = 16843136; // 0x1010180 field public static final int left = 16843181; // 0x10101ad + field public static final int letterSpacing = 16843958; // 0x10104b6 field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 field public static final int lines = 16843092; // 0x1010154 @@ -733,6 +821,7 @@ field public static final int manageSpaceActivity = 16842756; // 0x1010004 field public static final int mapViewStyle = 16842890; // 0x101008a field public static final int marqueeRepeatLimit = 16843293; // 0x101021d + field public static final int matchOrder = 16843855; // 0x101044f field public static final int max = 16843062; // 0x1010136 field public static final int maxDate = 16843584; // 0x1010340 field public static final int maxEms = 16843095; // 0x1010157 @@ -741,9 +830,11 @@ field public static final int maxLength = 16843104; // 0x1010160 field public static final int maxLevel = 16843186; // 0x10101b2 field public static final int maxLines = 16843091; // 0x1010153 + field public static final int maxRecents = 16843846; // 0x1010446 field public static final int maxRows = 16843059; // 0x1010133 field public static final int maxSdkVersion = 16843377; // 0x1010271 field public static final int maxWidth = 16843039; // 0x101011f + field public static final int maximumAngle = 16843903; // 0x101047f field public static final int measureAllChildren = 16843018; // 0x101010a field public static final int measureWithLargestChild = 16843476; // 0x10102d4 field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad @@ -759,14 +850,21 @@ field public static final int minResizeWidth = 16843669; // 0x1010395 field public static final int minSdkVersion = 16843276; // 0x101020c field public static final int minWidth = 16843071; // 0x101013f + field public static final int minimumHorizontalAngle = 16843901; // 0x101047d + field public static final int minimumVerticalAngle = 16843902; // 0x101047e field public static final int mipMap = 16843725; // 0x10103cd field public static final int mirrorForRtl = 16843726; // 0x10103ce field public static final int mode = 16843134; // 0x101017e field public static final int moreIcon = 16843061; // 0x1010135 + field public static final int multiArch = 16843918; // 0x101048e field public static final int multiprocess = 16842771; // 0x1010013 field public static final int name = 16842755; // 0x1010003 + field public static final int navigationBarColor = 16843858; // 0x1010452 + field public static final int navigationContentDescription = 16843969; // 0x10104c1 + field public static final int navigationIcon = 16843968; // 0x10104c0 field public static final int navigationMode = 16843471; // 0x10102cf field public static final int negativeButtonText = 16843254; // 0x10101f6 + field public static final int nestedScrollingEnabled = 16843830; // 0x1010436 field public static final int nextFocusDown = 16842980; // 0x10100e4 field public static final int nextFocusForward = 16843580; // 0x101033c field public static final int nextFocusLeft = 16842977; // 0x10100e1 @@ -777,6 +875,9 @@ field public static final int notificationTimeout = 16843651; // 0x1010383 field public static final int numColumns = 16843032; // 0x1010118 field public static final int numStars = 16843076; // 0x1010144 + field public static final int numbersBackgroundColor = 16843938; // 0x10104a2 + field public static final int numbersSelectorColor = 16843939; // 0x10104a3 + field public static final int numbersTextColor = 16843937; // 0x10104a1 field public static final deprecated int numeric = 16843109; // 0x1010165 field public static final int numericShortcut = 16843236; // 0x10101e4 field public static final int onClick = 16843375; // 0x101026f @@ -788,15 +889,18 @@ field public static final int orderingFromXml = 16843239; // 0x10101e7 field public static final int orientation = 16842948; // 0x10100c4 field public static final int outAnimation = 16843128; // 0x1010178 + field public static final int outlineProvider = 16843960; // 0x10104b8 field public static final int overScrollFooter = 16843459; // 0x10102c3 field public static final int overScrollHeader = 16843458; // 0x10102c2 field public static final int overScrollMode = 16843457; // 0x10102c1 + field public static final int overlapAnchor = 16843874; // 0x1010462 field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2 field public static final int packageNames = 16843649; // 0x1010381 field public static final int padding = 16842965; // 0x10100d5 field public static final int paddingBottom = 16842969; // 0x10100d9 field public static final int paddingEnd = 16843700; // 0x10103b4 field public static final int paddingLeft = 16842966; // 0x10100d6 + field public static final int paddingMode = 16843863; // 0x1010457 field public static final int paddingRight = 16842968; // 0x10100d8 field public static final int paddingStart = 16843699; // 0x10103b3 field public static final int paddingTop = 16842967; // 0x10100d7 @@ -808,12 +912,15 @@ field public static final int parentActivityName = 16843687; // 0x10103a7 field public static final deprecated int password = 16843100; // 0x101015c field public static final int path = 16842794; // 0x101002a + field public static final int pathData = 16843781; // 0x1010405 field public static final int pathPattern = 16842796; // 0x101002c field public static final int pathPrefix = 16842795; // 0x101002b + field public static final int patternPathData = 16843978; // 0x10104ca field public static final int permission = 16842758; // 0x1010006 field public static final int permissionFlags = 16843719; // 0x10103c7 field public static final int permissionGroup = 16842762; // 0x101000a field public static final int permissionGroupFlags = 16843717; // 0x10103c5 + field public static final int persistableMode = 16843821; // 0x101042d field public static final int persistent = 16842765; // 0x101000d field public static final int persistentDrawingCache = 16842990; // 0x10100ee field public static final deprecated int phoneNumber = 16843111; // 0x1010167 @@ -822,9 +929,11 @@ field public static final int popupAnimationStyle = 16843465; // 0x10102c9 field public static final int popupBackground = 16843126; // 0x1010176 field public static final int popupCharacters = 16843332; // 0x1010244 + field public static final int popupElevation = 16843916; // 0x101048c field public static final int popupKeyboard = 16843331; // 0x1010243 field public static final int popupLayout = 16843323; // 0x101023b field public static final int popupMenuStyle = 16843520; // 0x1010300 + field public static final int popupTheme = 16843945; // 0x10104a9 field public static final int popupWindowStyle = 16842870; // 0x1010076 field public static final int port = 16842793; // 0x1010029 field public static final int positiveButtonText = 16843253; // 0x10101f5 @@ -839,6 +948,8 @@ field public static final int privateImeOptions = 16843299; // 0x1010223 field public static final int process = 16842769; // 0x1010011 field public static final int progress = 16843063; // 0x1010137 + field public static final int progressBackgroundTint = 16843877; // 0x1010465 + field public static final int progressBackgroundTintMode = 16843878; // 0x1010466 field public static final int progressBarPadding = 16843545; // 0x1010319 field public static final int progressBarStyle = 16842871; // 0x1010077 field public static final int progressBarStyleHorizontal = 16842872; // 0x1010078 @@ -849,12 +960,17 @@ field public static final int progressBarStyleSmallInverse = 16843400; // 0x1010288 field public static final int progressBarStyleSmallTitle = 16843279; // 0x101020f field public static final int progressDrawable = 16843068; // 0x101013c + field public static final int progressTint = 16843875; // 0x1010463 + field public static final int progressTintMode = 16843876; // 0x1010464 field public static final int prompt = 16843131; // 0x101017b field public static final int propertyName = 16843489; // 0x10102e1 + field public static final int propertyXName = 16843892; // 0x1010474 + field public static final int propertyYName = 16843893; // 0x1010475 field public static final int protectionLevel = 16842761; // 0x1010009 field public static final int publicKey = 16843686; // 0x10103a6 field public static final int queryActionMsg = 16843227; // 0x10101db field public static final int queryAfterZeroResults = 16843394; // 0x1010282 + field public static final int queryBackground = 16843911; // 0x1010487 field public static final int queryHint = 16843608; // 0x1010358 field public static final int quickContactBadgeStyleSmallWindowLarge = 16843443; // 0x10102b3 field public static final int quickContactBadgeStyleSmallWindowMedium = 16843442; // 0x10102b2 @@ -869,6 +985,10 @@ field public static final int ratingBarStyleIndicator = 16843280; // 0x1010210 field public static final int ratingBarStyleSmall = 16842877; // 0x101007d field public static final int readPermission = 16842759; // 0x1010007 + field public static final int recognitionService = 16843932; // 0x101049c + field public static final int relinquishTaskIdentity = 16843894; // 0x1010476 + field public static final int reparent = 16843964; // 0x10104bc + field public static final int reparentWithOverlay = 16843965; // 0x10104bd field public static final int repeatCount = 16843199; // 0x10101bf field public static final int repeatMode = 16843200; // 0x10101c0 field public static final int reqFiveWayNav = 16843314; // 0x1010232 @@ -888,6 +1008,9 @@ field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d field public static final int restrictedAccountType = 16843733; // 0x10103d5 + field public static final int restrictionType = 16843923; // 0x1010493 + field public static final int resumeWhilePausing = 16843954; // 0x10104b2 + field public static final int reversible = 16843851; // 0x101044b field public static final int right = 16843183; // 0x10101af field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093 field public static final int ringtoneType = 16843257; // 0x10101f9 @@ -927,6 +1050,7 @@ field public static final int scrollbars = 16842974; // 0x10100de field public static final int scrollingCache = 16843006; // 0x10100fe field public static final deprecated int searchButtonText = 16843269; // 0x1010205 + field public static final int searchIcon = 16843907; // 0x1010483 field public static final int searchMode = 16843221; // 0x10101d5 field public static final int searchSettingsDescription = 16843402; // 0x101028a field public static final int searchSuggestAuthority = 16843222; // 0x10101d6 @@ -935,15 +1059,21 @@ field public static final int searchSuggestPath = 16843223; // 0x10101d7 field public static final int searchSuggestSelection = 16843224; // 0x10101d8 field public static final int searchSuggestThreshold = 16843373; // 0x101026d + field public static final int searchViewStyle = 16843904; // 0x1010480 field public static final int secondaryProgress = 16843064; // 0x1010138 + field public static final int secondaryProgressTint = 16843879; // 0x1010467 + field public static final int secondaryProgressTintMode = 16843880; // 0x1010468 field public static final int seekBarStyle = 16842875; // 0x101007b field public static final int segmentedButtonStyle = 16843568; // 0x1010330 field public static final int selectAllOnFocus = 16843102; // 0x101015e field public static final int selectable = 16843238; // 0x10101e6 field public static final int selectableItemBackground = 16843534; // 0x101030e + field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c field public static final int selectedDateVerticalBar = 16843591; // 0x1010347 field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342 + field public static final int sessionService = 16843837; // 0x101043d field public static final int settingsActivity = 16843301; // 0x1010225 + field public static final int setupActivity = 16843766; // 0x10103f6 field public static final int shadowColor = 16843105; // 0x1010161 field public static final int shadowDx = 16843106; // 0x1010162 field public static final int shadowDy = 16843107; // 0x1010163 @@ -958,11 +1088,13 @@ field public static final int showDividers = 16843561; // 0x1010329 field public static final int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb + field public static final int showText = 16843949; // 0x10104ad field public static final int showWeekNumber = 16843582; // 0x101033e field public static final int shownWeekCount = 16843585; // 0x1010341 field public static final int shrinkColumns = 16843082; // 0x101014a field public static final deprecated int singleLine = 16843101; // 0x101015d field public static final int singleUser = 16843711; // 0x10103bf + field public static final int slideEdge = 16843824; // 0x1010430 field public static final int smallIcon = 16843422; // 0x101029e field public static final int smallScreens = 16843396; // 0x1010284 field public static final int smoothScrollbar = 16843313; // 0x1010231 @@ -974,16 +1106,20 @@ field public static final int spinnerStyle = 16842881; // 0x1010081 field public static final int spinnersShown = 16843595; // 0x101034b field public static final int splitMotionEvents = 16843503; // 0x10102ef + field public static final int splitTrack = 16843852; // 0x101044c + field public static final int spotShadowAlpha = 16843967; // 0x10104bf field public static final int src = 16843033; // 0x1010119 field public static final int ssp = 16843747; // 0x10103e3 field public static final int sspPattern = 16843749; // 0x10103e5 field public static final int sspPrefix = 16843748; // 0x10103e4 field public static final int stackFromBottom = 16843005; // 0x10100fd + field public static final int stackViewStyle = 16843838; // 0x101043e field public static final int starStyle = 16842882; // 0x1010082 field public static final int startColor = 16843165; // 0x101019d field public static final int startDelay = 16843746; // 0x10103e2 field public static final int startOffset = 16843198; // 0x10101be field public static final deprecated int startYear = 16843132; // 0x101017c + field public static final int stateListAnimator = 16843848; // 0x1010448 field public static final int stateNotNeeded = 16842774; // 0x1010016 field public static final int state_above_anchor = 16842922; // 0x10100aa field public static final int state_accelerated = 16843547; // 0x101031b @@ -1008,18 +1144,28 @@ field public static final int state_single = 16842915; // 0x10100a3 field public static final int state_window_focused = 16842909; // 0x101009d field public static final int staticWallpaperPreview = 16843569; // 0x1010331 + field public static final int statusBarColor = 16843857; // 0x1010451 field public static final int stepSize = 16843078; // 0x1010146 field public static final int stopWithTask = 16843626; // 0x101036a field public static final int streamType = 16843273; // 0x1010209 field public static final int stretchColumns = 16843081; // 0x1010149 field public static final int stretchMode = 16843030; // 0x1010116 + field public static final int strokeAlpha = 16843979; // 0x10104cb + field public static final int strokeColor = 16843782; // 0x1010406 + field public static final int strokeLineCap = 16843787; // 0x101040b + field public static final int strokeLineJoin = 16843788; // 0x101040c + field public static final int strokeMiterLimit = 16843789; // 0x101040d + field public static final int strokeWidth = 16843783; // 0x1010407 + field public static final int submitBackground = 16843912; // 0x1010488 field public static final int subtitle = 16843473; // 0x10102d1 + field public static final int subtitleTextAppearance = 16843823; // 0x101042f field public static final int subtitleTextStyle = 16843513; // 0x10102f9 field public static final int subtypeExtraValue = 16843674; // 0x101039a field public static final int subtypeId = 16843713; // 0x10103c1 field public static final int subtypeLocale = 16843673; // 0x1010399 field public static final int suggestActionMsg = 16843228; // 0x10101dc field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd + field public static final int suggestionRowLayout = 16843910; // 0x1010486 field public static final int summary = 16843241; // 0x10101e9 field public static final int summaryColumn = 16843426; // 0x10102a2 field public static final int summaryOff = 16843248; // 0x10101f0 @@ -1030,6 +1176,7 @@ field public static final int switchMinWidth = 16843632; // 0x1010370 field public static final int switchPadding = 16843633; // 0x1010371 field public static final int switchPreferenceStyle = 16843629; // 0x101036d + field public static final int switchStyle = 16843839; // 0x101043f field public static final int switchTextAppearance = 16843630; // 0x101036e field public static final int switchTextOff = 16843628; // 0x101036c field public static final int switchTextOn = 16843627; // 0x101036b @@ -1043,6 +1190,7 @@ field public static final int targetClass = 16842799; // 0x101002f field public static final int targetDescriptions = 16843680; // 0x10103a0 field public static final int targetId = 16843740; // 0x10103dc + field public static final int targetName = 16843853; // 0x101044d field public static final int targetPackage = 16842785; // 0x1010021 field public static final int targetSdkVersion = 16843376; // 0x1010270 field public static final int taskAffinity = 16842770; // 0x1010012 @@ -1066,6 +1214,7 @@ field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043 field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301 field public static final int textAppearanceListItem = 16843678; // 0x101039e + field public static final int textAppearanceListItemSecondary = 16843826; // 0x1010432 field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f field public static final int textAppearanceMedium = 16842817; // 0x1010041 field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044 @@ -1122,34 +1271,55 @@ field public static final int thumb = 16843074; // 0x1010142 field public static final int thumbOffset = 16843075; // 0x1010143 field public static final int thumbTextPadding = 16843634; // 0x1010372 + field public static final int thumbTint = 16843889; // 0x1010471 + field public static final int thumbTintMode = 16843890; // 0x1010472 field public static final int thumbnail = 16843429; // 0x10102a5 field public static final int tileMode = 16843265; // 0x1010201 + field public static final int tileModeX = 16843895; // 0x1010477 + field public static final int tileModeY = 16843896; // 0x1010478 + field public static final int timePickerDialogTheme = 16843934; // 0x101049e + field public static final int timePickerMode = 16843956; // 0x10104b4 + field public static final int timePickerStyle = 16843933; // 0x101049d field public static final int timeZone = 16843724; // 0x10103cc field public static final int tint = 16843041; // 0x1010121 + field public static final int tintMode = 16843771; // 0x10103fb field public static final int title = 16843233; // 0x10101e1 field public static final int titleCondensed = 16843234; // 0x10101e2 + field public static final int titleTextAppearance = 16843822; // 0x101042e field public static final int titleTextStyle = 16843512; // 0x10102f8 field public static final int toAlpha = 16843211; // 0x10101cb field public static final int toDegrees = 16843188; // 0x10101b4 + field public static final int toId = 16843849; // 0x1010449 field public static final int toScene = 16843742; // 0x10103de field public static final int toXDelta = 16843207; // 0x10101c7 field public static final int toXScale = 16843203; // 0x10101c3 field public static final int toYDelta = 16843209; // 0x10101c9 field public static final int toYScale = 16843205; // 0x10101c5 + field public static final int toolbarStyle = 16843946; // 0x10104aa field public static final int top = 16843182; // 0x10101ae field public static final int topBright = 16842955; // 0x10100cb field public static final int topDark = 16842951; // 0x10100c7 field public static final int topLeftRadius = 16843177; // 0x10101a9 field public static final int topOffset = 16843352; // 0x1010258 field public static final int topRightRadius = 16843178; // 0x10101aa + field public static final int touchscreenBlocksFocus = 16843919; // 0x101048f field public static final int track = 16843631; // 0x101036f field public static final int transcriptMode = 16843008; // 0x1010100 field public static final int transformPivotX = 16843552; // 0x1010320 field public static final int transformPivotY = 16843553; // 0x1010321 field public static final int transition = 16843743; // 0x10103df + field public static final int transitionGroup = 16843777; // 0x1010401 + field public static final int transitionName = 16843776; // 0x1010400 field public static final int transitionOrdering = 16843744; // 0x10103e0 + field public static final int transitionVisibilityMode = 16843900; // 0x101047c + field public static final int translateX = 16843866; // 0x101045a + field public static final int translateY = 16843867; // 0x101045b field public static final int translationX = 16843554; // 0x1010322 field public static final int translationY = 16843555; // 0x1010323 + field public static final int translationZ = 16843770; // 0x10103fa + field public static final int trimPathEnd = 16843785; // 0x1010409 + field public static final int trimPathOffset = 16843786; // 0x101040a + field public static final int trimPathStart = 16843784; // 0x1010408 field public static final int type = 16843169; // 0x10101a1 field public static final int typeface = 16842902; // 0x1010096 field public static final int uiOptions = 16843672; // 0x1010398 @@ -1174,9 +1344,12 @@ field public static final int verticalGap = 16843328; // 0x1010240 field public static final int verticalScrollbarPosition = 16843572; // 0x1010334 field public static final int verticalSpacing = 16843029; // 0x1010115 + field public static final int viewportHeight = 16843779; // 0x1010403 + field public static final int viewportWidth = 16843778; // 0x1010402 field public static final int visibility = 16842972; // 0x10100dc field public static final int visible = 16843156; // 0x1010194 field public static final int vmSafeMode = 16843448; // 0x10102b8 + field public static final int voiceIcon = 16843908; // 0x1010484 field public static final int voiceLanguage = 16843349; // 0x1010255 field public static final int voiceLanguageModel = 16843347; // 0x1010253 field public static final int voiceMaxResults = 16843350; // 0x1010256 @@ -1202,14 +1375,24 @@ field public static final int windowActionBar = 16843469; // 0x10102cd field public static final int windowActionBarOverlay = 16843492; // 0x10102e4 field public static final int windowActionModeOverlay = 16843485; // 0x10102dd + field public static final int windowActivityTransitions = 16843981; // 0x10104cd + field public static final int windowAllowEnterTransitionOverlap = 16843836; // 0x101043c + field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b field public static final int windowAnimationStyle = 16842926; // 0x10100ae field public static final int windowBackground = 16842836; // 0x1010054 + field public static final int windowClipToOutline = 16843947; // 0x10104ab field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b field public static final int windowContentOverlay = 16842841; // 0x1010059 + field public static final int windowContentTransitionManager = 16843769; // 0x10103f9 + field public static final int windowContentTransitions = 16843768; // 0x10103f8 field public static final int windowDisablePreview = 16843298; // 0x1010222 + field public static final int windowDrawsSystemBarBackgrounds = 16843856; // 0x1010450 + field public static final int windowElevation = 16843920; // 0x1010490 field public static final int windowEnableSplitTouch = 16843543; // 0x1010317 field public static final int windowEnterAnimation = 16842932; // 0x10100b4 + field public static final int windowEnterTransition = 16843831; // 0x1010437 field public static final int windowExitAnimation = 16842933; // 0x10100b5 + field public static final int windowExitTransition = 16843832; // 0x1010438 field public static final int windowFrame = 16842837; // 0x1010055 field public static final int windowFullscreen = 16843277; // 0x101020d field public static final int windowHideAnimation = 16842935; // 0x10100b7 @@ -1220,6 +1403,13 @@ field public static final int windowNoDisplay = 16843294; // 0x101021e field public static final int windowNoTitle = 16842838; // 0x1010056 field public static final int windowOverscan = 16843727; // 0x10103cf + field public static final int windowReenterTransition = 16843951; // 0x10104af + field public static final int windowReturnTransition = 16843950; // 0x10104ae + field public static final int windowSharedElementEnterTransition = 16843833; // 0x1010439 + field public static final int windowSharedElementExitTransition = 16843834; // 0x101043a + field public static final int windowSharedElementReenterTransition = 16843953; // 0x10104b1 + field public static final int windowSharedElementReturnTransition = 16843952; // 0x10104b0 + field public static final int windowSharedElementsUseOverlay = 16843963; // 0x10104bb field public static final int windowShowAnimation = 16842934; // 0x10100b6 field public static final int windowShowWallpaper = 16843410; // 0x1010292 field public static final int windowSoftInputMode = 16843307; // 0x101022b @@ -1227,12 +1417,15 @@ field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c field public static final int windowTitleSize = 16842842; // 0x101005a field public static final int windowTitleStyle = 16842843; // 0x101005b + field public static final int windowTransitionBackgroundFadeDuration = 16843873; // 0x1010461 field public static final int windowTranslucentNavigation = 16843760; // 0x10103f0 field public static final int windowTranslucentStatus = 16843759; // 0x10103ef field public static final int writePermission = 16842760; // 0x1010008 field public static final int x = 16842924; // 0x10100ac field public static final int xlargeScreens = 16843455; // 0x10102bf field public static final int y = 16842925; // 0x10100ad + field public static final int yearListItemTextAppearance = 16843929; // 0x1010499 + field public static final int yearListSelectorColor = 16843930; // 0x101049a field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090 field public static final int zAdjustment = 16843201; // 0x10101c1 } @@ -1494,7 +1687,9 @@ field public static final int inputExtractEditText = 16908325; // 0x1020025 field public static final int keyboardView = 16908326; // 0x1020026 field public static final int list = 16908298; // 0x102000a + field public static final int mask = 16908334; // 0x102002e field public static final int message = 16908299; // 0x102000b + field public static final int navigationBarBackground = 16908336; // 0x1020030 field public static final int paste = 16908322; // 0x1020022 field public static final int primary = 16908300; // 0x102000c field public static final int progress = 16908301; // 0x102000d @@ -1503,6 +1698,7 @@ field public static final int selectTextMode = 16908333; // 0x102002d field public static final int selectedIcon = 16908302; // 0x102000e field public static final int startSelectingText = 16908328; // 0x1020028 + field public static final int statusBarBackground = 16908335; // 0x102002f field public static final int stopSelectingText = 16908329; // 0x1020029 field public static final int summary = 16908304; // 0x1020010 field public static final int switchInputMethod = 16908324; // 0x1020024 @@ -1537,7 +1733,10 @@ field public static final int decelerate_cubic = 17563651; // 0x10c0003 field public static final int decelerate_quad = 17563649; // 0x10c0001 field public static final int decelerate_quint = 17563653; // 0x10c0005 + field public static final int fast_out_linear_in = 17563663; // 0x10c000f + field public static final int fast_out_slow_in = 17563661; // 0x10c000d field public static final int linear = 17563659; // 0x10c000b + field public static final int linear_out_slow_in = 17563662; // 0x10c000e field public static final int overshoot = 17563656; // 0x10c0008 } @@ -1656,13 +1855,13 @@ field public static final int TextAppearance_DeviceDefault_Widget = 16974265; // 0x10301b9 field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Menu = 16974286; // 0x10301ce field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle = 16974279; // 0x10301c7 - field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb + field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title = 16974278; // 0x10301c6 - field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca + field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle = 16974281; // 0x10301c9 - field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd + field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title = 16974280; // 0x10301c8 - field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc + field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc field public static final int TextAppearance_DeviceDefault_Widget_Button = 16974266; // 0x10301ba field public static final int TextAppearance_DeviceDefault_Widget_DropDownHint = 16974271; // 0x10301bf field public static final int TextAppearance_DeviceDefault_Widget_DropDownItem = 16974272; // 0x10301c0 @@ -1714,6 +1913,60 @@ field public static final int TextAppearance_Inverse = 16973887; // 0x103003f field public static final int TextAppearance_Large = 16973890; // 0x1030042 field public static final int TextAppearance_Large_Inverse = 16973891; // 0x1030043 + field public static final int TextAppearance_Material = 16974317; // 0x10301ed + field public static final int TextAppearance_Material_Body1 = 16974320; // 0x10301f0 + field public static final int TextAppearance_Material_Body2 = 16974319; // 0x10301ef + field public static final int TextAppearance_Material_Button = 16974318; // 0x10301ee + field public static final int TextAppearance_Material_Caption = 16974321; // 0x10301f1 + field public static final int TextAppearance_Material_DialogWindowTitle = 16974322; // 0x10301f2 + field public static final int TextAppearance_Material_Display1 = 16974326; // 0x10301f6 + field public static final int TextAppearance_Material_Display2 = 16974325; // 0x10301f5 + field public static final int TextAppearance_Material_Display3 = 16974324; // 0x10301f4 + field public static final int TextAppearance_Material_Display4 = 16974323; // 0x10301f3 + field public static final int TextAppearance_Material_Headline = 16974327; // 0x10301f7 + field public static final int TextAppearance_Material_Inverse = 16974328; // 0x10301f8 + field public static final int TextAppearance_Material_Large = 16974329; // 0x10301f9 + field public static final int TextAppearance_Material_Large_Inverse = 16974330; // 0x10301fa + field public static final int TextAppearance_Material_Medium = 16974331; // 0x10301fb + field public static final int TextAppearance_Material_Medium_Inverse = 16974332; // 0x10301fc + field public static final int TextAppearance_Material_Menu = 16974333; // 0x10301fd + field public static final int TextAppearance_Material_Notification = 16974334; // 0x10301fe + field public static final int TextAppearance_Material_Notification_Emphasis = 16974335; // 0x10301ff + field public static final int TextAppearance_Material_Notification_Info = 16974336; // 0x1030200 + field public static final int TextAppearance_Material_Notification_Line2 = 16974337; // 0x1030201 + field public static final int TextAppearance_Material_Notification_Time = 16974338; // 0x1030202 + field public static final int TextAppearance_Material_Notification_Title = 16974339; // 0x1030203 + field public static final int TextAppearance_Material_SearchResult_Subtitle = 16974340; // 0x1030204 + field public static final int TextAppearance_Material_SearchResult_Title = 16974341; // 0x1030205 + field public static final int TextAppearance_Material_Small = 16974342; // 0x1030206 + field public static final int TextAppearance_Material_Small_Inverse = 16974343; // 0x1030207 + field public static final int TextAppearance_Material_Subhead = 16974344; // 0x1030208 + field public static final int TextAppearance_Material_Title = 16974345; // 0x1030209 + field public static final int TextAppearance_Material_Widget = 16974347; // 0x103020b + field public static final int TextAppearance_Material_Widget_ActionBar_Menu = 16974348; // 0x103020c + field public static final int TextAppearance_Material_Widget_ActionBar_Subtitle = 16974349; // 0x103020d + field public static final int TextAppearance_Material_Widget_ActionBar_Subtitle_Inverse = 16974350; // 0x103020e + field public static final int TextAppearance_Material_Widget_ActionBar_Title = 16974351; // 0x103020f + field public static final int TextAppearance_Material_Widget_ActionBar_Title_Inverse = 16974352; // 0x1030210 + field public static final int TextAppearance_Material_Widget_ActionMode_Subtitle = 16974353; // 0x1030211 + field public static final int TextAppearance_Material_Widget_ActionMode_Subtitle_Inverse = 16974354; // 0x1030212 + field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974355; // 0x1030213 + field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974356; // 0x1030214 + field public static final int TextAppearance_Material_Widget_Button = 16974357; // 0x1030215 + field public static final int TextAppearance_Material_Widget_DropDownHint = 16974358; // 0x1030216 + field public static final int TextAppearance_Material_Widget_DropDownItem = 16974359; // 0x1030217 + field public static final int TextAppearance_Material_Widget_EditText = 16974360; // 0x1030218 + field public static final int TextAppearance_Material_Widget_IconMenu_Item = 16974361; // 0x1030219 + field public static final int TextAppearance_Material_Widget_PopupMenu = 16974362; // 0x103021a + field public static final int TextAppearance_Material_Widget_PopupMenu_Large = 16974363; // 0x103021b + field public static final int TextAppearance_Material_Widget_PopupMenu_Small = 16974364; // 0x103021c + field public static final int TextAppearance_Material_Widget_TabWidget = 16974365; // 0x103021d + field public static final int TextAppearance_Material_Widget_TextView = 16974366; // 0x103021e + field public static final int TextAppearance_Material_Widget_TextView_PopupMenu = 16974367; // 0x103021f + field public static final int TextAppearance_Material_Widget_TextView_SpinnerItem = 16974368; // 0x1030220 + field public static final int TextAppearance_Material_Widget_Toolbar_Subtitle = 16974369; // 0x1030221 + field public static final int TextAppearance_Material_Widget_Toolbar_Title = 16974370; // 0x1030222 + field public static final int TextAppearance_Material_WindowTitle = 16974346; // 0x103020a field public static final int TextAppearance_Medium = 16973892; // 0x1030044 field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045 field public static final int TextAppearance_Small = 16973894; // 0x1030046 @@ -1739,6 +1992,12 @@ field public static final int TextAppearance_Widget_TextView_SpinnerItem = 16973906; // 0x1030052 field public static final int TextAppearance_WindowTitle = 16973907; // 0x1030053 field public static final int Theme = 16973829; // 0x1030005 + field public static final int ThemeOverlay = 16974407; // 0x1030247 + field public static final int ThemeOverlay_Material = 16974408; // 0x1030248 + field public static final int ThemeOverlay_Material_ActionBar = 16974409; // 0x1030249 + field public static final int ThemeOverlay_Material_Dark = 16974411; // 0x103024b + field public static final int ThemeOverlay_Material_Dark_ActionBar = 16974412; // 0x103024c + field public static final int ThemeOverlay_Material_Light = 16974410; // 0x103024a field public static final int Theme_Black = 16973832; // 0x1030008 field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009 field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a @@ -1768,6 +2027,7 @@ field public static final int Theme_DeviceDefault_NoActionBar_Overscan = 16974303; // 0x10301df field public static final int Theme_DeviceDefault_NoActionBar_TranslucentDecor = 16974307; // 0x10301e3 field public static final int Theme_DeviceDefault_Panel = 16974138; // 0x103013a + field public static final int Theme_DeviceDefault_Settings = 16974371; // 0x1030223 field public static final int Theme_DeviceDefault_Wallpaper = 16974140; // 0x103013c field public static final int Theme_DeviceDefault_Wallpaper_NoTitleBar = 16974141; // 0x103013d field public static final int Theme_Dialog = 16973835; // 0x103000b @@ -1805,6 +2065,41 @@ field public static final int Theme_Light_NoTitleBar_Fullscreen = 16973838; // 0x103000e field public static final int Theme_Light_Panel = 16973914; // 0x103005a field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062 + field public static final int Theme_Material = 16974372; // 0x1030224 + field public static final int Theme_Material_Dialog = 16974373; // 0x1030225 + field public static final int Theme_Material_DialogWhenLarge = 16974379; // 0x103022b + field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974380; // 0x103022c + field public static final int Theme_Material_Dialog_Alert = 16974374; // 0x1030226 + field public static final int Theme_Material_Dialog_MinWidth = 16974375; // 0x1030227 + field public static final int Theme_Material_Dialog_NoActionBar = 16974376; // 0x1030228 + field public static final int Theme_Material_Dialog_NoActionBar_MinWidth = 16974377; // 0x1030229 + field public static final int Theme_Material_Dialog_Presentation = 16974378; // 0x103022a + field public static final int Theme_Material_InputMethod = 16974381; // 0x103022d + field public static final int Theme_Material_Light = 16974391; // 0x1030237 + field public static final int Theme_Material_Light_DarkActionBar = 16974392; // 0x1030238 + field public static final int Theme_Material_Light_Dialog = 16974393; // 0x1030239 + field public static final int Theme_Material_Light_DialogWhenLarge = 16974399; // 0x103023f + field public static final int Theme_Material_Light_DialogWhenLarge_NoActionBar = 16974400; // 0x1030240 + field public static final int Theme_Material_Light_Dialog_Alert = 16974394; // 0x103023a + field public static final int Theme_Material_Light_Dialog_MinWidth = 16974395; // 0x103023b + field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974396; // 0x103023c + field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974397; // 0x103023d + field public static final int Theme_Material_Light_Dialog_Presentation = 16974398; // 0x103023e + field public static final int Theme_Material_Light_NoActionBar = 16974401; // 0x1030241 + field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974402; // 0x1030242 + field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974403; // 0x1030243 + field public static final int Theme_Material_Light_NoActionBar_TranslucentDecor = 16974404; // 0x1030244 + field public static final int Theme_Material_Light_Panel = 16974405; // 0x1030245 + field public static final int Theme_Material_Light_Voice = 16974406; // 0x1030246 + field public static final int Theme_Material_NoActionBar = 16974382; // 0x103022e + field public static final int Theme_Material_NoActionBar_Fullscreen = 16974383; // 0x103022f + field public static final int Theme_Material_NoActionBar_Overscan = 16974384; // 0x1030230 + field public static final int Theme_Material_NoActionBar_TranslucentDecor = 16974385; // 0x1030231 + field public static final int Theme_Material_Panel = 16974386; // 0x1030232 + field public static final int Theme_Material_Settings = 16974387; // 0x1030233 + field public static final int Theme_Material_Voice = 16974388; // 0x1030234 + field public static final int Theme_Material_Wallpaper = 16974389; // 0x1030235 + field public static final int Theme_Material_Wallpaper_NoTitleBar = 16974390; // 0x1030236 field public static final int Theme_NoDisplay = 16973909; // 0x1030055 field public static final int Theme_NoTitleBar = 16973830; // 0x1030006 field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007 @@ -1866,24 +2161,25 @@ field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162 field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b + field public static final int Widget_DeviceDefault_FastScroll = 16974313; // 0x10301e9 field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d field public static final int Widget_DeviceDefault_Light = 16974196; // 0x1030174 field public static final int Widget_DeviceDefault_Light_ActionBar = 16974243; // 0x10301a3 field public static final int Widget_DeviceDefault_Light_ActionBar_Solid = 16974247; // 0x10301a7 - field public static final int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8 + field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8 field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar = 16974246; // 0x10301a6 - field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9 + field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9 field public static final int Widget_DeviceDefault_Light_ActionBar_TabText = 16974245; // 0x10301a5 - field public static final int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab + field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab field public static final int Widget_DeviceDefault_Light_ActionBar_TabView = 16974244; // 0x10301a4 - field public static final int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa + field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa field public static final int Widget_DeviceDefault_Light_ActionButton = 16974239; // 0x103019f field public static final int Widget_DeviceDefault_Light_ActionButton_CloseMode = 16974242; // 0x10301a2 field public static final int Widget_DeviceDefault_Light_ActionButton_Overflow = 16974240; // 0x10301a0 field public static final int Widget_DeviceDefault_Light_ActionMode = 16974241; // 0x10301a1 - field public static final int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac + field public static final deprecated int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac field public static final int Widget_DeviceDefault_Light_AutoCompleteTextView = 16974203; // 0x103017b field public static final int Widget_DeviceDefault_Light_Button = 16974197; // 0x1030175 field public static final int Widget_DeviceDefault_Light_Button_Borderless_Small = 16974201; // 0x1030179 @@ -1899,6 +2195,7 @@ field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199 field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f + field public static final int Widget_DeviceDefault_Light_FastScroll = 16974315; // 0x10301eb field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180 field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192 field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181 @@ -1922,6 +2219,7 @@ field public static final int Widget_DeviceDefault_Light_ScrollView = 16974225; // 0x1030191 field public static final int Widget_DeviceDefault_Light_SeekBar = 16974220; // 0x103018c field public static final int Widget_DeviceDefault_Light_Spinner = 16974227; // 0x1030193 + field public static final int Widget_DeviceDefault_Light_StackView = 16974316; // 0x10301ec field public static final int Widget_DeviceDefault_Light_Tab = 16974237; // 0x103019d field public static final int Widget_DeviceDefault_Light_TabWidget = 16974229; // 0x1030195 field public static final int Widget_DeviceDefault_Light_TextView = 16974202; // 0x103017a @@ -1945,6 +2243,7 @@ field public static final int Widget_DeviceDefault_ScrollView = 16974170; // 0x103015a field public static final int Widget_DeviceDefault_SeekBar = 16974165; // 0x1030155 field public static final int Widget_DeviceDefault_Spinner = 16974172; // 0x103015c + field public static final int Widget_DeviceDefault_StackView = 16974314; // 0x10301ea field public static final int Widget_DeviceDefault_Tab = 16974189; // 0x103016d field public static final int Widget_DeviceDefault_TabWidget = 16974174; // 0x103015e field public static final int Widget_DeviceDefault_TextView = 16974150; // 0x1030146 @@ -1955,6 +2254,7 @@ field public static final int Widget_DropDownItem_Spinner = 16973868; // 0x103002c field public static final int Widget_EditText = 16973859; // 0x1030023 field public static final int Widget_ExpandableListView = 16973860; // 0x1030024 + field public static final int Widget_FastScroll = 16974309; // 0x10301e5 field public static final int Widget_FragmentBreadCrumbs = 16973961; // 0x1030089 field public static final int Widget_Gallery = 16973877; // 0x1030035 field public static final int Widget_GridView = 16973874; // 0x1030032 @@ -2079,6 +2379,137 @@ field public static final int Widget_ListView_DropDown = 16973872; // 0x1030030 field public static final int Widget_ListView_Menu = 16973873; // 0x1030031 field public static final int Widget_ListView_White = 16973871; // 0x103002f + field public static final int Widget_Material = 16974413; // 0x103024d + field public static final int Widget_Material_ActionBar = 16974414; // 0x103024e + field public static final int Widget_Material_ActionBar_Solid = 16974415; // 0x103024f + field public static final int Widget_Material_ActionBar_TabBar = 16974416; // 0x1030250 + field public static final int Widget_Material_ActionBar_TabText = 16974417; // 0x1030251 + field public static final int Widget_Material_ActionBar_TabView = 16974418; // 0x1030252 + field public static final int Widget_Material_ActionButton = 16974419; // 0x1030253 + field public static final int Widget_Material_ActionButton_CloseMode = 16974420; // 0x1030254 + field public static final int Widget_Material_ActionButton_Overflow = 16974421; // 0x1030255 + field public static final int Widget_Material_ActionMode = 16974422; // 0x1030256 + field public static final int Widget_Material_AutoCompleteTextView = 16974423; // 0x1030257 + field public static final int Widget_Material_Button = 16974424; // 0x1030258 + field public static final int Widget_Material_ButtonBar = 16974431; // 0x103025f + field public static final int Widget_Material_ButtonBar_AlertDialog = 16974432; // 0x1030260 + field public static final int Widget_Material_Button_Borderless = 16974425; // 0x1030259 + field public static final int Widget_Material_Button_Borderless_Colored = 16974426; // 0x103025a + field public static final int Widget_Material_Button_Borderless_Small = 16974427; // 0x103025b + field public static final int Widget_Material_Button_Inset = 16974428; // 0x103025c + field public static final int Widget_Material_Button_Small = 16974429; // 0x103025d + field public static final int Widget_Material_Button_Toggle = 16974430; // 0x103025e + field public static final int Widget_Material_CalendarView = 16974433; // 0x1030261 + field public static final int Widget_Material_CheckedTextView = 16974434; // 0x1030262 + field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263 + field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264 + field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265 + field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266 + field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267 + field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268 + field public static final int Widget_Material_EditText = 16974441; // 0x1030269 + field public static final int Widget_Material_ExpandableListView = 16974442; // 0x103026a + field public static final int Widget_Material_FastScroll = 16974443; // 0x103026b + field public static final int Widget_Material_GridView = 16974444; // 0x103026c + field public static final int Widget_Material_HorizontalScrollView = 16974445; // 0x103026d + field public static final int Widget_Material_ImageButton = 16974446; // 0x103026e + field public static final int Widget_Material_Light = 16974478; // 0x103028e + field public static final int Widget_Material_Light_ActionBar = 16974479; // 0x103028f + field public static final int Widget_Material_Light_ActionBar_Solid = 16974480; // 0x1030290 + field public static final int Widget_Material_Light_ActionBar_TabBar = 16974481; // 0x1030291 + field public static final int Widget_Material_Light_ActionBar_TabText = 16974482; // 0x1030292 + field public static final int Widget_Material_Light_ActionBar_TabView = 16974483; // 0x1030293 + field public static final int Widget_Material_Light_ActionButton = 16974484; // 0x1030294 + field public static final int Widget_Material_Light_ActionButton_CloseMode = 16974485; // 0x1030295 + field public static final int Widget_Material_Light_ActionButton_Overflow = 16974486; // 0x1030296 + field public static final int Widget_Material_Light_ActionMode = 16974487; // 0x1030297 + field public static final int Widget_Material_Light_AutoCompleteTextView = 16974488; // 0x1030298 + field public static final int Widget_Material_Light_Button = 16974489; // 0x1030299 + field public static final int Widget_Material_Light_ButtonBar = 16974496; // 0x10302a0 + field public static final int Widget_Material_Light_ButtonBar_AlertDialog = 16974497; // 0x10302a1 + field public static final int Widget_Material_Light_Button_Borderless = 16974490; // 0x103029a + field public static final int Widget_Material_Light_Button_Borderless_Colored = 16974491; // 0x103029b + field public static final int Widget_Material_Light_Button_Borderless_Small = 16974492; // 0x103029c + field public static final int Widget_Material_Light_Button_Inset = 16974493; // 0x103029d + field public static final int Widget_Material_Light_Button_Small = 16974494; // 0x103029e + field public static final int Widget_Material_Light_Button_Toggle = 16974495; // 0x103029f + field public static final int Widget_Material_Light_CalendarView = 16974498; // 0x10302a2 + field public static final int Widget_Material_Light_CheckedTextView = 16974499; // 0x10302a3 + field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4 + field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5 + field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6 + field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7 + field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8 + field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9 + field public static final int Widget_Material_Light_EditText = 16974506; // 0x10302aa + field public static final int Widget_Material_Light_ExpandableListView = 16974507; // 0x10302ab + field public static final int Widget_Material_Light_FastScroll = 16974508; // 0x10302ac + field public static final int Widget_Material_Light_GridView = 16974509; // 0x10302ad + field public static final int Widget_Material_Light_HorizontalScrollView = 16974510; // 0x10302ae + field public static final int Widget_Material_Light_ImageButton = 16974511; // 0x10302af + field public static final int Widget_Material_Light_ListPopupWindow = 16974512; // 0x10302b0 + field public static final int Widget_Material_Light_ListView = 16974513; // 0x10302b1 + field public static final int Widget_Material_Light_ListView_DropDown = 16974514; // 0x10302b2 + field public static final int Widget_Material_Light_MediaRouteButton = 16974515; // 0x10302b3 + field public static final int Widget_Material_Light_PopupMenu = 16974516; // 0x10302b4 + field public static final int Widget_Material_Light_PopupMenu_Overflow = 16974517; // 0x10302b5 + field public static final int Widget_Material_Light_PopupWindow = 16974518; // 0x10302b6 + field public static final int Widget_Material_Light_ProgressBar = 16974519; // 0x10302b7 + field public static final int Widget_Material_Light_ProgressBar_Horizontal = 16974520; // 0x10302b8 + field public static final int Widget_Material_Light_ProgressBar_Inverse = 16974521; // 0x10302b9 + field public static final int Widget_Material_Light_ProgressBar_Large = 16974522; // 0x10302ba + field public static final int Widget_Material_Light_ProgressBar_Large_Inverse = 16974523; // 0x10302bb + field public static final int Widget_Material_Light_ProgressBar_Small = 16974524; // 0x10302bc + field public static final int Widget_Material_Light_ProgressBar_Small_Inverse = 16974525; // 0x10302bd + field public static final int Widget_Material_Light_ProgressBar_Small_Title = 16974526; // 0x10302be + field public static final int Widget_Material_Light_RatingBar = 16974527; // 0x10302bf + field public static final int Widget_Material_Light_RatingBar_Indicator = 16974528; // 0x10302c0 + field public static final int Widget_Material_Light_RatingBar_Small = 16974529; // 0x10302c1 + field public static final int Widget_Material_Light_ScrollView = 16974530; // 0x10302c2 + field public static final int Widget_Material_Light_SearchView = 16974531; // 0x10302c3 + field public static final int Widget_Material_Light_SeekBar = 16974532; // 0x10302c4 + field public static final int Widget_Material_Light_SegmentedButton = 16974533; // 0x10302c5 + field public static final int Widget_Material_Light_Spinner = 16974535; // 0x10302c7 + field public static final int Widget_Material_Light_Spinner_Underlined = 16974536; // 0x10302c8 + field public static final int Widget_Material_Light_StackView = 16974534; // 0x10302c6 + field public static final int Widget_Material_Light_Tab = 16974537; // 0x10302c9 + field public static final int Widget_Material_Light_TabWidget = 16974538; // 0x10302ca + field public static final int Widget_Material_Light_TextView = 16974539; // 0x10302cb + field public static final int Widget_Material_Light_TextView_SpinnerItem = 16974540; // 0x10302cc + field public static final int Widget_Material_Light_TimePicker = 16974541; // 0x10302cd + field public static final int Widget_Material_Light_WebTextView = 16974542; // 0x10302ce + field public static final int Widget_Material_Light_WebView = 16974543; // 0x10302cf + field public static final int Widget_Material_ListPopupWindow = 16974447; // 0x103026f + field public static final int Widget_Material_ListView = 16974448; // 0x1030270 + field public static final int Widget_Material_ListView_DropDown = 16974449; // 0x1030271 + field public static final int Widget_Material_MediaRouteButton = 16974450; // 0x1030272 + field public static final int Widget_Material_PopupMenu = 16974451; // 0x1030273 + field public static final int Widget_Material_PopupMenu_Overflow = 16974452; // 0x1030274 + field public static final int Widget_Material_PopupWindow = 16974453; // 0x1030275 + field public static final int Widget_Material_ProgressBar = 16974454; // 0x1030276 + field public static final int Widget_Material_ProgressBar_Horizontal = 16974455; // 0x1030277 + field public static final int Widget_Material_ProgressBar_Large = 16974456; // 0x1030278 + field public static final int Widget_Material_ProgressBar_Small = 16974457; // 0x1030279 + field public static final int Widget_Material_ProgressBar_Small_Title = 16974458; // 0x103027a + field public static final int Widget_Material_RatingBar = 16974459; // 0x103027b + field public static final int Widget_Material_RatingBar_Indicator = 16974460; // 0x103027c + field public static final int Widget_Material_RatingBar_Small = 16974461; // 0x103027d + field public static final int Widget_Material_ScrollView = 16974462; // 0x103027e + field public static final int Widget_Material_SearchView = 16974463; // 0x103027f + field public static final int Widget_Material_SeekBar = 16974464; // 0x1030280 + field public static final int Widget_Material_SegmentedButton = 16974465; // 0x1030281 + field public static final int Widget_Material_Spinner = 16974467; // 0x1030283 + field public static final int Widget_Material_Spinner_Underlined = 16974468; // 0x1030284 + field public static final int Widget_Material_StackView = 16974466; // 0x1030282 + field public static final int Widget_Material_Tab = 16974469; // 0x1030285 + field public static final int Widget_Material_TabWidget = 16974470; // 0x1030286 + field public static final int Widget_Material_TextView = 16974471; // 0x1030287 + field public static final int Widget_Material_TextView_SpinnerItem = 16974472; // 0x1030288 + field public static final int Widget_Material_TimePicker = 16974473; // 0x1030289 + field public static final int Widget_Material_Toolbar = 16974474; // 0x103028a + field public static final int Widget_Material_Toolbar_Button_Navigation = 16974475; // 0x103028b + field public static final int Widget_Material_WebTextView = 16974476; // 0x103028c + field public static final int Widget_Material_WebView = 16974477; // 0x103028d field public static final int Widget_PopupMenu = 16973958; // 0x1030086 field public static final int Widget_PopupWindow = 16973878; // 0x1030036 field public static final int Widget_ProgressBar = 16973852; // 0x103001c @@ -2093,13 +2524,28 @@ field public static final int Widget_SeekBar = 16973856; // 0x1030020 field public static final int Widget_Spinner = 16973864; // 0x1030028 field public static final int Widget_Spinner_DropDown = 16973955; // 0x1030083 + field public static final int Widget_StackView = 16974310; // 0x10301e6 field public static final int Widget_TabWidget = 16973876; // 0x1030034 field public static final int Widget_TextView = 16973858; // 0x1030022 field public static final int Widget_TextView_PopupMenu = 16973865; // 0x1030029 field public static final int Widget_TextView_SpinnerItem = 16973866; // 0x103002a + field public static final int Widget_Toolbar = 16974311; // 0x10301e7 + field public static final int Widget_Toolbar_Button_Navigation = 16974312; // 0x10301e8 field public static final int Widget_WebView = 16973875; // 0x1030033 } + public static final class R.transition { + ctor public R.transition(); + field public static final int explode = 17760259; // 0x10f0003 + field public static final int fade = 17760258; // 0x10f0002 + field public static final int move = 17760257; // 0x10f0001 + field public static final int no_transition = 17760256; // 0x10f0000 + field public static final int slide_bottom = 17760260; // 0x10f0004 + field public static final int slide_left = 17760263; // 0x10f0007 + field public static final int slide_right = 17760262; // 0x10f0006 + field public static final int slide_top = 17760261; // 0x10f0005 + } + public static final class R.xml { ctor public R.xml(); } @@ -2110,8 +2556,10 @@ public abstract class AccessibilityService extends android.app.Service { ctor public AccessibilityService(); + method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow(); method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); + method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows(); method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent); method public final android.os.IBinder onBind(android.content.Intent); method protected boolean onGesture(int); @@ -2139,6 +2587,7 @@ field public static final int GLOBAL_ACTION_BACK = 1; // 0x1 field public static final int GLOBAL_ACTION_HOME = 2; // 0x2 field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4 + field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6 field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5 field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3 field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService"; @@ -2177,6 +2626,7 @@ field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8 field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20 field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4 + field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40 field public int eventTypes; field public int feedbackType; field public int flags; @@ -2247,6 +2697,7 @@ method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes(); method public java.lang.String getPassword(android.accounts.Account); + method public java.lang.String getPreviousName(android.accounts.Account); method public java.lang.String getUserData(android.accounts.Account, java.lang.String); method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void invalidateAuthToken(java.lang.String, java.lang.String); @@ -2254,6 +2705,7 @@ method public java.lang.String peekAuthToken(android.accounts.Account, java.lang.String); method public android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener); + method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler); method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String); method public void setPassword(android.accounts.Account, java.lang.String); method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String); @@ -2397,6 +2849,7 @@ public class AnimatorInflater { ctor public AnimatorInflater(); method public static android.animation.Animator loadAnimator(android.content.Context, int) throws android.content.res.Resources.NotFoundException; + method public static android.animation.StateListAnimator loadStateListAnimator(android.content.Context, int) throws android.content.res.Resources.NotFoundException; } public abstract class AnimatorListenerAdapter implements android.animation.Animator.AnimatorListener android.animation.Animator.AnimatorPauseListener { @@ -2437,11 +2890,29 @@ method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object); } + public abstract class BidirectionalTypeConverter extends android.animation.TypeConverter { + ctor public BidirectionalTypeConverter(java.lang.Class<T>, java.lang.Class<V>); + method public abstract T convertBack(V); + method public android.animation.BidirectionalTypeConverter<V, T> invert(); + } + + public class FloatArrayEvaluator implements android.animation.TypeEvaluator { + ctor public FloatArrayEvaluator(); + ctor public FloatArrayEvaluator(float[]); + method public float[] evaluate(float, float[], float[]); + } + public class FloatEvaluator implements android.animation.TypeEvaluator { ctor public FloatEvaluator(); method public java.lang.Float evaluate(float, java.lang.Number, java.lang.Number); } + public class IntArrayEvaluator implements android.animation.TypeEvaluator { + ctor public IntArrayEvaluator(); + ctor public IntArrayEvaluator(int[]); + method public int[] evaluate(float, int[], int[]); + } + public class IntEvaluator implements android.animation.TypeEvaluator { ctor public IntEvaluator(); method public java.lang.Integer evaluate(float, java.lang.Integer, java.lang.Integer); @@ -2510,18 +2981,39 @@ ctor public ObjectAnimator(); method public java.lang.String getPropertyName(); method public java.lang.Object getTarget(); + method public static android.animation.ObjectAnimator ofArgb(java.lang.Object, java.lang.String, int...); + method public static android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...); method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...); + method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path); method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...); + method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path); method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...); + method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path); method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...); + method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path); + method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, float[][]); + method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.graphics.Path); + method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...); + method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, int[][]); + method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.graphics.Path); + method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...); method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...); + method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path); method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...); + method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...); + method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path); method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...); method public void setAutoCancel(boolean); method public void setProperty(android.util.Property); method public void setPropertyName(java.lang.String); } + public class PointFEvaluator implements android.animation.TypeEvaluator { + ctor public PointFEvaluator(); + ctor public PointFEvaluator(android.graphics.PointF); + method public android.graphics.PointF evaluate(float, android.graphics.PointF, android.graphics.PointF); + } + public class PropertyValuesHolder implements java.lang.Cloneable { method public android.animation.PropertyValuesHolder clone(); method public java.lang.String getPropertyName(); @@ -2531,8 +3023,20 @@ method public static android.animation.PropertyValuesHolder ofInt(android.util.Property<?, java.lang.Integer>, int...); method public static android.animation.PropertyValuesHolder ofKeyframe(java.lang.String, android.animation.Keyframe...); method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...); + method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, float[][]); + method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.graphics.Path); + method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...); + method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...); + method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, int[][]); + method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.graphics.Path); + method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...); + method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...); method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...); + method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path); method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...); + method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...); + method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path); + method public void setConverter(android.animation.TypeConverter); method public void setEvaluator(android.animation.TypeEvaluator); method public void setFloatValues(float...); method public void setIntValues(int...); @@ -2544,9 +3048,16 @@ public class RectEvaluator implements android.animation.TypeEvaluator { ctor public RectEvaluator(); + ctor public RectEvaluator(android.graphics.Rect); method public android.graphics.Rect evaluate(float, android.graphics.Rect, android.graphics.Rect); } + public class StateListAnimator { + ctor public StateListAnimator(); + method public void addState(int[], android.animation.Animator); + method public void jumpToCurrentState(); + } + public class TimeAnimator extends android.animation.ValueAnimator { ctor public TimeAnimator(); method public void setTimeListener(android.animation.TimeAnimator.TimeListener); @@ -2560,6 +3071,11 @@ method public abstract float getInterpolation(float); } + public abstract class TypeConverter { + ctor public TypeConverter(java.lang.Class<T>, java.lang.Class<V>); + method public abstract V convert(T); + } + public abstract interface TypeEvaluator { method public abstract T evaluate(float, T, T); } @@ -2578,6 +3094,7 @@ method public long getStartDelay(); method public android.animation.PropertyValuesHolder[] getValues(); method public boolean isRunning(); + method public static android.animation.ValueAnimator ofArgb(int...); method public static android.animation.ValueAnimator ofFloat(float...); method public static android.animation.ValueAnimator ofInt(int...); method public static android.animation.ValueAnimator ofObject(android.animation.TypeEvaluator, java.lang.Object...); @@ -2623,30 +3140,33 @@ public abstract class ActionBar { ctor public ActionBar(); method public abstract void addOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener); - method public abstract void addTab(android.app.ActionBar.Tab); - method public abstract void addTab(android.app.ActionBar.Tab, boolean); - method public abstract void addTab(android.app.ActionBar.Tab, int); - method public abstract void addTab(android.app.ActionBar.Tab, int, boolean); + method public abstract deprecated void addTab(android.app.ActionBar.Tab); + method public abstract deprecated void addTab(android.app.ActionBar.Tab, boolean); + method public abstract deprecated void addTab(android.app.ActionBar.Tab, int); + method public abstract deprecated void addTab(android.app.ActionBar.Tab, int, boolean); method public abstract android.view.View getCustomView(); method public abstract int getDisplayOptions(); + method public float getElevation(); method public abstract int getHeight(); - method public abstract int getNavigationItemCount(); - method public abstract int getNavigationMode(); - method public abstract int getSelectedNavigationIndex(); - method public abstract android.app.ActionBar.Tab getSelectedTab(); + method public int getHideOffset(); + method public abstract deprecated int getNavigationItemCount(); + method public abstract deprecated int getNavigationMode(); + method public abstract deprecated int getSelectedNavigationIndex(); + method public abstract deprecated android.app.ActionBar.Tab getSelectedTab(); method public abstract java.lang.CharSequence getSubtitle(); - method public abstract android.app.ActionBar.Tab getTabAt(int); - method public abstract int getTabCount(); + method public abstract deprecated android.app.ActionBar.Tab getTabAt(int); + method public abstract deprecated int getTabCount(); method public android.content.Context getThemedContext(); method public abstract java.lang.CharSequence getTitle(); method public abstract void hide(); + method public boolean isHideOnContentScrollEnabled(); method public abstract boolean isShowing(); - method public abstract android.app.ActionBar.Tab newTab(); - method public abstract void removeAllTabs(); + method public abstract deprecated android.app.ActionBar.Tab newTab(); + method public abstract deprecated void removeAllTabs(); method public abstract void removeOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener); - method public abstract void removeTab(android.app.ActionBar.Tab); - method public abstract void removeTabAt(int); - method public abstract void selectTab(android.app.ActionBar.Tab); + method public abstract deprecated void removeTab(android.app.ActionBar.Tab); + method public abstract deprecated void removeTabAt(int); + method public abstract deprecated void selectTab(android.app.ActionBar.Tab); method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable); method public abstract void setCustomView(android.view.View); method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams); @@ -2658,6 +3178,9 @@ method public abstract void setDisplayShowHomeEnabled(boolean); method public abstract void setDisplayShowTitleEnabled(boolean); method public abstract void setDisplayUseLogoEnabled(boolean); + method public void setElevation(float); + method public void setHideOffset(int); + method public void setHideOnContentScrollEnabled(boolean); method public void setHomeActionContentDescription(java.lang.CharSequence); method public void setHomeActionContentDescription(int); method public void setHomeAsUpIndicator(android.graphics.drawable.Drawable); @@ -2665,11 +3188,11 @@ method public void setHomeButtonEnabled(boolean); method public abstract void setIcon(int); method public abstract void setIcon(android.graphics.drawable.Drawable); - method public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener); + method public abstract deprecated void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener); method public abstract void setLogo(int); method public abstract void setLogo(android.graphics.drawable.Drawable); - method public abstract void setNavigationMode(int); - method public abstract void setSelectedNavigationItem(int); + method public abstract deprecated void setNavigationMode(int); + method public abstract deprecated void setSelectedNavigationItem(int); method public void setSplitBackgroundDrawable(android.graphics.drawable.Drawable); method public void setStackedBackgroundDrawable(android.graphics.drawable.Drawable); method public abstract void setSubtitle(java.lang.CharSequence); @@ -2682,9 +3205,9 @@ field public static final int DISPLAY_SHOW_HOME = 2; // 0x2 field public static final int DISPLAY_SHOW_TITLE = 8; // 0x8 field public static final int DISPLAY_USE_LOGO = 1; // 0x1 - field public static final int NAVIGATION_MODE_LIST = 1; // 0x1 - field public static final int NAVIGATION_MODE_STANDARD = 0; // 0x0 - field public static final int NAVIGATION_MODE_TABS = 2; // 0x2 + field public static final deprecated int NAVIGATION_MODE_LIST = 1; // 0x1 + field public static final deprecated int NAVIGATION_MODE_STANDARD = 0; // 0x0 + field public static final deprecated int NAVIGATION_MODE_TABS = 2; // 0x2 } public static class ActionBar.LayoutParams extends android.view.ViewGroup.MarginLayoutParams { @@ -2701,11 +3224,11 @@ method public abstract void onMenuVisibilityChanged(boolean); } - public static abstract interface ActionBar.OnNavigationListener { + public static abstract deprecated interface ActionBar.OnNavigationListener { method public abstract boolean onNavigationItemSelected(int, long); } - public static abstract class ActionBar.Tab { + public static abstract deprecated class ActionBar.Tab { ctor public ActionBar.Tab(); method public abstract java.lang.CharSequence getContentDescription(); method public abstract android.view.View getCustomView(); @@ -2727,7 +3250,7 @@ field public static final int INVALID_POSITION = -1; // 0xffffffff } - public static abstract interface ActionBar.TabListener { + public static abstract deprecated interface ActionBar.TabListener { method public abstract void onTabReselected(android.app.ActionBar.Tab, android.app.FragmentTransaction); method public abstract void onTabSelected(android.app.ActionBar.Tab, android.app.FragmentTransaction); method public abstract void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction); @@ -2752,6 +3275,8 @@ method public void finishActivity(int); method public void finishActivityFromChild(android.app.Activity, int); method public void finishAffinity(); + method public void finishAfterTransition(); + method public void finishAndRemoveTask(); method public void finishFromChild(android.app.Activity); method public android.app.ActionBar getActionBar(); method public final android.app.Application getApplication(); @@ -2759,6 +3284,8 @@ method public java.lang.String getCallingPackage(); method public int getChangingConfigurations(); method public android.content.ComponentName getComponentName(); + method public android.transition.Scene getContentScene(); + method public android.transition.TransitionManager getContentTransitionManager(); method public android.view.View getCurrentFocus(); method public android.app.FragmentManager getFragmentManager(); method public android.content.Intent getIntent(); @@ -2766,6 +3293,7 @@ method public android.view.LayoutInflater getLayoutInflater(); method public android.app.LoaderManager getLoaderManager(); method public java.lang.String getLocalClassName(); + method public final android.media.session.MediaController getMediaController(); method public android.view.MenuInflater getMenuInflater(); method public final android.app.Activity getParent(); method public android.content.Intent getParentActivityIntent(); @@ -2791,6 +3319,7 @@ method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent); method public void onActionModeFinished(android.view.ActionMode); method public void onActionModeStarted(android.view.ActionMode); + method public void onActivityReenter(int, android.content.Intent); method protected void onActivityResult(int, int, android.content.Intent); method public void onAttachFragment(android.app.Fragment); method public void onAttachedToWindow(); @@ -2801,6 +3330,7 @@ method public boolean onContextItemSelected(android.view.MenuItem); method public void onContextMenuClosed(android.view.Menu); method protected void onCreate(android.os.Bundle); + method public void onCreate(android.os.Bundle, android.os.PersistableBundle); method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo); method public java.lang.CharSequence onCreateDescription(); method protected deprecated android.app.Dialog onCreateDialog(int); @@ -2814,6 +3344,7 @@ method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet); method protected void onDestroy(); method public void onDetachedFromWindow(); + method public void onEnterAnimationComplete(); method public boolean onGenericMotionEvent(android.view.MotionEvent); method public boolean onKeyDown(int, android.view.KeyEvent); method public boolean onKeyLongPress(int, android.view.KeyEvent); @@ -2831,6 +3362,7 @@ method public void onPanelClosed(int, android.view.Menu); method protected void onPause(); method protected void onPostCreate(android.os.Bundle); + method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle); method protected void onPostResume(); method protected deprecated void onPrepareDialog(int, android.app.Dialog); method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle); @@ -2840,9 +3372,11 @@ method public void onProvideAssistData(android.os.Bundle); method protected void onRestart(); method protected void onRestoreInstanceState(android.os.Bundle); + method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle); method protected void onResume(); method public deprecated java.lang.Object onRetainNonConfigurationInstance(); method protected void onSaveInstanceState(android.os.Bundle); + method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle); method public boolean onSearchRequested(); method protected void onStart(); method protected void onStop(); @@ -2852,22 +3386,30 @@ method public void onTrimMemory(int); method public void onUserInteraction(); method protected void onUserLeaveHint(); + method public void onVisibleBehindCanceled(); method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams); method public void onWindowFocusChanged(boolean); method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback); method public void openContextMenu(android.view.View); method public void openOptionsMenu(); method public void overridePendingTransition(int, int); + method public void postponeEnterTransition(); method public void recreate(); method public void registerForContextMenu(android.view.View); + method public boolean releaseInstance(); method public final deprecated void removeDialog(int); method public void reportFullyDrawn(); + method public boolean requestVisibleBehind(boolean); method public final boolean requestWindowFeature(int); method public final void runOnUiThread(java.lang.Runnable); + method public void setActionBar(android.widget.Toolbar); + method public void setContentTransitionManager(android.transition.TransitionManager); method public void setContentView(int); method public void setContentView(android.view.View); method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams); method public final void setDefaultKeyMode(int); + method public void setEnterSharedElementCallback(android.app.SharedElementCallback); + method public void setExitSharedElementCallback(android.app.SharedElementCallback); method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable); method public final void setFeatureDrawableAlpha(int, int); method public final void setFeatureDrawableResource(int, int); @@ -2875,6 +3417,7 @@ method public void setFinishOnTouchOutside(boolean); method public void setImmersive(boolean); method public void setIntent(android.content.Intent); + method public final void setMediaController(android.media.session.MediaController); method public final void setProgress(int); method public final void setProgressBarIndeterminate(boolean); method public final void setProgressBarIndeterminateVisibility(boolean); @@ -2883,9 +3426,10 @@ method public final void setResult(int); method public final void setResult(int, android.content.Intent); method public final void setSecondaryProgress(int); + method public void setTaskDescription(android.app.ActivityManager.TaskDescription); method public void setTitle(java.lang.CharSequence); method public void setTitle(int); - method public void setTitleColor(int); + method public deprecated void setTitleColor(int); method public void setVisible(boolean); method public final void setVolumeControlStream(int); method public boolean shouldUpRecreateTask(android.content.Intent); @@ -2904,10 +3448,13 @@ method public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException; method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException; + method public void startLockTask(); method public deprecated void startManagingCursor(android.database.Cursor); method public boolean startNextMatchingActivity(android.content.Intent); method public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle); + method public void startPostponedEnterTransition(); method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean); + method public void stopLockTask(); method public deprecated void stopManagingCursor(android.database.Cursor); method public void takeKeyEvents(boolean); method public void triggerSearch(java.lang.String, android.os.Bundle); @@ -2931,8 +3478,11 @@ } public class ActivityManager { + method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap); method public boolean clearApplicationUserData(); method public void dumpPackageState(java.io.FileDescriptor, java.lang.String); + method public android.util.Size getAppTaskThumbnailSize(); + method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks(); method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo(); method public int getLargeMemoryClass(); method public int getLauncherLargeIconDensity(); @@ -2942,11 +3492,12 @@ method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo); method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]); method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState(); - method public java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException; + method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException; method public java.util.List<android.app.ActivityManager.RunningAppProcessInfo> getRunningAppProcesses(); method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException; method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException; - method public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException; + method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException; + method public boolean isInLockTaskMode(); method public boolean isLowRamDevice(); method public static boolean isRunningInTestHarness(); method public static boolean isUserAMonkey(); @@ -2961,6 +3512,14 @@ field public static final int RECENT_WITH_EXCLUDED = 1; // 0x1 } + public static class ActivityManager.AppTask { + method public void finishAndRemoveTask(); + method public android.app.ActivityManager.RecentTaskInfo getTaskInfo(); + method public void moveToFront(); + method public void setExcludeFromRecents(boolean); + method public void startActivity(android.content.Context, android.content.Intent, android.os.Bundle); + } + public static class ActivityManager.MemoryInfo implements android.os.Parcelable { ctor public ActivityManager.MemoryInfo(); method public int describeContents(); @@ -2999,11 +3558,13 @@ method public void readFromParcel(android.os.Parcel); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; + field public int affiliatedTaskId; field public android.content.Intent baseIntent; field public java.lang.CharSequence description; field public int id; field public android.content.ComponentName origActivity; field public int persistentId; + field public android.app.ActivityManager.TaskDescription taskDescription; } public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable { @@ -3016,6 +3577,7 @@ field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190 field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4 field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64 + field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -3075,9 +3637,27 @@ field public android.content.ComponentName topActivity; } + public static class ActivityManager.TaskDescription implements android.os.Parcelable { + ctor public ActivityManager.TaskDescription(java.lang.String, android.graphics.Bitmap, int); + ctor public ActivityManager.TaskDescription(java.lang.String, android.graphics.Bitmap); + ctor public ActivityManager.TaskDescription(java.lang.String); + ctor public ActivityManager.TaskDescription(); + ctor public ActivityManager.TaskDescription(android.app.ActivityManager.TaskDescription); + method public int describeContents(); + method public android.graphics.Bitmap getIcon(); + method public java.lang.String getLabel(); + method public int getPrimaryColor(); + method public void readFromParcel(android.os.Parcel); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class ActivityOptions { method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int); method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int); + method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String); + method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...); + method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public android.os.Bundle toBundle(); method public void update(android.app.ActivityOptions); @@ -3085,13 +3665,16 @@ public class AlarmManager { method public void cancel(android.app.PendingIntent); + method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock(); method public void set(int, long, android.app.PendingIntent); + method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent); method public void setExact(int, long, android.app.PendingIntent); method public void setInexactRepeating(int, long, long, android.app.PendingIntent); method public void setRepeating(int, long, long, android.app.PendingIntent); method public void setTime(long); method public void setTimeZone(java.lang.String); method public void setWindow(int, long, long, android.app.PendingIntent); + field public static final java.lang.String ACTION_NEXT_ALARM_CLOCK_CHANGED = "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; field public static final int ELAPSED_REALTIME = 3; // 0x3 field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2 field public static final long INTERVAL_DAY = 86400000L; // 0x5265c00L @@ -3103,6 +3686,15 @@ field public static final int RTC_WAKEUP = 0; // 0x0 } + public static final class AlarmManager.AlarmClockInfo implements android.os.Parcelable { + ctor public AlarmManager.AlarmClockInfo(long, android.app.PendingIntent); + method public int describeContents(); + method public android.app.PendingIntent getShowIntent(); + method public long getTriggerTime(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface { ctor protected AlertDialog(android.content.Context); ctor protected AlertDialog(android.content.Context, int); @@ -3168,6 +3760,7 @@ method public android.app.AlertDialog.Builder setSingleChoiceItems(android.widget.ListAdapter, int, android.content.DialogInterface.OnClickListener); method public android.app.AlertDialog.Builder setTitle(int); method public android.app.AlertDialog.Builder setTitle(java.lang.CharSequence); + method public android.app.AlertDialog.Builder setView(int); method public android.app.AlertDialog.Builder setView(android.view.View); method public android.app.AlertDialog show(); } @@ -3188,10 +3781,12 @@ method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener); method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener); field public static final int MODE_ALLOWED = 0; // 0x0 + field public static final int MODE_DEFAULT = 3; // 0x3 field public static final int MODE_ERRORED = 2; // 0x2 field public static final int MODE_IGNORED = 1; // 0x1 field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location"; field public static final java.lang.String OPSTR_FINE_LOCATION = "android:fine_location"; + field public static final java.lang.String OPSTR_GET_USAGE_STATS = "android:get_usage_stats"; field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power"; field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location"; } @@ -3317,6 +3912,7 @@ method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams); method public void cancel(); method public void closeOptionsMenu(); + method public void create(); method public void dismiss(); method public boolean dispatchGenericMotionEvent(android.view.MotionEvent); method public boolean dispatchKeyEvent(android.view.KeyEvent); @@ -3519,14 +4115,22 @@ method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public final boolean equals(java.lang.Object); method public final android.app.Activity getActivity(); + method public boolean getAllowEnterTransitionOverlap(); + method public boolean getAllowReturnTransitionOverlap(); method public final android.os.Bundle getArguments(); method public final android.app.FragmentManager getChildFragmentManager(); + method public android.transition.Transition getEnterTransition(); + method public android.transition.Transition getExitTransition(); method public final android.app.FragmentManager getFragmentManager(); method public final int getId(); method public android.app.LoaderManager getLoaderManager(); method public final android.app.Fragment getParentFragment(); + method public android.transition.Transition getReenterTransition(); method public final android.content.res.Resources getResources(); method public final boolean getRetainInstance(); + method public android.transition.Transition getReturnTransition(); + method public android.transition.Transition getSharedElementEnterTransition(); + method public android.transition.Transition getSharedElementReturnTransition(); method public final java.lang.String getString(int); method public final java.lang.String getString(int, java.lang.Object...); method public final java.lang.String getTag(); @@ -3575,11 +4179,21 @@ method public void onViewCreated(android.view.View, android.os.Bundle); method public void onViewStateRestored(android.os.Bundle); method public void registerForContextMenu(android.view.View); + method public void setAllowEnterTransitionOverlap(boolean); + method public void setAllowReturnTransitionOverlap(boolean); method public void setArguments(android.os.Bundle); + method public void setEnterSharedElementCallback(android.app.SharedElementCallback); + method public void setEnterTransition(android.transition.Transition); + method public void setExitSharedElementCallback(android.app.SharedElementCallback); + method public void setExitTransition(android.transition.Transition); method public void setHasOptionsMenu(boolean); method public void setInitialSavedState(android.app.Fragment.SavedState); method public void setMenuVisibility(boolean); + method public void setReenterTransition(android.transition.Transition); method public void setRetainInstance(boolean); + method public void setReturnTransition(android.transition.Transition); + method public void setSharedElementEnterTransition(android.transition.Transition); + method public void setSharedElementReturnTransition(android.transition.Transition); method public void setTargetFragment(android.app.Fragment, int); method public void setUserVisibleHint(boolean); method public void startActivity(android.content.Intent); @@ -3599,7 +4213,7 @@ field public static final android.os.Parcelable.ClassLoaderCreator CREATOR; } - public class FragmentBreadCrumbs extends android.view.ViewGroup implements android.app.FragmentManager.OnBackStackChangedListener { + public deprecated class FragmentBreadCrumbs extends android.view.ViewGroup implements android.app.FragmentManager.OnBackStackChangedListener { ctor public FragmentBreadCrumbs(android.content.Context); ctor public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet); ctor public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet, int); @@ -3660,6 +4274,7 @@ method public abstract android.app.FragmentTransaction add(android.app.Fragment, java.lang.String); method public abstract android.app.FragmentTransaction add(int, android.app.Fragment); method public abstract android.app.FragmentTransaction add(int, android.app.Fragment, java.lang.String); + method public abstract android.app.FragmentTransaction addSharedElement(android.view.View, java.lang.String); method public abstract android.app.FragmentTransaction addToBackStack(java.lang.String); method public abstract android.app.FragmentTransaction attach(android.app.Fragment); method public abstract int commit(); @@ -3696,14 +4311,18 @@ method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean); method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean); method public void callActivityOnCreate(android.app.Activity, android.os.Bundle); + method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnDestroy(android.app.Activity); method public void callActivityOnNewIntent(android.app.Activity, android.content.Intent); method public void callActivityOnPause(android.app.Activity); method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle); + method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnRestart(android.app.Activity); method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle); + method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnResume(android.app.Activity); method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle); + method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnStart(android.app.Activity); method public void callActivityOnStop(android.app.Activity); method public void callActivityOnUserLeaving(android.app.Activity); @@ -3780,6 +4399,7 @@ } public class KeyguardManager { + method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence); method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult); method public boolean inKeyguardRestrictedInputMode(); method public boolean isKeyguardLocked(); @@ -3889,6 +4509,7 @@ ctor public MediaRouteButton(android.content.Context); ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet); ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet, int); + ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet, int, int); method public int getRouteTypes(); method public void onAttachedToWindow(); method public void onDetachedFromWindow(); @@ -3920,14 +4541,34 @@ method public java.lang.String getSortKey(); method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); method public void writeToParcel(android.os.Parcel, int); + field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT; + field public static final java.lang.String CATEGORY_ALARM = "alarm"; + field public static final java.lang.String CATEGORY_CALL = "call"; + field public static final java.lang.String CATEGORY_EMAIL = "email"; + field public static final java.lang.String CATEGORY_ERROR = "err"; + field public static final java.lang.String CATEGORY_EVENT = "event"; + field public static final java.lang.String CATEGORY_MESSAGE = "msg"; + field public static final java.lang.String CATEGORY_PROGRESS = "progress"; + field public static final java.lang.String CATEGORY_PROMO = "promo"; + field public static final java.lang.String CATEGORY_RECOMMENDATION = "recommendation"; + field public static final java.lang.String CATEGORY_SERVICE = "service"; + field public static final java.lang.String CATEGORY_SOCIAL = "social"; + field public static final java.lang.String CATEGORY_STATUS = "status"; + field public static final java.lang.String CATEGORY_SYSTEM = "sys"; + field public static final java.lang.String CATEGORY_TRANSPORT = "transport"; + field public static final int COLOR_DEFAULT = 0; // 0x0 field public static final android.os.Parcelable.Creator CREATOR; field public static final int DEFAULT_ALL = -1; // 0xffffffff field public static final int DEFAULT_LIGHTS = 4; // 0x4 field public static final int DEFAULT_SOUND = 1; // 0x1 field public static final int DEFAULT_VIBRATE = 2; // 0x2 + field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri"; + field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText"; + field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions"; field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText"; field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon"; field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big"; + field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession"; field public static final java.lang.String EXTRA_PEOPLE = "android.people"; field public static final java.lang.String EXTRA_PICTURE = "android.picture"; field public static final java.lang.String EXTRA_PROGRESS = "android.progress"; @@ -3938,6 +4579,7 @@ field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon"; field public static final java.lang.String EXTRA_SUB_TEXT = "android.subText"; field public static final java.lang.String EXTRA_SUMMARY_TEXT = "android.summaryText"; + field public static final java.lang.String EXTRA_TEMPLATE = "android.template"; field public static final java.lang.String EXTRA_TEXT = "android.text"; field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines"; field public static final java.lang.String EXTRA_TITLE = "android.title"; @@ -3952,15 +4594,22 @@ field public static final int FLAG_ONGOING_EVENT = 2; // 0x2 field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8 field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1 + field public static final java.lang.String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES"; field public static final int PRIORITY_DEFAULT = 0; // 0x0 field public static final int PRIORITY_HIGH = 1; // 0x1 field public static final int PRIORITY_LOW = -1; // 0xffffffff field public static final int PRIORITY_MAX = 2; // 0x2 field public static final int PRIORITY_MIN = -2; // 0xfffffffe - field public static final int STREAM_DEFAULT = -1; // 0xffffffff + field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff + field public static final int VISIBILITY_PRIVATE = 0; // 0x0 + field public static final int VISIBILITY_PUBLIC = 1; // 0x1 + field public static final int VISIBILITY_SECRET = -1; // 0xffffffff field public android.app.Notification.Action[] actions; - field public int audioStreamType; + field public android.media.AudioAttributes audioAttributes; + field public deprecated int audioStreamType; field public android.widget.RemoteViews bigContentView; + field public java.lang.String category; + field public int color; field public android.app.PendingIntent contentIntent; field public android.widget.RemoteViews contentView; field public int defaults; @@ -3968,6 +4617,7 @@ field public android.os.Bundle extras; field public int flags; field public android.app.PendingIntent fullScreenIntent; + field public android.widget.RemoteViews headsUpContentView; field public int icon; field public int iconLevel; field public android.graphics.Bitmap largeIcon; @@ -3976,10 +4626,12 @@ field public int ledOnMS; field public int number; field public int priority; + field public android.app.Notification publicVersion; field public android.net.Uri sound; field public java.lang.CharSequence tickerText; - field public android.widget.RemoteViews tickerView; + field public deprecated android.widget.RemoteViews tickerView; field public long[] vibrate; + field public int visibility; field public long when; } @@ -4041,11 +4693,14 @@ method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent); method public android.app.Notification.Builder addAction(android.app.Notification.Action); method public android.app.Notification.Builder addExtras(android.os.Bundle); + method public android.app.Notification.Builder addPerson(java.lang.String); method public android.app.Notification build(); method public android.app.Notification.Builder extend(android.app.Notification.Extender); method public android.os.Bundle getExtras(); method public deprecated android.app.Notification getNotification(); method public android.app.Notification.Builder setAutoCancel(boolean); + method public android.app.Notification.Builder setCategory(java.lang.String); + method public android.app.Notification.Builder setColor(int); method public android.app.Notification.Builder setContent(android.widget.RemoteViews); method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence); method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent); @@ -4065,18 +4720,21 @@ method public android.app.Notification.Builder setOnlyAlertOnce(boolean); method public android.app.Notification.Builder setPriority(int); method public android.app.Notification.Builder setProgress(int, int, boolean); + method public android.app.Notification.Builder setPublicVersion(android.app.Notification); method public android.app.Notification.Builder setShowWhen(boolean); method public android.app.Notification.Builder setSmallIcon(int); method public android.app.Notification.Builder setSmallIcon(int, int); method public android.app.Notification.Builder setSortKey(java.lang.String); method public android.app.Notification.Builder setSound(android.net.Uri); - method public android.app.Notification.Builder setSound(android.net.Uri, int); + method public deprecated android.app.Notification.Builder setSound(android.net.Uri, int); + method public android.app.Notification.Builder setSound(android.net.Uri, android.media.AudioAttributes); method public android.app.Notification.Builder setStyle(android.app.Notification.Style); method public android.app.Notification.Builder setSubText(java.lang.CharSequence); method public android.app.Notification.Builder setTicker(java.lang.CharSequence); - method public android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews); + method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews); method public android.app.Notification.Builder setUsesChronometer(boolean); method public android.app.Notification.Builder setVibrate(long[]); + method public android.app.Notification.Builder setVisibility(int); method public android.app.Notification.Builder setWhen(long); } @@ -4092,6 +4750,13 @@ method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence); } + public static class Notification.MediaStyle extends android.app.Notification.Style { + ctor public Notification.MediaStyle(); + ctor public Notification.MediaStyle(android.app.Notification.Builder); + method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSession.Token); + method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...); + } + public static abstract class Notification.Style { ctor public Notification.Style(); method public android.app.Notification build(); @@ -4288,6 +4953,9 @@ field public static final int MENU_KEYCODE = 47; // 0x2f field public static final java.lang.String QUERY = "query"; field public static final java.lang.String SHORTCUT_MIME_TYPE = "vnd.android.cursor.item/vnd.android.search.suggest"; + field public static final java.lang.String SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG = "suggest_audio_channel_config"; + field public static final java.lang.String SUGGEST_COLUMN_CONTENT_TYPE = "suggest_content_type"; + field public static final java.lang.String SUGGEST_COLUMN_DURATION = "suggest_duration"; field public static final java.lang.String SUGGEST_COLUMN_FLAGS = "suggest_flags"; field public static final java.lang.String SUGGEST_COLUMN_FORMAT = "suggest_format"; field public static final java.lang.String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1"; @@ -4296,13 +4964,22 @@ field public static final java.lang.String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data"; field public static final java.lang.String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id"; field public static final java.lang.String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; + field public static final java.lang.String SUGGEST_COLUMN_IS_LIVE = "suggest_is_live"; field public static final java.lang.String SUGGEST_COLUMN_LAST_ACCESS_HINT = "suggest_last_access_hint"; + field public static final java.lang.String SUGGEST_COLUMN_PRODUCTION_YEAR = "suggest_production_year"; + field public static final java.lang.String SUGGEST_COLUMN_PURCHASE_PRICE = "suggest_purchase_price"; field public static final java.lang.String SUGGEST_COLUMN_QUERY = "suggest_intent_query"; + field public static final java.lang.String SUGGEST_COLUMN_RATING_SCORE = "suggest_rating_score"; + field public static final java.lang.String SUGGEST_COLUMN_RATING_STYLE = "suggest_rating_style"; + field public static final java.lang.String SUGGEST_COLUMN_RENTAL_PRICE = "suggest_rental_price"; + field public static final java.lang.String SUGGEST_COLUMN_RESULT_CARD_IMAGE = "suggest_result_card_image"; field public static final java.lang.String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id"; field public static final java.lang.String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING = "suggest_spinner_while_refreshing"; field public static final java.lang.String SUGGEST_COLUMN_TEXT_1 = "suggest_text_1"; field public static final java.lang.String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2"; field public static final java.lang.String SUGGEST_COLUMN_TEXT_2_URL = "suggest_text_2_url"; + field public static final java.lang.String SUGGEST_COLUMN_VIDEO_HEIGHT = "suggest_video_height"; + field public static final java.lang.String SUGGEST_COLUMN_VIDEO_WIDTH = "suggest_video_width"; field public static final java.lang.String SUGGEST_MIME_TYPE = "vnd.android.cursor.dir/vnd.android.search.suggest"; field public static final java.lang.String SUGGEST_NEVER_MAKE_SHORTCUT = "_-1"; field public static final java.lang.String SUGGEST_PARAMETER_LIMIT = "limit"; @@ -4378,6 +5055,16 @@ field public static final int START_STICKY_COMPATIBILITY = 0; // 0x0 } + public abstract class SharedElementCallback { + ctor public SharedElementCallback(); + method public android.os.Parcelable onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF); + method public android.view.View onCreateSnapshotView(android.content.Context, android.os.Parcelable); + method public void onMapSharedElements(java.util.List<java.lang.String>, java.util.Map<java.lang.String, android.view.View>); + method public void onRejectSharedElements(java.util.List<android.view.View>); + method public void onSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>); + method public void onSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>); + } + public deprecated class TabActivity extends android.app.ActivityGroup { ctor public TabActivity(); method public android.widget.TabHost getTabHost(); @@ -4415,9 +5102,16 @@ } public final class UiAutomation { + method public void clearWindowAnimationFrameStats(); + method public boolean clearWindowContentFrameStats(int); method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException; + method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String); + method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow(); method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); + method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats(); + method public android.view.WindowContentFrameStats getWindowContentFrameStats(int); + method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows(); method public boolean injectInputEvent(android.view.InputEvent, boolean); method public final boolean performGlobalAction(int); method public void setOnAccessibilityEventListener(android.app.UiAutomation.OnAccessibilityEventListener); @@ -4453,6 +5147,7 @@ field public static java.lang.String ACTION_EXIT_CAR_MODE; field public static java.lang.String ACTION_EXIT_DESK_MODE; field public static final int DISABLE_CAR_MODE_GO_HOME = 1; // 0x1 + field public static final int ENABLE_CAR_MODE_ALLOW_SLEEP = 2; // 0x2 field public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 1; // 0x1 field public static final int MODE_NIGHT_AUTO = 0; // 0x0 field public static final int MODE_NIGHT_NO = 1; // 0x1 @@ -4548,26 +5243,51 @@ method public java.lang.CharSequence onDisableRequested(android.content.Context, android.content.Intent); method public void onDisabled(android.content.Context, android.content.Intent); method public void onEnabled(android.content.Context, android.content.Intent); + method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String); + method public void onLockTaskModeExiting(android.content.Context, android.content.Intent); method public void onPasswordChanged(android.content.Context, android.content.Intent); method public void onPasswordExpiring(android.content.Context, android.content.Intent); method public void onPasswordFailed(android.content.Context, android.content.Intent); method public void onPasswordSucceeded(android.content.Context, android.content.Intent); + method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent); method public void onReceive(android.content.Context, android.content.Intent); field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"; + field public static final java.lang.String ACTION_LOCK_TASK_ENTERING = "android.app.action.LOCK_TASK_ENTERING"; + field public static final java.lang.String ACTION_LOCK_TASK_EXITING = "android.app.action.LOCK_TASK_EXITING"; field public static final java.lang.String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED"; field public static final java.lang.String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING"; field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED"; field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED"; + field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE"; field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin"; field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING"; + field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE"; } public class DevicePolicyManager { + method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int); + method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); + method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName); + method public void addUserRestriction(android.content.ComponentName, java.lang.String); + method public void clearCrossProfileIntentFilters(android.content.ComponentName); + method public void clearDeviceOwnerApp(java.lang.String); + method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String); + method public void clearUserRestriction(android.content.ComponentName, java.lang.String); + method public android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle); + method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String); + method public void enableSystemApp(android.content.ComponentName, java.lang.String); + method public int enableSystemApp(android.content.ComponentName, android.content.Intent); + method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); + method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String); + method public boolean getAutoTimeRequired(); method public boolean getCameraDisabled(android.content.ComponentName); + method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName); + method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); + method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); @@ -4583,17 +5303,38 @@ method public int getPasswordMinimumSymbols(android.content.ComponentName); method public int getPasswordMinimumUpperCase(android.content.ComponentName); method public int getPasswordQuality(android.content.ComponentName); + method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName); + method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName); + method public boolean getScreenCaptureDisabled(android.content.ComponentName); method public boolean getStorageEncryption(android.content.ComponentName); method public int getStorageEncryptionStatus(); + method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]); method public boolean hasGrantedPolicy(android.content.ComponentName, int); + method public boolean installCaCert(android.content.ComponentName, byte[]); + method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String); method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); + method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String); method public boolean isDeviceOwnerApp(java.lang.String); + method public boolean isLockTaskPermitted(java.lang.String); + method public boolean isMasterVolumeMuted(android.content.ComponentName); + method public boolean isProfileOwnerApp(java.lang.String); + method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String); method public void lockNow(); method public void removeActiveAdmin(android.content.ComponentName); + method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); + method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean resetPassword(java.lang.String, int); + method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); + method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); + method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); + method public void setAutoTimeRequired(android.content.ComponentName, boolean); method public void setCameraDisabled(android.content.ComponentName, boolean); + method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); + method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public void setKeyguardDisabledFeatures(android.content.ComponentName, int); + method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException; + method public void setMasterVolumeMuted(android.content.ComponentName, boolean); method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int); method public void setMaximumTimeToLock(android.content.ComponentName, long); method public void setPasswordExpirationTimeout(android.content.ComponentName, long); @@ -4606,9 +5347,22 @@ method public void setPasswordMinimumSymbols(android.content.ComponentName, int); method public void setPasswordMinimumUpperCase(android.content.ComponentName, int); method public void setPasswordQuality(android.content.ComponentName, int); + method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>); + method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>); + method public void setProfileEnabled(android.content.ComponentName); + method public void setProfileName(android.content.ComponentName, java.lang.String); + method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo); + method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); + method public void setScreenCaptureDisabled(android.content.ComponentName, boolean); + method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public int setStorageEncryption(android.content.ComponentName, boolean); + method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean); + method public boolean switchUser(android.content.ComponentName, android.os.UserHandle); + method public void uninstallAllUserCaCerts(android.content.ComponentName); + method public void uninstallCaCert(android.content.ComponentName, byte[]); method public void wipeData(int); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; + field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE"; field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD"; field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION"; field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 @@ -4617,15 +5371,40 @@ field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0 field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN"; + field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE"; + field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM"; + field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER"; + field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION"; + field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME"; + field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS"; + field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE"; + field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME"; + field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.PROVISIONING_WIFI_PAC_URL"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.PROVISIONING_WIFI_PASSWORD"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE"; + field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID"; + field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2 + field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1 field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0 + field public static final int KEYGUARD_DISABLE_FINGERPRINT = 32; // 0x20 field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2 + field public static final int KEYGUARD_DISABLE_SECURE_NOTIFICATIONS = 4; // 0x4 + field public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 16; // 0x10 + field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8 field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1 + field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning"; field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000 field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000 field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000 field public static final int PASSWORD_QUALITY_COMPLEX = 393216; // 0x60000 field public static final int PASSWORD_QUALITY_NUMERIC = 131072; // 0x20000 + field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000 field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000 field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 @@ -4645,6 +5424,7 @@ method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException; method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException; method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException; + method public void onRestoreFinished(); field public static final int TYPE_DIRECTORY = 2; // 0x2 field public static final int TYPE_FILE = 1; // 0x1 } @@ -4716,6 +5496,142 @@ } +package android.app.job { + + public class JobInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getBackoffPolicy(); + method public android.os.PersistableBundle getExtras(); + method public int getId(); + method public long getInitialBackoffMillis(); + method public long getIntervalMillis(); + method public long getMaxExecutionDelayMillis(); + method public long getMinLatencyMillis(); + method public int getNetworkType(); + method public android.content.ComponentName getService(); + method public boolean isPeriodic(); + method public boolean isPersisted(); + method public boolean isRequireCharging(); + method public boolean isRequireDeviceIdle(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int BACKOFF_POLICY_EXPONENTIAL = 1; // 0x1 + field public static final int BACKOFF_POLICY_LINEAR = 0; // 0x0 + field public static final android.os.Parcelable.Creator CREATOR; + field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L + field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L + field public static final int NETWORK_TYPE_ANY = 1; // 0x1 + field public static final int NETWORK_TYPE_NONE = 0; // 0x0 + field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2 + } + + public static final class JobInfo.Builder { + ctor public JobInfo.Builder(int, android.content.ComponentName); + method public android.app.job.JobInfo build(); + method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int); + method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle); + method public android.app.job.JobInfo.Builder setMinimumLatency(long); + method public android.app.job.JobInfo.Builder setOverrideDeadline(long); + method public android.app.job.JobInfo.Builder setPeriodic(long); + method public android.app.job.JobInfo.Builder setPersisted(boolean); + method public android.app.job.JobInfo.Builder setRequiredNetworkType(int); + method public android.app.job.JobInfo.Builder setRequiresCharging(boolean); + method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean); + } + + public class JobParameters implements android.os.Parcelable { + method public int describeContents(); + method public android.os.PersistableBundle getExtras(); + method public int getJobId(); + method public boolean isOverrideDeadlineExpired(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public abstract class JobScheduler { + ctor public JobScheduler(); + method public abstract void cancel(int); + method public abstract void cancelAll(); + method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs(); + method public abstract int schedule(android.app.job.JobInfo); + field public static final int RESULT_FAILURE = 0; // 0x0 + field public static final int RESULT_SUCCESS = 1; // 0x1 + } + + public abstract class JobService extends android.app.Service { + ctor public JobService(); + method public final void jobFinished(android.app.job.JobParameters, boolean); + method public final android.os.IBinder onBind(android.content.Intent); + method public abstract boolean onStartJob(android.app.job.JobParameters); + method public abstract boolean onStopJob(android.app.job.JobParameters); + field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE"; + } + +} + +package android.app.usage { + + public final class ConfigurationStats implements android.os.Parcelable { + ctor public ConfigurationStats(android.app.usage.ConfigurationStats); + method public int describeContents(); + method public int getActivationCount(); + method public android.content.res.Configuration getConfiguration(); + method public long getFirstTimeStamp(); + method public long getLastTimeActive(); + method public long getLastTimeStamp(); + method public long getTotalTimeActive(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class UsageEvents implements android.os.Parcelable { + method public int describeContents(); + method public boolean getNextEvent(android.app.usage.UsageEvents.Event); + method public boolean hasNextEvent(); + method public void resetToStart(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class UsageEvents.Event { + ctor public UsageEvents.Event(); + method public java.lang.String getClassName(); + method public android.content.res.Configuration getConfiguration(); + method public int getEventType(); + method public java.lang.String getPackageName(); + method public long getTimeStamp(); + field public static final int CONFIGURATION_CHANGE = 5; // 0x5 + field public static final int MOVE_TO_BACKGROUND = 2; // 0x2 + field public static final int MOVE_TO_FOREGROUND = 1; // 0x1 + field public static final int NONE = 0; // 0x0 + } + + public final class UsageStats implements android.os.Parcelable { + ctor public UsageStats(android.app.usage.UsageStats); + method public void add(android.app.usage.UsageStats); + method public int describeContents(); + method public long getFirstTimeStamp(); + method public long getLastTimeStamp(); + method public long getLastTimeUsed(); + method public java.lang.String getPackageName(); + method public long getTotalTimeInForeground(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class UsageStatsManager { + 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); + method public android.app.usage.UsageEvents queryEvents(long, long); + method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long); + field public static final int INTERVAL_BEST = 4; // 0x4 + field public static final int INTERVAL_DAILY = 0; // 0x0 + 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 + } + +} + package android.appwidget { public class AppWidgetHost { @@ -4729,6 +5645,7 @@ method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo); method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo); method protected void onProvidersChanged(); + method public final void startAppWidgetConfigureActivityForResult(android.app.Activity, int, int, int, android.os.Bundle); method public void startListening(); method public void stopListening(); } @@ -4751,10 +5668,12 @@ public class AppWidgetManager { method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName); method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName, android.os.Bundle); + method public boolean bindAppWidgetIdIfAllowed(int, android.os.UserHandle, android.content.ComponentName, android.os.Bundle); method public int[] getAppWidgetIds(android.content.ComponentName); method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int); method public android.os.Bundle getAppWidgetOptions(int); method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders(); + method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle); method public static android.appwidget.AppWidgetManager getInstance(android.content.Context); method public void notifyAppWidgetViewDataChanged(int[], int); method public void notifyAppWidgetViewDataChanged(int, int); @@ -4769,15 +5688,20 @@ field public static final java.lang.String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED"; field public static final java.lang.String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED"; field public static final java.lang.String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED"; + field public static final java.lang.String ACTION_APPWIDGET_HOST_RESTORED = "android.appwidget.action.APPWIDGET_HOST_RESTORED"; field public static final java.lang.String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"; field public static final java.lang.String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK"; + field public static final java.lang.String ACTION_APPWIDGET_RESTORED = "android.appwidget.action.APPWIDGET_RESTORED"; field public static final java.lang.String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE"; field public static final java.lang.String EXTRA_APPWIDGET_ID = "appWidgetId"; field public static final java.lang.String EXTRA_APPWIDGET_IDS = "appWidgetIds"; + field public static final java.lang.String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds"; field public static final java.lang.String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions"; field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider"; + field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile"; field public static final java.lang.String EXTRA_CUSTOM_EXTRAS = "customExtras"; field public static final java.lang.String EXTRA_CUSTOM_INFO = "customInfo"; + field public static final java.lang.String EXTRA_HOST_ID = "hostId"; field public static final int INVALID_APPWIDGET_ID = 0; // 0x0 field public static final java.lang.String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider"; field public static final java.lang.String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory"; @@ -4794,6 +5718,7 @@ method public void onDisabled(android.content.Context); method public void onEnabled(android.content.Context); method public void onReceive(android.content.Context, android.content.Intent); + method public void onRestored(android.content.Context, int[], int[]); method public void onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]); } @@ -4802,6 +5727,10 @@ ctor public AppWidgetProviderInfo(android.os.Parcel); method public android.appwidget.AppWidgetProviderInfo clone(); method public int describeContents(); + method public final android.os.UserHandle getProfile(); + method public final android.graphics.drawable.Drawable loadIcon(android.content.Context, int); + method public final java.lang.String loadLabel(android.content.pm.PackageManager); + method public final android.graphics.drawable.Drawable loadPreviewImage(android.content.Context, int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int RESIZE_BOTH = 3; // 0x3 @@ -4810,12 +5739,13 @@ field public static final int RESIZE_VERTICAL = 2; // 0x2 field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1 field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2 + field public static final int WIDGET_CATEGORY_SEARCHBOX = 4; // 0x4 field public int autoAdvanceViewId; field public android.content.ComponentName configure; field public int icon; field public int initialKeyguardLayout; field public int initialLayout; - field public java.lang.String label; + field public deprecated java.lang.String label; field public int minHeight; field public int minResizeHeight; field public int minResizeWidth; @@ -4850,6 +5780,8 @@ method public boolean disable(); method public boolean enable(); method public java.lang.String getAddress(); + method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser(); + method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner(); method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices(); method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter(); method public java.lang.String getName(); @@ -4861,13 +5793,16 @@ method public int getState(); method public boolean isDiscovering(); method public boolean isEnabled(); + method public boolean isMultipleAdvertisementSupported(); + method public boolean isOffloadedFilteringSupported(); + method public boolean isOffloadedScanBatchingSupported(); method public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException; method public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException; method public boolean setName(java.lang.String); method public boolean startDiscovery(); - method public boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); - method public boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback); - method public void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); + method public deprecated boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); + method public deprecated boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback); + method public deprecated void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED"; field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED"; @@ -5288,9 +6223,15 @@ method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic); method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor); method public boolean readRemoteRssi(); + method public boolean requestConnectionPriority(int); + method public boolean requestMtu(int); method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean); method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic); method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor); + field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0 + field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1 + field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2 + field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f field public static final int GATT_FAILURE = 257; // 0x101 field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5 field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf @@ -5310,6 +6251,7 @@ method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int); method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int); method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int); + method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int); method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int); method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int); method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int); @@ -5409,6 +6351,7 @@ method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor); method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]); method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean); + method public void onNotificationSent(android.bluetooth.BluetoothDevice, int); method public void onServiceAdded(int, android.bluetooth.BluetoothGattService); } @@ -5539,6 +6482,166 @@ } +package android.bluetooth.le { + + public abstract class AdvertiseCallback { + ctor public AdvertiseCallback(); + method public void onStartFailure(int); + method public void onStartSuccess(android.bluetooth.le.AdvertiseSettings); + field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3 + field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1 + field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5 + field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4 + field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2 + } + + public final class AdvertiseData implements android.os.Parcelable { + method public int describeContents(); + method public boolean getIncludeDeviceName(); + method public boolean getIncludeTxPowerLevel(); + method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); + method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); + method public java.util.List<android.os.ParcelUuid> getServiceUuids(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class AdvertiseData.Builder { + ctor public AdvertiseData.Builder(); + method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]); + method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]); + method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid); + method public android.bluetooth.le.AdvertiseData build(); + method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); + method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean); + } + + public final class AdvertiseSettings implements android.os.Parcelable { + method public int describeContents(); + method public int getMode(); + method public int getTimeout(); + method public int getTxPowerLevel(); + method public boolean isConnectable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1 + field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2 + field public static final int ADVERTISE_MODE_LOW_POWER = 0; // 0x0 + field public static final int ADVERTISE_TX_POWER_HIGH = 3; // 0x3 + field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1 + field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2 + field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0 + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class AdvertiseSettings.Builder { + ctor public AdvertiseSettings.Builder(); + method public android.bluetooth.le.AdvertiseSettings build(); + method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int); + method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean); + method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int); + method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int); + } + + public final class BluetoothLeAdvertiser { + method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); + method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); + method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback); + } + + public final class BluetoothLeScanner { + method public void flushPendingScanResults(android.bluetooth.le.ScanCallback); + method public void startScan(android.bluetooth.le.ScanCallback); + method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); + method public void stopScan(android.bluetooth.le.ScanCallback); + } + + public abstract class ScanCallback { + ctor public ScanCallback(); + method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>); + method public void onScanFailed(int); + method public void onScanResult(int, android.bluetooth.le.ScanResult); + field public static final int SCAN_FAILED_ALREADY_STARTED = 1; // 0x1 + field public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2; // 0x2 + field public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; // 0x4 + field public static final int SCAN_FAILED_INTERNAL_ERROR = 3; // 0x3 + } + + public final class ScanFilter implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.String getDeviceAddress(); + method public java.lang.String getDeviceName(); + method public byte[] getManufacturerData(); + method public byte[] getManufacturerDataMask(); + method public int getManufacturerId(); + method public byte[] getServiceData(); + method public byte[] getServiceDataMask(); + method public android.os.ParcelUuid getServiceDataUuid(); + method public android.os.ParcelUuid getServiceUuid(); + method public android.os.ParcelUuid getServiceUuidMask(); + method public boolean matches(android.bluetooth.le.ScanResult); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class ScanFilter.Builder { + ctor public ScanFilter.Builder(); + method public android.bluetooth.le.ScanFilter build(); + method public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(java.lang.String); + method public android.bluetooth.le.ScanFilter.Builder setDeviceName(java.lang.String); + method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[]); + method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]); + method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]); + method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]); + method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid); + method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid); + } + + public final class ScanRecord { + method public int getAdvertiseFlags(); + method public byte[] getBytes(); + method public java.lang.String getDeviceName(); + method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); + method public byte[] getManufacturerSpecificData(int); + method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); + method public byte[] getServiceData(android.os.ParcelUuid); + method public java.util.List<android.os.ParcelUuid> getServiceUuids(); + method public int getTxPowerLevel(); + } + + public final class ScanResult implements android.os.Parcelable { + ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); + method public int describeContents(); + method public android.bluetooth.BluetoothDevice getDevice(); + method public int getRssi(); + method public android.bluetooth.le.ScanRecord getScanRecord(); + method public long getTimestampNanos(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class ScanSettings implements android.os.Parcelable { + method public int describeContents(); + method public int getCallbackType(); + method public long getReportDelayMillis(); + method public int getScanMode(); + method public int getScanResultType(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1 + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int SCAN_MODE_BALANCED = 1; // 0x1 + field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 + field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 + } + + public static final class ScanSettings.Builder { + ctor public ScanSettings.Builder(); + method public android.bluetooth.le.ScanSettings build(); + method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long); + method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); + } + +} + package android.content { public abstract class AbstractThreadedSyncAdapter { @@ -5868,6 +6971,7 @@ method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle); method public deprecated void cancelSync(android.net.Uri); method public static void cancelSync(android.accounts.Account, java.lang.String); + method public static void cancelSync(android.content.SyncRequest); method public final android.net.Uri canonicalize(android.net.Uri); method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]); method public static deprecated android.content.SyncInfo getCurrentSync(); @@ -5912,8 +7016,10 @@ method public final void unregisterContentObserver(android.database.ContentObserver); method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); method public static void validateSyncExtrasBundle(android.os.Bundle); + field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*"; field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir"; field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; + field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE"; field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource"; field public static final java.lang.String SCHEME_CONTENT = "content"; field public static final java.lang.String SCHEME_FILE = "file"; @@ -6007,16 +7113,20 @@ method public abstract android.content.res.AssetManager getAssets(); method public abstract java.io.File getCacheDir(); method public abstract java.lang.ClassLoader getClassLoader(); + method public abstract java.io.File getCodeCacheDir(); method public abstract android.content.ContentResolver getContentResolver(); method public abstract java.io.File getDatabasePath(java.lang.String); method public abstract java.io.File getDir(java.lang.String, int); + method public final android.graphics.drawable.Drawable getDrawable(int); method public abstract java.io.File getExternalCacheDir(); method public abstract java.io.File[] getExternalCacheDirs(); method public abstract java.io.File getExternalFilesDir(java.lang.String); method public abstract java.io.File[] getExternalFilesDirs(java.lang.String); + method public abstract java.io.File[] getExternalMediaDirs(); method public abstract java.io.File getFileStreamPath(java.lang.String); method public abstract java.io.File getFilesDir(); method public abstract android.os.Looper getMainLooper(); + method public abstract java.io.File getNoBackupFilesDir(); method public abstract java.io.File getObbDir(); method public abstract java.io.File[] getObbDirs(); method public abstract java.lang.String getPackageCodePath(); @@ -6047,8 +7157,8 @@ method public void registerComponentCallbacks(android.content.ComponentCallbacks); method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter); method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler); - method public abstract void removeStickyBroadcast(android.content.Intent); - method public abstract void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); + method public abstract deprecated void removeStickyBroadcast(android.content.Intent); + method public abstract deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public abstract void revokeUriPermission(android.net.Uri, int); method public abstract void sendBroadcast(android.content.Intent); method public abstract void sendBroadcast(android.content.Intent, java.lang.String); @@ -6057,10 +7167,10 @@ method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String); method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); - method public abstract void sendStickyBroadcast(android.content.Intent); - method public abstract void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); - method public abstract void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); - method public abstract void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public abstract deprecated void sendStickyBroadcast(android.content.Intent); + method public abstract deprecated void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); + method public abstract deprecated void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public abstract deprecated void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public abstract void setTheme(int); method public abstract deprecated void setWallpaper(android.graphics.Bitmap) throws java.io.IOException; method public abstract deprecated void setWallpaper(java.io.InputStream) throws java.io.IOException; @@ -6080,8 +7190,10 @@ field public static final java.lang.String ACCOUNT_SERVICE = "account"; field public static final java.lang.String ACTIVITY_SERVICE = "activity"; field public static final java.lang.String ALARM_SERVICE = "alarm"; + field public static final java.lang.String APPWIDGET_SERVICE = "appwidget"; field public static final java.lang.String APP_OPS_SERVICE = "appops"; field public static final java.lang.String AUDIO_SERVICE = "audio"; + field public static final java.lang.String BATTERY_SERVICE = "batterymanager"; field public static final int BIND_ABOVE_CLIENT = 8; // 0x8 field public static final int BIND_ADJUST_WITH_ACTIVITY = 128; // 0x80 field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10 @@ -6091,6 +7203,7 @@ field public static final int BIND_NOT_FOREGROUND = 4; // 0x4 field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20 field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth"; + field public static final java.lang.String CAMERA_SERVICE = "camera"; field public static final java.lang.String CAPTIONING_SERVICE = "captioning"; field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard"; field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity"; @@ -6104,10 +7217,14 @@ field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; + field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler"; field public static final java.lang.String KEYGUARD_SERVICE = "keyguard"; + field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps"; field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater"; field public static final java.lang.String LOCATION_SERVICE = "location"; + field public static final java.lang.String MEDIA_PROJECTION_SERVICE = "media_projection"; field public static final java.lang.String MEDIA_ROUTER_SERVICE = "media_router"; + field public static final java.lang.String MEDIA_SESSION_SERVICE = "media_session"; field public static final int MODE_APPEND = 32768; // 0x8000 field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8 field public static final int MODE_MULTI_PROCESS = 4; // 0x4 @@ -6119,11 +7236,14 @@ field public static final java.lang.String NSD_SERVICE = "servicediscovery"; field public static final java.lang.String POWER_SERVICE = "power"; field public static final java.lang.String PRINT_SERVICE = "print"; + field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions"; field public static final java.lang.String SEARCH_SERVICE = "search"; field public static final java.lang.String SENSOR_SERVICE = "sensor"; field public static final java.lang.String STORAGE_SERVICE = "storage"; + field public static final java.lang.String TELECOM_SERVICE = "telecom"; field public static final java.lang.String TELEPHONY_SERVICE = "phone"; field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices"; + field public static final java.lang.String TV_INPUT_SERVICE = "tv_input"; field public static final java.lang.String UI_MODE_SERVICE = "uimode"; field public static final java.lang.String USB_SERVICE = "usb"; field public static final java.lang.String USER_SERVICE = "user"; @@ -6166,6 +7286,7 @@ method public android.content.Context getBaseContext(); method public java.io.File getCacheDir(); method public java.lang.ClassLoader getClassLoader(); + method public java.io.File getCodeCacheDir(); method public android.content.ContentResolver getContentResolver(); method public java.io.File getDatabasePath(java.lang.String); method public java.io.File getDir(java.lang.String, int); @@ -6173,9 +7294,11 @@ method public java.io.File[] getExternalCacheDirs(); method public java.io.File getExternalFilesDir(java.lang.String); method public java.io.File[] getExternalFilesDirs(java.lang.String); + method public java.io.File[] getExternalMediaDirs(); method public java.io.File getFileStreamPath(java.lang.String); method public java.io.File getFilesDir(); method public android.os.Looper getMainLooper(); + method public java.io.File getNoBackupFilesDir(); method public java.io.File getObbDir(); method public java.io.File[] getObbDirs(); method public java.lang.String getPackageCodePath(); @@ -6429,6 +7552,7 @@ field public static final java.lang.String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE"; field public static final java.lang.String ACTION_ALL_APPS = "android.intent.action.ALL_APPS"; field public static final java.lang.String ACTION_ANSWER = "android.intent.action.ANSWER"; + field public static final java.lang.String ACTION_APPLICATION_RESTRICTIONS_CHANGED = "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED"; field public static final java.lang.String ACTION_APP_ERROR = "android.intent.action.APP_ERROR"; field public static final java.lang.String ACTION_ASSIST = "android.intent.action.ASSIST"; field public static final java.lang.String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA"; @@ -6469,6 +7593,8 @@ field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE"; field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED"; field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN"; + field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED"; + field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED"; field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE"; field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE"; field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL"; @@ -6487,6 +7613,7 @@ field public static final java.lang.String ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED"; field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL"; field public static final java.lang.String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT"; + field public static final java.lang.String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE"; field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED"; field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED"; field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED"; @@ -6557,6 +7684,7 @@ field public static final java.lang.String CATEGORY_HOME = "android.intent.category.HOME"; field public static final java.lang.String CATEGORY_INFO = "android.intent.category.INFO"; field public static final java.lang.String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"; + field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER"; field public static final java.lang.String CATEGORY_LE_DESK_DOCK = "android.intent.category.LE_DESK_DOCK"; field public static final java.lang.String CATEGORY_MONKEY = "android.intent.category.MONKEY"; field public static final java.lang.String CATEGORY_OPENABLE = "android.intent.category.OPENABLE"; @@ -6571,6 +7699,7 @@ field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE"; field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE"; field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT"; + field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD"; field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE"; field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC"; field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT"; @@ -6600,6 +7729,7 @@ field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER"; field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER"; field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token"; + field public static final java.lang.String EXTRA_REPLACEMENT_EXTRAS = "android.intent.extra.REPLACEMENT_EXTRAS"; field public static final java.lang.String EXTRA_REPLACING = "android.intent.extra.REPLACING"; field public static final java.lang.String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle"; field public static final java.lang.String EXTRA_RESTRICTIONS_INTENT = "android.intent.extra.restrictions_intent"; @@ -6616,6 +7746,7 @@ field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT"; field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE"; field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID"; + field public static final java.lang.String EXTRA_USER = "android.intent.extra.USER"; field public static final int FILL_IN_ACTION = 1; // 0x1 field public static final int FILL_IN_CATEGORIES = 4; // 0x4 field public static final int FILL_IN_CLIP_DATA = 128; // 0x80 @@ -6627,11 +7758,12 @@ field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000 field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000 field public static final int FLAG_ACTIVITY_CLEAR_TOP = 67108864; // 0x4000000 - field public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 524288; // 0x80000 + field public static final deprecated int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 524288; // 0x80000 field public static final int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 8388608; // 0x800000 field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000 field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000 field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000 + field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 524288; // 0x80000 field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000 field public static final int FLAG_ACTIVITY_NO_ANIMATION = 65536; // 0x10000 field public static final int FLAG_ACTIVITY_NO_HISTORY = 1073741824; // 0x40000000 @@ -6639,12 +7771,14 @@ field public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 16777216; // 0x1000000 field public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 131072; // 0x20000 field public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 2097152; // 0x200000 + field public static final int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 8192; // 0x2000 field public static final int FLAG_ACTIVITY_SINGLE_TOP = 536870912; // 0x20000000 field public static final int FLAG_ACTIVITY_TASK_ON_HOME = 16384; // 0x4000 field public static final int FLAG_DEBUG_LOG_RESOLUTION = 8; // 0x8 field public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 16; // 0x10 field public static final int FLAG_FROM_BACKGROUND = 4; // 0x4 field public static final int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 64; // 0x40 + field public static final int FLAG_GRANT_PREFIX_URI_PERMISSION = 128; // 0x80 field public static final int FLAG_GRANT_READ_URI_PERMISSION = 1; // 0x1 field public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 2; // 0x2 field public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 32; // 0x20 @@ -6856,15 +7990,18 @@ } public class RestrictionEntry implements android.os.Parcelable { + ctor public RestrictionEntry(int, java.lang.String); ctor public RestrictionEntry(java.lang.String, java.lang.String); ctor public RestrictionEntry(java.lang.String, boolean); ctor public RestrictionEntry(java.lang.String, java.lang.String[]); + ctor public RestrictionEntry(java.lang.String, int); ctor public RestrictionEntry(android.os.Parcel); method public int describeContents(); method public java.lang.String[] getAllSelectedStrings(); method public java.lang.String[] getChoiceEntries(); method public java.lang.String[] getChoiceValues(); method public java.lang.String getDescription(); + method public int getIntValue(); method public java.lang.String getKey(); method public boolean getSelectedState(); method public java.lang.String getSelectedString(); @@ -6876,6 +8013,7 @@ method public void setChoiceValues(java.lang.String[]); method public void setChoiceValues(android.content.Context, int); method public void setDescription(java.lang.String); + method public void setIntValue(int); method public void setSelectedState(boolean); method public void setSelectedString(java.lang.String); method public void setTitle(java.lang.String); @@ -6884,8 +8022,49 @@ field public static final android.os.Parcelable.Creator CREATOR; field public static final int TYPE_BOOLEAN = 1; // 0x1 field public static final int TYPE_CHOICE = 2; // 0x2 + field public static final int TYPE_INTEGER = 5; // 0x5 field public static final int TYPE_MULTI_SELECT = 4; // 0x4 field public static final int TYPE_NULL = 0; // 0x0 + field public static final int TYPE_STRING = 6; // 0x6 + } + + public class RestrictionsManager { + method public android.content.Intent createLocalApprovalIntent(); + method public android.os.Bundle getApplicationRestrictions(); + method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String); + method public boolean hasRestrictionsProvider(); + method public void notifyPermissionResponse(java.lang.String, android.os.PersistableBundle); + method public void requestPermission(java.lang.String, java.lang.String, android.os.PersistableBundle); + field public static final java.lang.String ACTION_PERMISSION_RESPONSE_RECEIVED = "android.content.action.PERMISSION_RESPONSE_RECEIVED"; + field public static final java.lang.String ACTION_REQUEST_LOCAL_APPROVAL = "android.content.action.REQUEST_LOCAL_APPROVAL"; + field public static final java.lang.String ACTION_REQUEST_PERMISSION = "android.content.action.REQUEST_PERMISSION"; + field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME"; + field public static final java.lang.String EXTRA_REQUEST_BUNDLE = "android.content.extra.REQUEST_BUNDLE"; + field public static final java.lang.String EXTRA_REQUEST_ID = "android.content.extra.REQUEST_ID"; + field public static final java.lang.String EXTRA_REQUEST_TYPE = "android.content.extra.REQUEST_TYPE"; + field public static final java.lang.String EXTRA_RESPONSE_BUNDLE = "android.content.extra.RESPONSE_BUNDLE"; + field public static final java.lang.String META_DATA_APP_RESTRICTIONS = "android.content.APP_RESTRICTIONS"; + field public static final java.lang.String REQUEST_KEY_APPROVE_LABEL = "android.request.approve_label"; + field public static final java.lang.String REQUEST_KEY_DATA = "android.request.data"; + field public static final java.lang.String REQUEST_KEY_DENY_LABEL = "android.request.deny_label"; + field public static final java.lang.String REQUEST_KEY_ICON = "android.request.icon"; + field public static final java.lang.String REQUEST_KEY_ID = "android.request.id"; + field public static final java.lang.String REQUEST_KEY_MESSAGE = "android.request.mesg"; + field public static final java.lang.String REQUEST_KEY_NEW_REQUEST = "android.request.new_request"; + field public static final java.lang.String REQUEST_KEY_TITLE = "android.request.title"; + field public static final java.lang.String REQUEST_TYPE_APPROVAL = "android.request.type.approval"; + field public static final java.lang.String RESPONSE_KEY_ERROR_CODE = "android.response.errorcode"; + field public static final java.lang.String RESPONSE_KEY_MESSAGE = "android.response.msg"; + field public static final java.lang.String RESPONSE_KEY_RESPONSE_TIMESTAMP = "android.response.timestamp"; + field public static final java.lang.String RESPONSE_KEY_RESULT = "android.response.result"; + field public static final int RESULT_APPROVED = 1; // 0x1 + field public static final int RESULT_DENIED = 2; // 0x2 + field public static final int RESULT_ERROR = 5; // 0x5 + field public static final int RESULT_ERROR_BAD_REQUEST = 1; // 0x1 + field public static final int RESULT_ERROR_INTERNAL = 3; // 0x3 + field public static final int RESULT_ERROR_NETWORK = 2; // 0x2 + field public static final int RESULT_NO_RESPONSE = 3; // 0x3 + field public static final int RESULT_UNKNOWN_REQUEST = 4; // 0x4 } public class SearchRecentSuggestionsProvider extends android.content.ContentProvider { @@ -7077,8 +8256,13 @@ field public static final int CONFIG_TOUCHSCREEN = 8; // 0x8 field public static final int CONFIG_UI_MODE = 512; // 0x200 field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DOCUMENT_LAUNCH_ALWAYS = 2; // 0x2 + field public static final int DOCUMENT_LAUNCH_INTO_EXISTING = 1; // 0x1 + field public static final int DOCUMENT_LAUNCH_NEVER = 3; // 0x3 + field public static final int DOCUMENT_LAUNCH_NONE = 0; // 0x0 field public static final int FLAG_ALLOW_TASK_REPARENTING = 64; // 0x40 field public static final int FLAG_ALWAYS_RETAIN_TASK_STATE = 8; // 0x8 + field public static final int FLAG_AUTO_REMOVE_FROM_RECENTS = 8192; // 0x2000 field public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 4; // 0x4 field public static final int FLAG_EXCLUDE_FROM_RECENTS = 32; // 0x20 field public static final int FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS = 256; // 0x100 @@ -7087,12 +8271,17 @@ field public static final int FLAG_IMMERSIVE = 2048; // 0x800 field public static final int FLAG_MULTIPROCESS = 1; // 0x1 field public static final int FLAG_NO_HISTORY = 128; // 0x80 + field public static final int FLAG_RELINQUISH_TASK_IDENTITY = 4096; // 0x1000 + field public static final int FLAG_RESUME_WHILE_PAUSING = 16384; // 0x4000 field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000 field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10 field public static final int LAUNCH_MULTIPLE = 0; // 0x0 field public static final int LAUNCH_SINGLE_INSTANCE = 3; // 0x3 field public static final int LAUNCH_SINGLE_TASK = 2; // 0x2 field public static final int LAUNCH_SINGLE_TOP = 1; // 0x1 + field public static final int PERSIST_ACROSS_REBOOTS = 2; // 0x2 + field public static final int PERSIST_NEVER = 1; // 0x1 + field public static final int PERSIST_ROOT_ONLY = 0; // 0x0 field public static final int SCREEN_ORIENTATION_BEHIND = 3; // 0x3 field public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10; // 0xa field public static final int SCREEN_ORIENTATION_FULL_USER = 13; // 0xd @@ -7111,10 +8300,13 @@ field public static final int SCREEN_ORIENTATION_USER_PORTRAIT = 12; // 0xc field public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1; // 0x1 field public int configChanges; + field public int documentLaunchMode; field public int flags; field public int launchMode; + field public int maxRecents; field public java.lang.String parentActivityName; field public java.lang.String permission; + field public int persistableMode; field public int screenOrientation; field public int softInputMode; field public java.lang.String targetActivity; @@ -7136,11 +8328,14 @@ field public static final int FLAG_DEBUGGABLE = 2; // 0x2 field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000 field public static final int FLAG_FACTORY_TEST = 16; // 0x10 + field public static final int FLAG_FULL_BACKUP_ONLY = 67108864; // 0x4000000 field public static final int FLAG_HAS_CODE = 4; // 0x4 field public static final int FLAG_INSTALLED = 8388608; // 0x800000 field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000 + field public static final int FLAG_IS_GAME = 33554432; // 0x2000000 field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000 field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000 + field public static final int FLAG_MULTIARCH = -2147483648; // 0x80000000 field public static final int FLAG_PERSISTENT = 8; // 0x8 field public static final int FLAG_RESIZEABLE_FOR_SCREENS = 4096; // 0x1000 field public static final int FLAG_RESTORE_ANY_VERSION = 131072; // 0x20000 @@ -7171,6 +8366,8 @@ field public int requiresSmallestWidthDp; field public java.lang.String[] sharedLibraryFiles; field public java.lang.String sourceDir; + field public java.lang.String[] splitPublicSourceDirs; + field public java.lang.String[] splitSourceDirs; field public int targetSdkVersion; field public java.lang.String taskAffinity; field public int theme; @@ -7215,6 +8412,15 @@ field public int reqTouchScreen; } + public final class FeatureGroupInfo implements android.os.Parcelable { + ctor public FeatureGroupInfo(); + ctor public FeatureGroupInfo(android.content.pm.FeatureGroupInfo); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public android.content.pm.FeatureInfo[] features; + } + public class FeatureInfo implements android.os.Parcelable { ctor public FeatureInfo(); ctor public FeatureInfo(android.content.pm.FeatureInfo); @@ -7239,6 +8445,8 @@ field public boolean handleProfiling; field public java.lang.String publicSourceDir; field public java.lang.String sourceDir; + field public java.lang.String[] splitPublicSourceDirs; + field public java.lang.String[] splitSourceDirs; field public java.lang.String targetPackage; } @@ -7256,18 +8464,55 @@ field public static final android.os.Parcelable.Creator CREATOR; } + public class LauncherActivityInfo { + method public android.content.pm.ApplicationInfo getApplicationInfo(); + method public android.graphics.drawable.Drawable getBadgedIcon(int); + method public android.content.ComponentName getComponentName(); + method public long getFirstInstallTime(); + method public android.graphics.drawable.Drawable getIcon(int); + method public java.lang.CharSequence getLabel(); + method public java.lang.String getName(); + method public android.os.UserHandle getUser(); + } + + public class LauncherApps { + method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle); + method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); + method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); + method public void registerCallback(android.content.pm.LauncherApps.Callback); + method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler); + method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle); + method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); + method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); + method public void unregisterCallback(android.content.pm.LauncherApps.Callback); + } + + public static abstract class LauncherApps.Callback { + ctor public LauncherApps.Callback(); + method public abstract void onPackageAdded(java.lang.String, android.os.UserHandle); + method public abstract void onPackageChanged(java.lang.String, android.os.UserHandle); + method public abstract void onPackageRemoved(java.lang.String, android.os.UserHandle); + method public abstract void onPackagesAvailable(java.lang.String[], android.os.UserHandle, boolean); + method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean); + } + public class PackageInfo implements android.os.Parcelable { ctor public PackageInfo(); method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; + field public static final int INSTALL_LOCATION_AUTO = 0; // 0x0 + field public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1; // 0x1 + field public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2; // 0x2 field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2 field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1 field public android.content.pm.ActivityInfo[] activities; field public android.content.pm.ApplicationInfo applicationInfo; field public android.content.pm.ConfigurationInfo[] configPreferences; + field public android.content.pm.FeatureGroupInfo[] featureGroups; field public long firstInstallTime; field public int[] gids; + field public int installLocation; field public android.content.pm.InstrumentationInfo[] instrumentation; field public long lastUpdateTime; field public java.lang.String packageName; @@ -7281,10 +8526,92 @@ field public java.lang.String sharedUserId; field public int sharedUserLabel; field public android.content.pm.Signature[] signatures; + field public java.lang.String[] splitNames; field public int versionCode; field public java.lang.String versionName; } + public class PackageInstaller { + method public void abandonSession(int); + method public int createSession(android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException; + method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions(); + method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions(); + method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int); + method public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException; + method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback); + method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler); + method public void uninstall(java.lang.String, android.content.IntentSender); + method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback); + method public void updateSessionAppIcon(int, android.graphics.Bitmap); + method public void updateSessionAppLabel(int, java.lang.CharSequence); + field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; + field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME"; + field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; + field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID"; + field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS"; + field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE"; + field public static final java.lang.String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH"; + field public static final int STATUS_FAILURE = 1; // 0x1 + field public static final int STATUS_FAILURE_ABORTED = 3; // 0x3 + field public static final int STATUS_FAILURE_BLOCKED = 2; // 0x2 + field public static final int STATUS_FAILURE_CONFLICT = 5; // 0x5 + field public static final int STATUS_FAILURE_INCOMPATIBLE = 7; // 0x7 + field public static final int STATUS_FAILURE_INVALID = 4; // 0x4 + field public static final int STATUS_FAILURE_STORAGE = 6; // 0x6 + field public static final int STATUS_PENDING_USER_ACTION = -1; // 0xffffffff + field public static final int STATUS_SUCCESS = 0; // 0x0 + } + + public static class PackageInstaller.Session implements java.io.Closeable { + method public void abandon(); + method public void close(); + method public void commit(android.content.IntentSender); + method public void fsync(java.io.OutputStream) throws java.io.IOException; + method public java.lang.String[] getNames() throws java.io.IOException; + method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException; + method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException; + method public void setStagingProgress(float); + } + + public static abstract class PackageInstaller.SessionCallback { + ctor public PackageInstaller.SessionCallback(); + method public abstract void onActiveChanged(int, boolean); + method public abstract void onBadgingChanged(int); + method public abstract void onCreated(int); + method public abstract void onFinished(int, boolean); + method public abstract void onProgressChanged(int, float); + } + + public static class PackageInstaller.SessionInfo implements android.os.Parcelable { + method public android.content.Intent createDetailsIntent(); + method public int describeContents(); + method public android.graphics.Bitmap getAppIcon(); + method public java.lang.CharSequence getAppLabel(); + method public java.lang.String getAppPackageName(); + method public java.lang.String getInstallerPackageName(); + method public float getProgress(); + method public int getSessionId(); + method public boolean isActive(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static class PackageInstaller.SessionParams implements android.os.Parcelable { + ctor public PackageInstaller.SessionParams(int); + method public int describeContents(); + method public void setAppIcon(android.graphics.Bitmap); + method public void setAppLabel(java.lang.CharSequence); + method public void setAppPackageName(java.lang.String); + method public void setInstallLocation(int); + method public void setOriginatingUri(android.net.Uri); + method public void setReferrerUri(android.net.Uri); + method public void setSize(long); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int MODE_FULL_INSTALL = 1; // 0x1 + field public static final int MODE_INHERIT_EXISTING = 2; // 0x2 + } + public class PackageItemInfo { ctor public PackageItemInfo(); ctor public PackageItemInfo(android.content.pm.PackageItemInfo); @@ -7350,10 +8677,12 @@ method public abstract java.lang.String getInstallerPackageName(java.lang.String); method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String); + method public abstract android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String); method public abstract java.lang.String getNameForUid(int); method public android.content.pm.PackageInfo getPackageArchiveInfo(java.lang.String, int); method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; + method public abstract android.content.pm.PackageInstaller getPackageInstaller(); method public abstract java.lang.String[] getPackagesForUid(int); method public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int); method public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; @@ -7369,6 +8698,9 @@ method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures(); method public abstract java.lang.String[] getSystemSharedLibraryNames(); method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo); + method public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int); + method public abstract android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle); + method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle); method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo); method public abstract boolean hasSystemFeature(java.lang.String); method public abstract boolean isSafeMode(); @@ -7399,39 +8731,54 @@ field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT"; field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets"; field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency"; + field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output"; field public static final java.lang.String FEATURE_BACKUP = "android.software.backup"; field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; field public static final java.lang.String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le"; field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera"; field public static final java.lang.String FEATURE_CAMERA_ANY = "android.hardware.camera.any"; field public static final java.lang.String FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus"; + field public static final java.lang.String FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING = "android.hardware.camera.capability.manual_post_processing"; + field public static final java.lang.String FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR = "android.hardware.camera.capability.manual_sensor"; + field public static final java.lang.String FEATURE_CAMERA_CAPABILITY_RAW = "android.hardware.camera.capability.raw"; field public static final java.lang.String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external"; field public static final java.lang.String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash"; field public static final java.lang.String FEATURE_CAMERA_FRONT = "android.hardware.camera.front"; + field public static final java.lang.String FEATURE_CAMERA_LEVEL_FULL = "android.hardware.camera.level.full"; + field public static final java.lang.String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice"; field public static final java.lang.String FEATURE_CONSUMER_IR = "android.hardware.consumerir"; field public static final java.lang.String FEATURE_DEVICE_ADMIN = "android.software.device_admin"; field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch"; field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct"; field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand"; + field public static final java.lang.String FEATURE_GAMEPAD = "android.hardware.gamepad"; field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen"; field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods"; + field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback"; + field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv"; field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper"; field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location"; field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps"; field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network"; + field public static final java.lang.String FEATURE_MANAGED_USERS = "android.software.managed_users"; field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone"; field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc"; field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce"; + field public static final java.lang.String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep"; field public static final java.lang.String FEATURE_PRINTING = "android.software.print"; field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape"; field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait"; + field public static final java.lang.String FEATURE_SECURELY_REMOVES_USERS = "android.software.securely_removes_users"; field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer"; + field public static final java.lang.String FEATURE_SENSOR_AMBIENT_TEMPERATURE = "android.hardware.sensor.ambient_temperature"; field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer"; field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass"; field public static final java.lang.String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope"; field public static final java.lang.String FEATURE_SENSOR_HEART_RATE = "android.hardware.sensor.heartrate"; + field public static final java.lang.String FEATURE_SENSOR_HEART_RATE_ECG = "android.hardware.sensor.heartrate.ecg"; field public static final java.lang.String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light"; field public static final java.lang.String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity"; + field public static final java.lang.String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity"; field public static final java.lang.String FEATURE_SENSOR_STEP_COUNTER = "android.hardware.sensor.stepcounter"; field public static final java.lang.String FEATURE_SENSOR_STEP_DETECTOR = "android.hardware.sensor.stepdetector"; field public static final java.lang.String FEATURE_SIP = "android.software.sip"; @@ -7439,13 +8786,14 @@ field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony"; field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma"; field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm"; - field public static final java.lang.String FEATURE_TELEVISION = "android.hardware.type.television"; + field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television"; field public static final java.lang.String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen"; field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch"; field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct"; field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = "android.hardware.touchscreen.multitouch.jazzhand"; field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory"; field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host"; + field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot"; field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch"; field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview"; field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi"; @@ -7533,6 +8881,7 @@ field public static final android.os.Parcelable.Creator CREATOR; field public static final int FLAG_COSTS_MONEY = 1; // 0x1 field public static final int PROTECTION_DANGEROUS = 1; // 0x1 + field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40 field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20 field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10 field public static final int PROTECTION_MASK_BASE = 15; // 0xf @@ -7651,7 +9000,7 @@ ctor public AssetFileDescriptor.AutoCloseOutputStream(android.content.res.AssetFileDescriptor) throws java.io.IOException; } - public final class AssetManager { + public final class AssetManager implements java.lang.AutoCloseable { method public void close(); method public final java.lang.String[] getLocales(); method public final java.lang.String[] list(java.lang.String) throws java.io.IOException; @@ -7671,7 +9020,6 @@ public final class AssetManager.AssetInputStream extends java.io.InputStream { method public final int available() throws java.io.IOException; method public final void close() throws java.io.IOException; - method public final int getAssetInt(); method public final void mark(int); method public final boolean markSupported(); method public final int read() throws java.io.IOException; @@ -7687,6 +9035,7 @@ method public int describeContents(); method public int getColorForState(int[], int); method public int getDefaultColor(); + method public boolean isOpaque(); method public boolean isStateful(); method public static android.content.res.ColorStateList valueOf(int); method public android.content.res.ColorStateList withAlpha(int); @@ -7820,7 +9169,9 @@ method public int getDimensionPixelSize(int) throws android.content.res.Resources.NotFoundException; method public android.util.DisplayMetrics getDisplayMetrics(); method public android.graphics.drawable.Drawable getDrawable(int) throws android.content.res.Resources.NotFoundException; + method public android.graphics.drawable.Drawable getDrawable(int, android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException; method public android.graphics.drawable.Drawable getDrawableForDensity(int, int) throws android.content.res.Resources.NotFoundException; + method public android.graphics.drawable.Drawable getDrawableForDensity(int, int, android.content.res.Resources.Theme); method public float getFraction(int, int, int); method public int getIdentifier(java.lang.String, java.lang.String, java.lang.String); method public int[] getIntArray(int) throws android.content.res.Resources.NotFoundException; @@ -7864,6 +9215,8 @@ public final class Resources.Theme { method public void applyStyle(int, boolean); method public void dump(int, java.lang.String, java.lang.String); + method public android.graphics.drawable.Drawable getDrawable(int) throws android.content.res.Resources.NotFoundException; + method public android.content.res.Resources getResources(); method public android.content.res.TypedArray obtainStyledAttributes(int[]); method public android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException; method public android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[], int, int); @@ -7873,6 +9226,7 @@ public class TypedArray { method public boolean getBoolean(int, boolean); + method public int getChangingConfigurations(); method public int getColor(int, int); method public android.content.res.ColorStateList getColorStateList(int); method public float getDimension(int, float); @@ -7894,6 +9248,7 @@ method public java.lang.String getString(int); method public java.lang.CharSequence getText(int); method public java.lang.CharSequence[] getTextArray(int); + method public int getType(int); method public boolean getValue(int, android.util.TypedValue); method public boolean hasValue(int); method public int length(); @@ -8877,6 +10232,7 @@ ctor public GestureOverlayView(android.content.Context); ctor public GestureOverlayView(android.content.Context, android.util.AttributeSet); ctor public GestureOverlayView(android.content.Context, android.util.AttributeSet, int); + ctor public GestureOverlayView(android.content.Context, android.util.AttributeSet, int, int); method public void addOnGestureListener(android.gesture.GestureOverlayView.OnGestureListener); method public void addOnGesturePerformedListener(android.gesture.GestureOverlayView.OnGesturePerformedListener); method public void addOnGesturingListener(android.gesture.GestureOverlayView.OnGesturingListener); @@ -9118,13 +10474,13 @@ field public android.graphics.Bitmap inBitmap; field public int inDensity; field public boolean inDither; - field public boolean inInputShareable; + field public deprecated boolean inInputShareable; field public boolean inJustDecodeBounds; field public boolean inMutable; field public boolean inPreferQualityOverSpeed; field public android.graphics.Bitmap.Config inPreferredConfig; field public boolean inPremultiplied; - field public boolean inPurgeable; + field public deprecated boolean inPurgeable; field public int inSampleSize; field public boolean inScaled; field public int inScreenDensity; @@ -9195,16 +10551,17 @@ method public boolean clipRect(float, float, float, float, android.graphics.Region.Op); method public boolean clipRect(float, float, float, float); method public boolean clipRect(int, int, int, int); - method public boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); - method public boolean clipRegion(android.graphics.Region); + method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); + method public deprecated boolean clipRegion(android.graphics.Region); method public void concat(android.graphics.Matrix); method public void drawARGB(int, int, int, int); method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint); + method public void drawArc(float, float, float, float, float, float, boolean, android.graphics.Paint); method public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint); method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint); method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint); - method public void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint); - method public void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint); + method public deprecated void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint); + method public deprecated void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint); method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint); method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint); method public void drawCircle(float, float, float, android.graphics.Paint); @@ -9214,6 +10571,7 @@ method public void drawLines(float[], int, int, android.graphics.Paint); method public void drawLines(float[], android.graphics.Paint); method public void drawOval(android.graphics.RectF, android.graphics.Paint); + method public void drawOval(float, float, float, float, android.graphics.Paint); method public void drawPaint(android.graphics.Paint); method public void drawPath(android.graphics.Path, android.graphics.Paint); method public void drawPicture(android.graphics.Picture); @@ -9229,6 +10587,7 @@ method public void drawRect(android.graphics.Rect, android.graphics.Paint); method public void drawRect(float, float, float, float, android.graphics.Paint); method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint); + method public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint); method public void drawText(char[], int, int, float, float, android.graphics.Paint); method public void drawText(java.lang.String, float, float, android.graphics.Paint); method public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint); @@ -9259,9 +10618,13 @@ method public int save(); method public int save(int); method public int saveLayer(android.graphics.RectF, android.graphics.Paint, int); + method public int saveLayer(android.graphics.RectF, android.graphics.Paint); method public int saveLayer(float, float, float, float, android.graphics.Paint, int); + method public int saveLayer(float, float, float, float, android.graphics.Paint); method public int saveLayerAlpha(android.graphics.RectF, int, int); + method public int saveLayerAlpha(android.graphics.RectF, int); method public int saveLayerAlpha(float, float, float, float, int, int); + method public int saveLayerAlpha(float, float, float, float, int); method public void scale(float, float); method public final void scale(float, float, float, float); method public void setBitmap(android.graphics.Bitmap); @@ -9382,6 +10745,8 @@ field public static final int JPEG = 256; // 0x100 field public static final int NV16 = 16; // 0x10 field public static final int NV21 = 17; // 0x11 + field public static final int RAW10 = 37; // 0x25 + field public static final int RAW_SENSOR = 32; // 0x20 field public static final int RGB_565 = 4; // 0x4 field public static final int UNKNOWN = 0; // 0x0 field public static final int YUV_420_888 = 35; // 0x23 @@ -9411,7 +10776,7 @@ enum_constant public static final android.graphics.Interpolator.Result NORMAL; } - public class LayerRasterizer extends android.graphics.Rasterizer { + public deprecated class LayerRasterizer extends android.graphics.Rasterizer { ctor public LayerRasterizer(); method public void addLayer(android.graphics.Paint, float, float); method public void addLayer(android.graphics.Paint); @@ -9435,6 +10800,7 @@ ctor public Matrix(android.graphics.Matrix); method public void getValues(float[]); method public boolean invert(android.graphics.Matrix); + method public boolean isAffine(); method public boolean isIdentity(); method public void mapPoints(float[], int, float[], int, int); method public void mapPoints(float[], float[]); @@ -9529,6 +10895,24 @@ method public void setPaint(android.graphics.Paint); } + public final class Outline { + ctor public Outline(); + ctor public Outline(android.graphics.Outline); + method public boolean canClip(); + method public float getAlpha(); + method public boolean isEmpty(); + method public void set(android.graphics.Outline); + method public void setAlpha(float); + method public void setConvexPath(android.graphics.Path); + method public void setEmpty(); + method public void setOval(int, int, int, int); + method public void setOval(android.graphics.Rect); + method public void setRect(int, int, int, int); + method public void setRect(android.graphics.Rect); + method public void setRoundRect(int, int, int, int, float); + method public void setRoundRect(android.graphics.Rect, float); + } + public class Paint { ctor public Paint(); ctor public Paint(int); @@ -9544,15 +10928,17 @@ method public android.graphics.ColorFilter getColorFilter(); method public boolean getFillPath(android.graphics.Path, android.graphics.Path); method public int getFlags(); + method public java.lang.String getFontFeatureSettings(); method public float getFontMetrics(android.graphics.Paint.FontMetrics); method public android.graphics.Paint.FontMetrics getFontMetrics(); method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt); method public android.graphics.Paint.FontMetricsInt getFontMetricsInt(); method public float getFontSpacing(); method public int getHinting(); + method public float getLetterSpacing(); method public android.graphics.MaskFilter getMaskFilter(); method public android.graphics.PathEffect getPathEffect(); - method public android.graphics.Rasterizer getRasterizer(); + method public deprecated android.graphics.Rasterizer getRasterizer(); method public android.graphics.Shader getShader(); method public android.graphics.Paint.Cap getStrokeCap(); method public android.graphics.Paint.Join getStrokeJoin(); @@ -9576,6 +10962,7 @@ method public android.graphics.Xfermode getXfermode(); method public final boolean isAntiAlias(); method public final boolean isDither(); + method public boolean isElegantTextHeight(); method public final boolean isFakeBoldText(); method public final boolean isFilterBitmap(); method public final boolean isLinearText(); @@ -9594,14 +10981,17 @@ method public void setColor(int); method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter); method public void setDither(boolean); + method public void setElegantTextHeight(boolean); method public void setFakeBoldText(boolean); method public void setFilterBitmap(boolean); method public void setFlags(int); + method public void setFontFeatureSettings(java.lang.String); method public void setHinting(int); + method public void setLetterSpacing(float); method public void setLinearText(boolean); method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter); method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect); - method public android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer); + method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer); method public android.graphics.Shader setShader(android.graphics.Shader); method public void setShadowLayer(float, float, float, int); method public void setStrikeThruText(boolean); @@ -9691,22 +11081,28 @@ ctor public Path(); ctor public Path(android.graphics.Path); method public void addArc(android.graphics.RectF, float, float); + method public void addArc(float, float, float, float, float, float); method public void addCircle(float, float, float, android.graphics.Path.Direction); method public void addOval(android.graphics.RectF, android.graphics.Path.Direction); + method public void addOval(float, float, float, float, android.graphics.Path.Direction); method public void addPath(android.graphics.Path, float, float); method public void addPath(android.graphics.Path); method public void addPath(android.graphics.Path, android.graphics.Matrix); method public void addRect(android.graphics.RectF, android.graphics.Path.Direction); method public void addRect(float, float, float, float, android.graphics.Path.Direction); method public void addRoundRect(android.graphics.RectF, float, float, android.graphics.Path.Direction); + method public void addRoundRect(float, float, float, float, float, float, android.graphics.Path.Direction); method public void addRoundRect(android.graphics.RectF, float[], android.graphics.Path.Direction); + method public void addRoundRect(float, float, float, float, float[], android.graphics.Path.Direction); method public void arcTo(android.graphics.RectF, float, float, boolean); method public void arcTo(android.graphics.RectF, float, float); + method public void arcTo(float, float, float, float, float, float, boolean); method public void close(); method public void computeBounds(android.graphics.RectF, boolean); method public void cubicTo(float, float, float, float, float, float); method public android.graphics.Path.FillType getFillType(); method public void incReserve(int); + method public boolean isConvex(); method public boolean isEmpty(); method public boolean isInverseFillType(); method public boolean isRect(android.graphics.RectF); @@ -9904,7 +11300,7 @@ ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode); } - public class Rasterizer { + public deprecated class Rasterizer { ctor public Rasterizer(); } @@ -10073,6 +11469,7 @@ method public void releaseTexImage(); method public void setDefaultBufferSize(int, int); method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener); + method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener, android.os.Handler); method public void updateTexImage(); } @@ -10135,6 +11532,23 @@ method public abstract void stop(); } + public class AnimatedStateListDrawable extends android.graphics.drawable.StateListDrawable { + ctor public AnimatedStateListDrawable(); + method public void addState(int[], android.graphics.drawable.Drawable, int); + method public void addTransition(int, int, T, boolean); + } + + public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable { + ctor public AnimatedVectorDrawable(); + method public void draw(android.graphics.Canvas); + method public int getOpacity(); + method public boolean isRunning(); + method public void setAlpha(int); + method public void setColorFilter(android.graphics.ColorFilter); + method public void start(); + method public void stop(); + } + public class AnimationDrawable extends android.graphics.drawable.DrawableContainer implements android.graphics.drawable.Animatable java.lang.Runnable { ctor public AnimationDrawable(); method public void addFrame(android.graphics.drawable.Drawable, int); @@ -10208,6 +11622,8 @@ public abstract class Drawable { ctor public Drawable(); + method public void applyTheme(android.content.res.Resources.Theme); + method public boolean canApplyTheme(); method public void clearColorFilter(); method public final void copyBounds(android.graphics.Rect); method public final android.graphics.Rect copyBounds(); @@ -10216,24 +11632,30 @@ method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options); method public static android.graphics.drawable.Drawable createFromStream(java.io.InputStream, java.lang.String); method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public abstract void draw(android.graphics.Canvas); method public int getAlpha(); method public final android.graphics.Rect getBounds(); method public android.graphics.drawable.Drawable.Callback getCallback(); method public int getChangingConfigurations(); + method public android.graphics.ColorFilter getColorFilter(); method public android.graphics.drawable.Drawable.ConstantState getConstantState(); method public android.graphics.drawable.Drawable getCurrent(); + method public android.graphics.Rect getDirtyBounds(); method public int getIntrinsicHeight(); method public int getIntrinsicWidth(); method public final int getLevel(); method public int getMinimumHeight(); method public int getMinimumWidth(); method public abstract int getOpacity(); + method public void getOutline(android.graphics.Outline); method public boolean getPadding(android.graphics.Rect); method public int[] getState(); method public android.graphics.Region getTransparentRegion(); method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public void invalidateSelf(); method public boolean isAutoMirrored(); method public boolean isStateful(); @@ -10255,8 +11677,13 @@ method public void setColorFilter(int, android.graphics.PorterDuff.Mode); method public void setDither(boolean); method public void setFilterBitmap(boolean); + method public void setHotspot(float, float); + method public void setHotspotBounds(int, int, int, int); method public final boolean setLevel(int); method public boolean setState(int[]); + method public void setTint(int); + method public void setTintList(android.content.res.ColorStateList); + method public void setTintMode(android.graphics.PorterDuff.Mode); method public boolean setVisible(boolean, boolean); method public void unscheduleSelf(java.lang.Runnable); } @@ -10269,9 +11696,11 @@ public static abstract class Drawable.ConstantState { ctor public Drawable.ConstantState(); + method public boolean canApplyTheme(); method public abstract int getChangingConfigurations(); method public abstract android.graphics.drawable.Drawable newDrawable(); method public android.graphics.drawable.Drawable newDrawable(android.content.res.Resources); + method public android.graphics.drawable.Drawable newDrawable(android.content.res.Resources, android.content.res.Resources.Theme); } public class DrawableContainer extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback { @@ -10318,10 +11747,12 @@ ctor public GradientDrawable(); ctor public GradientDrawable(android.graphics.drawable.GradientDrawable.Orientation, int[]); method public void draw(android.graphics.Canvas); + method public float getGradientRadius(); method public int getOpacity(); method public android.graphics.drawable.GradientDrawable.Orientation getOrientation(); method public void setAlpha(int); method public void setColor(int); + method public void setColor(android.content.res.ColorStateList); method public void setColorFilter(android.graphics.ColorFilter); method public void setColors(int[]); method public void setCornerRadii(float[]); @@ -10333,7 +11764,9 @@ method public void setShape(int); method public void setSize(int, int); method public void setStroke(int, int); + method public void setStroke(int, android.content.res.ColorStateList); method public void setStroke(int, int, float, float); + method public void setStroke(int, android.content.res.ColorStateList, float, float); method public void setUseLevel(boolean); field public static final int LINE = 2; // 0x2 field public static final int LINEAR_GRADIENT = 0; // 0x0 @@ -10378,6 +11811,7 @@ method public int getId(int); method public int getNumberOfLayers(); method public int getOpacity(); + method public int getPaddingMode(); method public void invalidateDrawable(android.graphics.drawable.Drawable); method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long); method public void setAlpha(int); @@ -10386,7 +11820,10 @@ method public void setId(int, int); method public void setLayerInset(int, int, int, int, int); method public void setOpacity(int); + method public void setPaddingMode(int); method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); + field public static final int PADDING_MODE_NEST = 0; // 0x0 + field public static final int PADDING_MODE_STACK = 1; // 0x1 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { @@ -10426,15 +11863,33 @@ method public void setPicture(android.graphics.Picture); } + public class RippleDrawable extends android.graphics.drawable.LayerDrawable { + ctor public RippleDrawable(android.content.res.ColorStateList, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable); + method public void setColor(android.content.res.ColorStateList); + } + public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback { ctor public RotateDrawable(); method public void draw(android.graphics.Canvas); method public android.graphics.drawable.Drawable getDrawable(); + method public float getFromDegrees(); method public int getOpacity(); + method public float getPivotX(); + method public float getPivotY(); + method public float getToDegrees(); method public void invalidateDrawable(android.graphics.drawable.Drawable); + method public boolean isPivotXRelative(); + method public boolean isPivotYRelative(); method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long); method public void setAlpha(int); method public void setColorFilter(android.graphics.ColorFilter); + method public void setDrawable(android.graphics.drawable.Drawable); + method public void setFromDegrees(float); + method public void setPivotX(float); + method public void setPivotXRelative(boolean); + method public void setPivotY(float); + method public void setPivotYRelative(boolean); + method public void setToDegrees(float); method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); } @@ -10489,6 +11944,14 @@ method public void startTransition(int); } + public class VectorDrawable extends android.graphics.drawable.Drawable { + ctor public VectorDrawable(); + method public void draw(android.graphics.Canvas); + method public int getOpacity(); + method public void setAlpha(int); + method public void setColorFilter(android.graphics.ColorFilter); + } + } package android.graphics.drawable.shapes { @@ -10521,6 +11984,7 @@ method public android.graphics.drawable.shapes.Shape clone() throws java.lang.CloneNotSupportedException; method public abstract void draw(android.graphics.Canvas, android.graphics.Paint); method public final float getHeight(); + method public void getOutline(android.graphics.Outline); method public final float getWidth(); method public boolean hasAlpha(); method protected void onResize(float, float); @@ -10558,11 +12022,29 @@ method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect); } + public final class PdfRenderer implements java.lang.AutoCloseable { + ctor public PdfRenderer(android.os.ParcelFileDescriptor) throws java.io.IOException; + method public void close(); + method public int getPageCount(); + method public android.graphics.pdf.PdfRenderer.Page openPage(int); + method public boolean shouldScaleForPrinting(); + } + + public final class PdfRenderer.Page implements java.lang.AutoCloseable { + method public void close(); + method public int getHeight(); + method public int getIndex(); + method public int getWidth(); + method public void render(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Matrix, int); + field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1 + field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2 + } + } package android.hardware { - public class Camera { + public deprecated class Camera { method public final void addCallbackBuffer(byte[]); method public final void autoFocus(android.hardware.Camera.AutoFocusCallback); method public final void cancelAutoFocus(); @@ -10601,21 +12083,21 @@ field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1 } - public static class Camera.Area { + public static deprecated class Camera.Area { ctor public Camera.Area(android.graphics.Rect, int); field public android.graphics.Rect rect; field public int weight; } - public static abstract interface Camera.AutoFocusCallback { + public static abstract deprecated interface Camera.AutoFocusCallback { method public abstract void onAutoFocus(boolean, android.hardware.Camera); } - public static abstract interface Camera.AutoFocusMoveCallback { + public static abstract deprecated interface Camera.AutoFocusMoveCallback { method public abstract void onAutoFocusMoving(boolean, android.hardware.Camera); } - public static class Camera.CameraInfo { + public static deprecated class Camera.CameraInfo { ctor public Camera.CameraInfo(); field public static final int CAMERA_FACING_BACK = 0; // 0x0 field public static final int CAMERA_FACING_FRONT = 1; // 0x1 @@ -10624,11 +12106,11 @@ field public int orientation; } - public static abstract interface Camera.ErrorCallback { + public static abstract deprecated interface Camera.ErrorCallback { method public abstract void onError(int, android.hardware.Camera); } - public static class Camera.Face { + public static deprecated class Camera.Face { ctor public Camera.Face(); field public int id; field public android.graphics.Point leftEye; @@ -10638,15 +12120,15 @@ field public int score; } - public static abstract interface Camera.FaceDetectionListener { + public static abstract deprecated interface Camera.FaceDetectionListener { method public abstract void onFaceDetection(android.hardware.Camera.Face[], android.hardware.Camera); } - public static abstract interface Camera.OnZoomChangeListener { + public static abstract deprecated interface Camera.OnZoomChangeListener { method public abstract void onZoomChange(int, boolean, android.hardware.Camera); } - public class Camera.Parameters { + public deprecated class Camera.Parameters { method public java.lang.String flatten(); method public java.lang.String get(java.lang.String); method public java.lang.String getAntibanding(); @@ -10796,19 +12278,19 @@ field public static final java.lang.String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent"; } - public static abstract interface Camera.PictureCallback { + public static abstract deprecated interface Camera.PictureCallback { method public abstract void onPictureTaken(byte[], android.hardware.Camera); } - public static abstract interface Camera.PreviewCallback { + public static abstract deprecated interface Camera.PreviewCallback { method public abstract void onPreviewFrame(byte[], android.hardware.Camera); } - public static abstract interface Camera.ShutterCallback { + public static abstract deprecated interface Camera.ShutterCallback { method public abstract void onShutter(); } - public class Camera.Size { + public deprecated class Camera.Size { ctor public Camera.Size(int, int); field public int height; field public int width; @@ -10840,15 +12322,22 @@ public final class Sensor { method public int getFifoMaxEventCount(); method public int getFifoReservedEventCount(); + method public int getMaxDelay(); method public float getMaximumRange(); method public int getMinDelay(); method public java.lang.String getName(); method public float getPower(); + method public int getReportingMode(); method public float getResolution(); method public java.lang.String getStringType(); method public int getType(); method public java.lang.String getVendor(); method public int getVersion(); + method public boolean isWakeUpSensor(); + field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0 + field public static final int REPORTING_MODE_ONE_SHOT = 2; // 0x2 + field public static final int REPORTING_MODE_ON_CHANGE = 1; // 0x1 + field public static final int REPORTING_MODE_SPECIAL_TRIGGER = 3; // 0x3 field public static final java.lang.String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer"; field public static final java.lang.String STRING_TYPE_AMBIENT_TEMPERATURE = "android.sensor.ambient_temperature"; field public static final java.lang.String STRING_TYPE_GAME_ROTATION_VECTOR = "android.sensor.game_rotation_vector"; @@ -10921,6 +12410,7 @@ method public static float getAltitude(float, float); method public static void getAngleChange(float[], float[], float[]); method public android.hardware.Sensor getDefaultSensor(int); + method public android.hardware.Sensor getDefaultSensor(int, boolean); method public static float getInclination(float[]); method public static float[] getOrientation(float[], float[]); method public static void getQuaternionFromVector(float[], float[]); @@ -11013,16 +12503,640 @@ } +package android.hardware.camera2 { + + public class CameraAccessException extends android.util.AndroidException { + ctor public CameraAccessException(int); + ctor public CameraAccessException(int, java.lang.String); + ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable); + ctor public CameraAccessException(int, java.lang.Throwable); + method public final int getReason(); + field public static final int CAMERA_DISABLED = 1; // 0x1 + field public static final int CAMERA_DISCONNECTED = 2; // 0x2 + field public static final int CAMERA_ERROR = 3; // 0x3 + } + + public abstract class CameraCaptureSession implements java.lang.AutoCloseable { + ctor public CameraCaptureSession(); + method public abstract void abortCaptures() throws android.hardware.camera2.CameraAccessException; + method public abstract int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public abstract int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public abstract void close(); + method public abstract android.hardware.camera2.CameraDevice getDevice(); + method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException; + } + + public static abstract class CameraCaptureSession.CaptureCallback { + ctor public CameraCaptureSession.CaptureCallback(); + method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult); + method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure); + method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult); + method public void onCaptureSequenceAborted(android.hardware.camera2.CameraCaptureSession, int); + method public void onCaptureSequenceCompleted(android.hardware.camera2.CameraCaptureSession, int, long); + method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long, long); + } + + public static abstract class CameraCaptureSession.StateCallback { + ctor public CameraCaptureSession.StateCallback(); + method public void onActive(android.hardware.camera2.CameraCaptureSession); + method public void onClosed(android.hardware.camera2.CameraCaptureSession); + method public abstract void onConfigureFailed(android.hardware.camera2.CameraCaptureSession); + method public abstract void onConfigured(android.hardware.camera2.CameraCaptureSession); + method public void onReady(android.hardware.camera2.CameraCaptureSession); + } + + public final class CameraCharacteristics extends android.hardware.camera2.CameraMetadata { + method public T get(android.hardware.camera2.CameraCharacteristics.Key<T>); + method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys(); + method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys(); + field public static final android.hardware.camera2.CameraCharacteristics.Key COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_ANTIBANDING_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_COMPENSATION_RANGE; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_COMPENSATION_STEP; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AF_AVAILABLE_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AVAILABLE_EFFECTS; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AVAILABLE_SCENE_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AWB_AVAILABLE_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_MAX_REGIONS_AE; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_MAX_REGIONS_AF; + field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_MAX_REGIONS_AWB; + field public static final android.hardware.camera2.CameraCharacteristics.Key EDGE_AVAILABLE_EDGE_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key FLASH_INFO_AVAILABLE; + field public static final android.hardware.camera2.CameraCharacteristics.Key HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key INFO_SUPPORTED_HARDWARE_LEVEL; + field public static final android.hardware.camera2.CameraCharacteristics.Key JPEG_AVAILABLE_THUMBNAIL_SIZES; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_FACING; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_APERTURES; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_FILTER_DENSITIES; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_FOCAL_LENGTHS; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_FOCUS_DISTANCE_CALIBRATION; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_HYPERFOCAL_DISTANCE; + field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_MINIMUM_FOCUS_DISTANCE; + field public static final android.hardware.camera2.CameraCharacteristics.Key NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_AVAILABLE_CAPABILITIES; + field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_MAX_NUM_OUTPUT_PROC; + field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_MAX_NUM_OUTPUT_PROC_STALLING; + field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_MAX_NUM_OUTPUT_RAW; + field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_PARTIAL_RESULT_COUNT; + field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_PIPELINE_MAX_DEPTH; + field public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_AVAILABLE_MAX_DIGITAL_ZOOM; + field public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_CROPPING_TYPE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_STREAM_CONFIGURATION_MAP; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_AVAILABLE_TEST_PATTERN_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_BLACK_LEVEL_PATTERN; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_CALIBRATION_TRANSFORM1; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_CALIBRATION_TRANSFORM2; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_COLOR_TRANSFORM1; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_COLOR_TRANSFORM2; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_FORWARD_MATRIX1; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_FORWARD_MATRIX2; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_ACTIVE_ARRAY_SIZE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_COLOR_FILTER_ARRANGEMENT; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_EXPOSURE_TIME_RANGE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_MAX_FRAME_DURATION; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_PHYSICAL_SIZE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_PIXEL_ARRAY_SIZE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_SENSITIVITY_RANGE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_TIMESTAMP_SOURCE; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_WHITE_LEVEL; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_MAX_ANALOG_SENSITIVITY; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_ORIENTATION; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_REFERENCE_ILLUMINANT1; + field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_REFERENCE_ILLUMINANT2; + field public static final android.hardware.camera2.CameraCharacteristics.Key STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key STATISTICS_INFO_MAX_FACE_COUNT; + field public static final android.hardware.camera2.CameraCharacteristics.Key SYNC_MAX_LATENCY; + field public static final android.hardware.camera2.CameraCharacteristics.Key TONEMAP_AVAILABLE_TONE_MAP_MODES; + field public static final android.hardware.camera2.CameraCharacteristics.Key TONEMAP_MAX_CURVE_POINTS; + } + + public static final class CameraCharacteristics.Key { + method public final boolean equals(java.lang.Object); + method public java.lang.String getName(); + method public final int hashCode(); + } + + public abstract class CameraDevice implements java.lang.AutoCloseable { + method public abstract void close(); + method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException; + method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public abstract java.lang.String getId(); + field public static final int TEMPLATE_MANUAL = 6; // 0x6 + field public static final int TEMPLATE_PREVIEW = 1; // 0x1 + field public static final int TEMPLATE_RECORD = 3; // 0x3 + field public static final int TEMPLATE_STILL_CAPTURE = 2; // 0x2 + field public static final int TEMPLATE_VIDEO_SNAPSHOT = 4; // 0x4 + field public static final int TEMPLATE_ZERO_SHUTTER_LAG = 5; // 0x5 + } + + public static abstract class CameraDevice.StateCallback { + ctor public CameraDevice.StateCallback(); + method public void onClosed(android.hardware.camera2.CameraDevice); + method public abstract void onDisconnected(android.hardware.camera2.CameraDevice); + method public abstract void onError(android.hardware.camera2.CameraDevice, int); + method public abstract void onOpened(android.hardware.camera2.CameraDevice); + field public static final int ERROR_CAMERA_DEVICE = 4; // 0x4 + field public static final int ERROR_CAMERA_DISABLED = 3; // 0x3 + field public static final int ERROR_CAMERA_IN_USE = 1; // 0x1 + field public static final int ERROR_CAMERA_SERVICE = 5; // 0x5 + field public static final int ERROR_MAX_CAMERAS_IN_USE = 2; // 0x2 + } + + public final class CameraManager { + method public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(java.lang.String) throws android.hardware.camera2.CameraAccessException; + method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException; + method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException; + method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler); + method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback); + } + + public static abstract class CameraManager.AvailabilityCallback { + ctor public CameraManager.AvailabilityCallback(); + method public void onCameraAvailable(java.lang.String); + method public void onCameraUnavailable(java.lang.String); + } + + public abstract class CameraMetadata { + method public java.util.List<TKey> getKeys(); + field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1 + field public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2; // 0x2 + field public static final int COLOR_CORRECTION_ABERRATION_MODE_OFF = 0; // 0x0 + field public static final int COLOR_CORRECTION_MODE_FAST = 1; // 0x1 + field public static final int COLOR_CORRECTION_MODE_HIGH_QUALITY = 2; // 0x2 + field public static final int COLOR_CORRECTION_MODE_TRANSFORM_MATRIX = 0; // 0x0 + field public static final int CONTROL_AE_ANTIBANDING_MODE_50HZ = 1; // 0x1 + field public static final int CONTROL_AE_ANTIBANDING_MODE_60HZ = 2; // 0x2 + field public static final int CONTROL_AE_ANTIBANDING_MODE_AUTO = 3; // 0x3 + field public static final int CONTROL_AE_ANTIBANDING_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_AE_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_AE_MODE_ON = 1; // 0x1 + field public static final int CONTROL_AE_MODE_ON_ALWAYS_FLASH = 3; // 0x3 + field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH = 2; // 0x2 + field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4; // 0x4 + field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0; // 0x0 + field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1; // 0x1 + field public static final int CONTROL_AE_STATE_CONVERGED = 2; // 0x2 + field public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4; // 0x4 + field public static final int CONTROL_AE_STATE_INACTIVE = 0; // 0x0 + field public static final int CONTROL_AE_STATE_LOCKED = 3; // 0x3 + field public static final int CONTROL_AE_STATE_PRECAPTURE = 5; // 0x5 + field public static final int CONTROL_AE_STATE_SEARCHING = 1; // 0x1 + field public static final int CONTROL_AF_MODE_AUTO = 1; // 0x1 + field public static final int CONTROL_AF_MODE_CONTINUOUS_PICTURE = 4; // 0x4 + field public static final int CONTROL_AF_MODE_CONTINUOUS_VIDEO = 3; // 0x3 + field public static final int CONTROL_AF_MODE_EDOF = 5; // 0x5 + field public static final int CONTROL_AF_MODE_MACRO = 2; // 0x2 + field public static final int CONTROL_AF_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_AF_STATE_ACTIVE_SCAN = 3; // 0x3 + field public static final int CONTROL_AF_STATE_FOCUSED_LOCKED = 4; // 0x4 + field public static final int CONTROL_AF_STATE_INACTIVE = 0; // 0x0 + field public static final int CONTROL_AF_STATE_NOT_FOCUSED_LOCKED = 5; // 0x5 + field public static final int CONTROL_AF_STATE_PASSIVE_FOCUSED = 2; // 0x2 + field public static final int CONTROL_AF_STATE_PASSIVE_SCAN = 1; // 0x1 + field public static final int CONTROL_AF_STATE_PASSIVE_UNFOCUSED = 6; // 0x6 + field public static final int CONTROL_AF_TRIGGER_CANCEL = 2; // 0x2 + field public static final int CONTROL_AF_TRIGGER_IDLE = 0; // 0x0 + field public static final int CONTROL_AF_TRIGGER_START = 1; // 0x1 + field public static final int CONTROL_AWB_MODE_AUTO = 1; // 0x1 + field public static final int CONTROL_AWB_MODE_CLOUDY_DAYLIGHT = 6; // 0x6 + field public static final int CONTROL_AWB_MODE_DAYLIGHT = 5; // 0x5 + field public static final int CONTROL_AWB_MODE_FLUORESCENT = 3; // 0x3 + field public static final int CONTROL_AWB_MODE_INCANDESCENT = 2; // 0x2 + field public static final int CONTROL_AWB_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_AWB_MODE_SHADE = 8; // 0x8 + field public static final int CONTROL_AWB_MODE_TWILIGHT = 7; // 0x7 + field public static final int CONTROL_AWB_MODE_WARM_FLUORESCENT = 4; // 0x4 + field public static final int CONTROL_AWB_STATE_CONVERGED = 2; // 0x2 + field public static final int CONTROL_AWB_STATE_INACTIVE = 0; // 0x0 + field public static final int CONTROL_AWB_STATE_LOCKED = 3; // 0x3 + field public static final int CONTROL_AWB_STATE_SEARCHING = 1; // 0x1 + field public static final int CONTROL_CAPTURE_INTENT_CUSTOM = 0; // 0x0 + field public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6; // 0x6 + field public static final int CONTROL_CAPTURE_INTENT_PREVIEW = 1; // 0x1 + field public static final int CONTROL_CAPTURE_INTENT_STILL_CAPTURE = 2; // 0x2 + field public static final int CONTROL_CAPTURE_INTENT_VIDEO_RECORD = 3; // 0x3 + field public static final int CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT = 4; // 0x4 + field public static final int CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG = 5; // 0x5 + field public static final int CONTROL_EFFECT_MODE_AQUA = 8; // 0x8 + field public static final int CONTROL_EFFECT_MODE_BLACKBOARD = 7; // 0x7 + field public static final int CONTROL_EFFECT_MODE_MONO = 1; // 0x1 + field public static final int CONTROL_EFFECT_MODE_NEGATIVE = 2; // 0x2 + field public static final int CONTROL_EFFECT_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_EFFECT_MODE_POSTERIZE = 5; // 0x5 + field public static final int CONTROL_EFFECT_MODE_SEPIA = 4; // 0x4 + field public static final int CONTROL_EFFECT_MODE_SOLARIZE = 3; // 0x3 + field public static final int CONTROL_EFFECT_MODE_WHITEBOARD = 6; // 0x6 + field public static final int CONTROL_MODE_AUTO = 1; // 0x1 + field public static final int CONTROL_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_MODE_OFF_KEEP_STATE = 3; // 0x3 + field public static final int CONTROL_MODE_USE_SCENE_MODE = 2; // 0x2 + field public static final int CONTROL_SCENE_MODE_ACTION = 2; // 0x2 + field public static final int CONTROL_SCENE_MODE_BARCODE = 16; // 0x10 + field public static final int CONTROL_SCENE_MODE_BEACH = 8; // 0x8 + field public static final int CONTROL_SCENE_MODE_CANDLELIGHT = 15; // 0xf + field public static final int CONTROL_SCENE_MODE_DISABLED = 0; // 0x0 + field public static final int CONTROL_SCENE_MODE_FACE_PRIORITY = 1; // 0x1 + field public static final int CONTROL_SCENE_MODE_FIREWORKS = 12; // 0xc + field public static final int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17; // 0x11 + field public static final int CONTROL_SCENE_MODE_LANDSCAPE = 4; // 0x4 + field public static final int CONTROL_SCENE_MODE_NIGHT = 5; // 0x5 + field public static final int CONTROL_SCENE_MODE_NIGHT_PORTRAIT = 6; // 0x6 + field public static final int CONTROL_SCENE_MODE_PARTY = 14; // 0xe + field public static final int CONTROL_SCENE_MODE_PORTRAIT = 3; // 0x3 + field public static final int CONTROL_SCENE_MODE_SNOW = 9; // 0x9 + field public static final int CONTROL_SCENE_MODE_SPORTS = 13; // 0xd + field public static final int CONTROL_SCENE_MODE_STEADYPHOTO = 11; // 0xb + field public static final int CONTROL_SCENE_MODE_SUNSET = 10; // 0xa + field public static final int CONTROL_SCENE_MODE_THEATRE = 7; // 0x7 + field public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0; // 0x0 + field public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1; // 0x1 + field public static final int EDGE_MODE_FAST = 1; // 0x1 + field public static final int EDGE_MODE_HIGH_QUALITY = 2; // 0x2 + field public static final int EDGE_MODE_OFF = 0; // 0x0 + field public static final int FLASH_MODE_OFF = 0; // 0x0 + field public static final int FLASH_MODE_SINGLE = 1; // 0x1 + field public static final int FLASH_MODE_TORCH = 2; // 0x2 + field public static final int FLASH_STATE_CHARGING = 1; // 0x1 + field public static final int FLASH_STATE_FIRED = 3; // 0x3 + field public static final int FLASH_STATE_PARTIAL = 4; // 0x4 + field public static final int FLASH_STATE_READY = 2; // 0x2 + field public static final int FLASH_STATE_UNAVAILABLE = 0; // 0x0 + field public static final int HOT_PIXEL_MODE_FAST = 1; // 0x1 + field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2 + field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0 + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1 + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2 + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0 + field public static final int LENS_FACING_BACK = 1; // 0x1 + field public static final int LENS_FACING_FRONT = 0; // 0x0 + field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE = 1; // 0x1 + field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED = 2; // 0x2 + field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED = 0; // 0x0 + field public static final int LENS_OPTICAL_STABILIZATION_MODE_OFF = 0; // 0x0 + field public static final int LENS_OPTICAL_STABILIZATION_MODE_ON = 1; // 0x1 + field public static final int LENS_STATE_MOVING = 1; // 0x1 + field public static final int LENS_STATE_STATIONARY = 0; // 0x0 + field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1 + field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2 + field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3 + field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0 + field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1 + field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3 + field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2 + field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1 + field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4 + field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0 + field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME = 1; // 0x1 + field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN = 0; // 0x0 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10; // 0xa + field public static final int SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14; // 0xe + field public static final int SENSOR_REFERENCE_ILLUMINANT1_D50 = 23; // 0x17 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_D55 = 20; // 0x14 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_D65 = 21; // 0x15 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_D75 = 22; // 0x16 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT = 1; // 0x1 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT = 12; // 0xc + field public static final int SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT = 13; // 0xd + field public static final int SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER = 9; // 0x9 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_FLASH = 4; // 0x4 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT = 2; // 0x2 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24; // 0x18 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_SHADE = 11; // 0xb + field public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A = 17; // 0x11 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B = 18; // 0x12 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C = 19; // 0x13 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN = 3; // 0x3 + field public static final int SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT = 15; // 0xf + field public static final int SENSOR_TEST_PATTERN_MODE_COLOR_BARS = 2; // 0x2 + field public static final int SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY = 3; // 0x3 + field public static final int SENSOR_TEST_PATTERN_MODE_CUSTOM1 = 256; // 0x100 + field public static final int SENSOR_TEST_PATTERN_MODE_OFF = 0; // 0x0 + field public static final int SENSOR_TEST_PATTERN_MODE_PN9 = 4; // 0x4 + field public static final int SENSOR_TEST_PATTERN_MODE_SOLID_COLOR = 1; // 0x1 + field public static final int SHADING_MODE_FAST = 1; // 0x1 + field public static final int SHADING_MODE_HIGH_QUALITY = 2; // 0x2 + field public static final int SHADING_MODE_OFF = 0; // 0x0 + field public static final int STATISTICS_FACE_DETECT_MODE_FULL = 2; // 0x2 + field public static final int STATISTICS_FACE_DETECT_MODE_OFF = 0; // 0x0 + field public static final int STATISTICS_FACE_DETECT_MODE_SIMPLE = 1; // 0x1 + field public static final int STATISTICS_LENS_SHADING_MAP_MODE_OFF = 0; // 0x0 + field public static final int STATISTICS_LENS_SHADING_MAP_MODE_ON = 1; // 0x1 + field public static final int STATISTICS_SCENE_FLICKER_50HZ = 1; // 0x1 + field public static final int STATISTICS_SCENE_FLICKER_60HZ = 2; // 0x2 + field public static final int STATISTICS_SCENE_FLICKER_NONE = 0; // 0x0 + field public static final int SYNC_MAX_LATENCY_PER_FRAME_CONTROL = 0; // 0x0 + field public static final int SYNC_MAX_LATENCY_UNKNOWN = -1; // 0xffffffff + field public static final int TONEMAP_MODE_CONTRAST_CURVE = 0; // 0x0 + field public static final int TONEMAP_MODE_FAST = 1; // 0x1 + field public static final int TONEMAP_MODE_HIGH_QUALITY = 2; // 0x2 + } + + public class CaptureFailure { + method public long getFrameNumber(); + method public int getReason(); + method public android.hardware.camera2.CaptureRequest getRequest(); + method public int getSequenceId(); + method public boolean wasImageCaptured(); + field public static final int REASON_ERROR = 0; // 0x0 + field public static final int REASON_FLUSHED = 1; // 0x1 + } + + public final class CaptureRequest extends android.hardware.camera2.CameraMetadata implements android.os.Parcelable { + method public int describeContents(); + method public T get(android.hardware.camera2.CaptureRequest.Key<T>); + method public java.lang.Object getTag(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.hardware.camera2.CaptureRequest.Key BLACK_LEVEL_LOCK; + field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_ABERRATION_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_GAINS; + field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_TRANSFORM; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_ANTIBANDING_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_EXPOSURE_COMPENSATION; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_LOCK; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_PRECAPTURE_TRIGGER; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_REGIONS; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_TARGET_FPS_RANGE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AF_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AF_REGIONS; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AF_TRIGGER; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AWB_LOCK; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AWB_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AWB_REGIONS; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_CAPTURE_INTENT; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_EFFECT_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_SCENE_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_VIDEO_STABILIZATION_MODE; + field public static final android.os.Parcelable.Creator CREATOR; + field public static final android.hardware.camera2.CaptureRequest.Key EDGE_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key FLASH_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key HOT_PIXEL_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key JPEG_GPS_LOCATION; + field public static final android.hardware.camera2.CaptureRequest.Key JPEG_ORIENTATION; + field public static final android.hardware.camera2.CaptureRequest.Key JPEG_QUALITY; + field public static final android.hardware.camera2.CaptureRequest.Key JPEG_THUMBNAIL_QUALITY; + field public static final android.hardware.camera2.CaptureRequest.Key JPEG_THUMBNAIL_SIZE; + field public static final android.hardware.camera2.CaptureRequest.Key LENS_APERTURE; + field public static final android.hardware.camera2.CaptureRequest.Key LENS_FILTER_DENSITY; + field public static final android.hardware.camera2.CaptureRequest.Key LENS_FOCAL_LENGTH; + field public static final android.hardware.camera2.CaptureRequest.Key LENS_FOCUS_DISTANCE; + field public static final android.hardware.camera2.CaptureRequest.Key LENS_OPTICAL_STABILIZATION_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key NOISE_REDUCTION_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key SCALER_CROP_REGION; + field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_EXPOSURE_TIME; + field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_FRAME_DURATION; + field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_SENSITIVITY; + field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_TEST_PATTERN_DATA; + field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_TEST_PATTERN_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key SHADING_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key STATISTICS_FACE_DETECT_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key STATISTICS_HOT_PIXEL_MAP_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key STATISTICS_LENS_SHADING_MAP_MODE; + field public static final android.hardware.camera2.CaptureRequest.Key TONEMAP_CURVE; + field public static final android.hardware.camera2.CaptureRequest.Key TONEMAP_MODE; + } + + public static final class CaptureRequest.Builder { + method public void addTarget(android.view.Surface); + method public android.hardware.camera2.CaptureRequest build(); + method public T get(android.hardware.camera2.CaptureRequest.Key<T>); + method public void removeTarget(android.view.Surface); + method public void set(android.hardware.camera2.CaptureRequest.Key<T>, T); + method public void setTag(java.lang.Object); + } + + public static final class CaptureRequest.Key { + method public final boolean equals(java.lang.Object); + method public java.lang.String getName(); + method public final int hashCode(); + } + + public class CaptureResult extends android.hardware.camera2.CameraMetadata { + method public T get(android.hardware.camera2.CaptureResult.Key<T>); + method public long getFrameNumber(); + method public android.hardware.camera2.CaptureRequest getRequest(); + method public int getSequenceId(); + field public static final android.hardware.camera2.CaptureResult.Key BLACK_LEVEL_LOCK; + field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_ABERRATION_MODE; + field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_GAINS; + field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_MODE; + field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_TRANSFORM; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_ANTIBANDING_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_EXPOSURE_COMPENSATION; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_LOCK; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_PRECAPTURE_TRIGGER; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_REGIONS; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_STATE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_TARGET_FPS_RANGE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_REGIONS; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_STATE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_TRIGGER; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_LOCK; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_REGIONS; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_STATE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_CAPTURE_INTENT; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_EFFECT_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_SCENE_MODE; + field public static final android.hardware.camera2.CaptureResult.Key CONTROL_VIDEO_STABILIZATION_MODE; + field public static final android.hardware.camera2.CaptureResult.Key EDGE_MODE; + field public static final android.hardware.camera2.CaptureResult.Key FLASH_MODE; + field public static final android.hardware.camera2.CaptureResult.Key FLASH_STATE; + field public static final android.hardware.camera2.CaptureResult.Key HOT_PIXEL_MODE; + field public static final android.hardware.camera2.CaptureResult.Key JPEG_GPS_LOCATION; + field public static final android.hardware.camera2.CaptureResult.Key JPEG_ORIENTATION; + field public static final android.hardware.camera2.CaptureResult.Key JPEG_QUALITY; + field public static final android.hardware.camera2.CaptureResult.Key JPEG_THUMBNAIL_QUALITY; + field public static final android.hardware.camera2.CaptureResult.Key JPEG_THUMBNAIL_SIZE; + field public static final android.hardware.camera2.CaptureResult.Key LENS_APERTURE; + field public static final android.hardware.camera2.CaptureResult.Key LENS_FILTER_DENSITY; + field public static final android.hardware.camera2.CaptureResult.Key LENS_FOCAL_LENGTH; + field public static final android.hardware.camera2.CaptureResult.Key LENS_FOCUS_DISTANCE; + field public static final android.hardware.camera2.CaptureResult.Key LENS_FOCUS_RANGE; + field public static final android.hardware.camera2.CaptureResult.Key LENS_OPTICAL_STABILIZATION_MODE; + field public static final android.hardware.camera2.CaptureResult.Key LENS_STATE; + field public static final android.hardware.camera2.CaptureResult.Key NOISE_REDUCTION_MODE; + field public static final android.hardware.camera2.CaptureResult.Key REQUEST_PIPELINE_DEPTH; + field public static final android.hardware.camera2.CaptureResult.Key SCALER_CROP_REGION; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_EXPOSURE_TIME; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_FRAME_DURATION; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_GREEN_SPLIT; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_NEUTRAL_COLOR_POINT; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_NOISE_PROFILE; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_ROLLING_SHUTTER_SKEW; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_SENSITIVITY; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_TEST_PATTERN_DATA; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_TEST_PATTERN_MODE; + field public static final android.hardware.camera2.CaptureResult.Key SENSOR_TIMESTAMP; + field public static final android.hardware.camera2.CaptureResult.Key SHADING_MODE; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_FACES; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_FACE_DETECT_MODE; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_HOT_PIXEL_MAP; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_HOT_PIXEL_MAP_MODE; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_CORRECTION_MAP; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_MAP_MODE; + field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_SCENE_FLICKER; + field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_CURVE; + field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_MODE; + } + + public static final class CaptureResult.Key { + method public final boolean equals(java.lang.Object); + method public java.lang.String getName(); + method public final int hashCode(); + } + + public final class DngCreator implements java.lang.AutoCloseable { + ctor public DngCreator(android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CaptureResult); + method public void close(); + method public android.hardware.camera2.DngCreator setDescription(java.lang.String); + method public android.hardware.camera2.DngCreator setLocation(android.location.Location); + method public android.hardware.camera2.DngCreator setOrientation(int); + method public android.hardware.camera2.DngCreator setThumbnail(android.graphics.Bitmap); + method public android.hardware.camera2.DngCreator setThumbnail(android.media.Image); + method public void writeByteBuffer(java.io.OutputStream, android.util.Size, java.nio.ByteBuffer, long) throws java.io.IOException; + method public void writeImage(java.io.OutputStream, android.media.Image) throws java.io.IOException; + method public void writeInputStream(java.io.OutputStream, android.util.Size, java.io.InputStream, long) throws java.io.IOException; + field public static final int MAX_THUMBNAIL_DIMENSION = 256; // 0x100 + } + + public final class TotalCaptureResult extends android.hardware.camera2.CaptureResult { + method public java.util.List<android.hardware.camera2.CaptureResult> getPartialResults(); + } + +} + +package android.hardware.camera2.params { + + public final class BlackLevelPattern { + method public void copyTo(int[], int); + method public int getOffsetForIndex(int, int); + field public static final int COUNT = 4; // 0x4 + } + + public final class ColorSpaceTransform { + ctor public ColorSpaceTransform(android.util.Rational[]); + ctor public ColorSpaceTransform(int[]); + method public void copyElements(android.util.Rational[], int); + method public void copyElements(int[], int); + method public android.util.Rational getElement(int, int); + } + + public final class Face { + method public android.graphics.Rect getBounds(); + method public int getId(); + method public android.graphics.Point getLeftEyePosition(); + method public android.graphics.Point getMouthPosition(); + method public android.graphics.Point getRightEyePosition(); + method public int getScore(); + field public static final int ID_UNSUPPORTED = -1; // 0xffffffff + field public static final int SCORE_MAX = 100; // 0x64 + field public static final int SCORE_MIN = 1; // 0x1 + } + + public final class LensShadingMap { + method public void copyGainFactors(float[], int); + method public int getColumnCount(); + method public float getGainFactor(int, int, int); + method public int getGainFactorCount(); + method public android.hardware.camera2.params.RggbChannelVector getGainFactorVector(int, int); + method public int getRowCount(); + field public static final float MINIMUM_GAIN_FACTOR = 1.0f; + } + + public final class MeteringRectangle { + ctor public MeteringRectangle(int, int, int, int, int); + ctor public MeteringRectangle(android.graphics.Point, android.util.Size, int); + ctor public MeteringRectangle(android.graphics.Rect, int); + method public boolean equals(android.hardware.camera2.params.MeteringRectangle); + method public int getHeight(); + method public int getMeteringWeight(); + method public android.graphics.Rect getRect(); + method public android.util.Size getSize(); + method public android.graphics.Point getUpperLeftPoint(); + method public int getWidth(); + method public int getX(); + method public int getY(); + field public static final int METERING_WEIGHT_DONT_CARE = 0; // 0x0 + field public static final int METERING_WEIGHT_MAX = 1000; // 0x3e8 + field public static final int METERING_WEIGHT_MIN = 0; // 0x0 + } + + public final class RggbChannelVector { + ctor public RggbChannelVector(float, float, float, float); + method public void copyTo(float[], int); + method public float getBlue(); + method public float getComponent(int); + method public float getGreenEven(); + method public float getGreenOdd(); + method public final float getRed(); + field public static final int BLUE = 3; // 0x3 + field public static final int COUNT = 4; // 0x4 + field public static final int GREEN_EVEN = 1; // 0x1 + field public static final int GREEN_ODD = 2; // 0x2 + field public static final int RED = 0; // 0x0 + } + + public final class StreamConfigurationMap { + method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRanges(); + method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size); + method public android.util.Size[] getHighSpeedVideoSizes(); + method public android.util.Size[] getHighSpeedVideoSizesFor(android.util.Range<java.lang.Integer>); + method public final int[] getOutputFormats(); + method public long getOutputMinFrameDuration(int, android.util.Size); + method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size); + method public android.util.Size[] getOutputSizes(java.lang.Class<T>); + method public android.util.Size[] getOutputSizes(int); + method public long getOutputStallDuration(int, android.util.Size); + method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size); + method public boolean isOutputSupportedFor(int); + method public static boolean isOutputSupportedFor(java.lang.Class<T>); + method public boolean isOutputSupportedFor(android.view.Surface); + } + + public final class TonemapCurve { + ctor public TonemapCurve(float[], float[], float[]); + method public void copyColorCurve(int, float[], int); + method public android.graphics.PointF getPoint(int, int); + method public int getPointCount(int); + field public static final int CHANNEL_BLUE = 2; // 0x2 + field public static final int CHANNEL_GREEN = 1; // 0x1 + field public static final int CHANNEL_RED = 0; // 0x0 + field public static final float LEVEL_BLACK = 0.0f; + field public static final float LEVEL_WHITE = 1.0f; + field public static final int POINT_SIZE = 2; // 0x2 + } + +} + package android.hardware.display { public final class DisplayManager { method public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, android.view.Surface, int); + method public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, android.view.Surface, int, android.hardware.display.VirtualDisplay.Callback, android.os.Handler); method public android.view.Display getDisplay(int); method public android.view.Display[] getDisplays(); method public android.view.Display[] getDisplays(java.lang.String); method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler); method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener); field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION"; + field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10 field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8 field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2 field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1 @@ -11039,9 +13153,17 @@ method public android.view.Display getDisplay(); method public android.view.Surface getSurface(); method public void release(); + method public void resize(int, int, int); method public void setSurface(android.view.Surface); } + public static abstract class VirtualDisplay.Callback { + ctor public VirtualDisplay.Callback(); + method public void onPaused(); + method public void onResumed(); + method public void onStopped(); + } + } package android.hardware.input { @@ -11063,64 +13185,6 @@ } -package android.hardware.location { - - public final class GeofenceHardware { - method public boolean addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback); - method public int[] getMonitoringTypes(); - method public int getStatusOfMonitoringType(int); - method public boolean pauseGeofence(int, int); - method public boolean registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback); - method public boolean removeGeofence(int, int); - method public boolean resumeGeofence(int, int, int); - method public boolean unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback); - field public static final int GEOFENCE_ENTERED = 1; // 0x1 - field public static final int GEOFENCE_ERROR_ID_EXISTS = 2; // 0x2 - field public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3; // 0x3 - field public static final int GEOFENCE_ERROR_INVALID_TRANSITION = 4; // 0x4 - field public static final int GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 1; // 0x1 - field public static final int GEOFENCE_EXITED = 2; // 0x2 - field public static final int GEOFENCE_FAILURE = 5; // 0x5 - field public static final int GEOFENCE_SUCCESS = 0; // 0x0 - field public static final int GEOFENCE_UNCERTAIN = 4; // 0x4 - field public static final int MONITORING_TYPE_GPS_HARDWARE = 0; // 0x0 - field public static final int MONITOR_CURRENTLY_AVAILABLE = 0; // 0x0 - field public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1; // 0x1 - field public static final int MONITOR_UNSUPPORTED = 2; // 0x2 - } - - public abstract class GeofenceHardwareCallback { - ctor public GeofenceHardwareCallback(); - method public void onGeofenceAdd(int, int); - method public void onGeofencePause(int, int); - method public void onGeofenceRemove(int, int); - method public void onGeofenceResume(int, int); - method public void onGeofenceTransition(int, int, android.location.Location, long, int); - } - - public abstract class GeofenceHardwareMonitorCallback { - ctor public GeofenceHardwareMonitorCallback(); - method public void onMonitoringSystemChange(int, boolean, android.location.Location); - } - - public final class GeofenceHardwareRequest { - ctor public GeofenceHardwareRequest(); - method public static android.hardware.location.GeofenceHardwareRequest createCircularGeofence(double, double, double); - method public int getLastTransition(); - method public double getLatitude(); - method public double getLongitude(); - method public int getMonitorTransitions(); - method public int getNotificationResponsiveness(); - method public double getRadius(); - method public int getUnknownTimer(); - method public void setLastTransition(int); - method public void setMonitorTransitions(int); - method public void setNotificationResponsiveness(int); - method public void setUnknownTimer(int); - } - -} - package android.hardware.usb { public class UsbAccessory implements android.os.Parcelable { @@ -11135,6 +13199,19 @@ field public static final android.os.Parcelable.Creator CREATOR; } + public class UsbConfiguration implements android.os.Parcelable { + method public int describeContents(); + method public int getId(); + method public android.hardware.usb.UsbInterface getInterface(int); + method public int getInterfaceCount(); + method public int getMaxPower(); + method public java.lang.String getName(); + method public boolean isRemoteWakeup(); + method public boolean isSelfPowered(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public final class UsbConstants { ctor public UsbConstants(); field public static final int USB_CLASS_APP_SPEC = 254; // 0xfe @@ -11174,6 +13251,8 @@ public class UsbDevice implements android.os.Parcelable { method public int describeContents(); + method public android.hardware.usb.UsbConfiguration getConfiguration(int); + method public int getConfigurationCount(); method public int getDeviceClass(); method public int getDeviceId(); method public static int getDeviceId(java.lang.String); @@ -11183,7 +13262,10 @@ method public int getDeviceSubclass(); method public android.hardware.usb.UsbInterface getInterface(int); method public int getInterfaceCount(); + method public java.lang.String getManufacturerName(); method public int getProductId(); + method public java.lang.String getProductName(); + method public java.lang.String getSerialNumber(); method public int getVendorId(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -11201,6 +13283,8 @@ method public java.lang.String getSerial(); method public boolean releaseInterface(android.hardware.usb.UsbInterface); method public android.hardware.usb.UsbRequest requestWait(); + method public boolean setConfiguration(android.hardware.usb.UsbConfiguration); + method public boolean setInterface(android.hardware.usb.UsbInterface); } public class UsbEndpoint implements android.os.Parcelable { @@ -11218,12 +13302,14 @@ public class UsbInterface implements android.os.Parcelable { method public int describeContents(); + method public int getAlternateSetting(); method public android.hardware.usb.UsbEndpoint getEndpoint(int); method public int getEndpointCount(); method public int getId(); method public int getInterfaceClass(); method public int getInterfaceProtocol(); method public int getInterfaceSubclass(); + method public java.lang.String getName(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; } @@ -11293,6 +13379,7 @@ ctor public ExtractEditText(android.content.Context); ctor public ExtractEditText(android.content.Context, android.util.AttributeSet); ctor public ExtractEditText(android.content.Context, android.util.AttributeSet, int); + ctor public ExtractEditText(android.content.Context, android.util.AttributeSet, int, int); method public void finishInternalChanges(); method public boolean hasVerticalScrollBar(); method public void startInternalChanges(); @@ -11300,13 +13387,14 @@ public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService { ctor public InputMethodService(); - method public boolean enableHardwareAcceleration(); + method public deprecated boolean enableHardwareAcceleration(); method public int getBackDisposition(); method public int getCandidatesHiddenVisibility(); method public android.view.inputmethod.InputBinding getCurrentInputBinding(); method public android.view.inputmethod.InputConnection getCurrentInputConnection(); method public android.view.inputmethod.EditorInfo getCurrentInputEditorInfo(); method public boolean getCurrentInputStarted(); + method public int getInputMethodWindowRecommendedHeight(); method public android.view.LayoutInflater getLayoutInflater(); method public int getMaxWidth(); method public java.lang.CharSequence getTextForImeAction(int); @@ -11348,7 +13436,8 @@ method public void onStartInput(android.view.inputmethod.EditorInfo, boolean); method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean); method public void onUnbindInput(); - method public void onUpdateCursor(android.graphics.Rect); + method public deprecated void onUpdateCursor(android.graphics.Rect); + method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo); method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText); method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo); method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo); @@ -11395,6 +13484,7 @@ method public void finishInput(); method public void toggleSoftInput(int, int); method public void updateCursor(android.graphics.Rect); + method public void updateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo); method public void updateExtractedText(int, android.view.inputmethod.ExtractedText); method public void updateSelection(int, int, int, int, int, int); method public void viewClicked(boolean); @@ -11489,6 +13579,7 @@ public class KeyboardView extends android.view.View implements android.view.View.OnClickListener { ctor public KeyboardView(android.content.Context, android.util.AttributeSet); ctor public KeyboardView(android.content.Context, android.util.AttributeSet, int); + ctor public KeyboardView(android.content.Context, android.util.AttributeSet, int, int); method public void closing(); method public android.inputmethodservice.Keyboard getKeyboard(); method protected android.inputmethodservice.KeyboardView.OnKeyboardActionListener getOnKeyboardActionListener(); @@ -11776,7 +13867,7 @@ ctor public SettingInjectorService(java.lang.String); method public final android.os.IBinder onBind(android.content.Intent); method protected abstract boolean onGetEnabled(); - method protected abstract java.lang.String onGetSummary(); + method protected abstract deprecated java.lang.String onGetSummary(); method public final void onStart(android.content.Intent, int); method public final int onStartCommand(android.content.Intent, int, int); field public static final java.lang.String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged"; @@ -11795,8 +13886,51 @@ method public void stop(); } + public final class AudioAttributes implements android.os.Parcelable { + method public int describeContents(); + method public int getContentType(); + method public int getFlags(); + method public int getUsage(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3 + field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2 + field public static final int CONTENT_TYPE_SONIFICATION = 4; // 0x4 + field public static final int CONTENT_TYPE_SPEECH = 1; // 0x1 + field public static final int CONTENT_TYPE_UNKNOWN = 0; // 0x0 + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1 + field public static final int FLAG_HW_AV_SYNC = 16; // 0x10 + field public static final int USAGE_ALARM = 4; // 0x4 + field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb + field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc + field public static final int USAGE_ASSISTANCE_SONIFICATION = 13; // 0xd + field public static final int USAGE_GAME = 14; // 0xe + field public static final int USAGE_MEDIA = 1; // 0x1 + field public static final int USAGE_NOTIFICATION = 5; // 0x5 + field public static final int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9; // 0x9 + field public static final int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8; // 0x8 + field public static final int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7; // 0x7 + field public static final int USAGE_NOTIFICATION_EVENT = 10; // 0xa + field public static final int USAGE_NOTIFICATION_RINGTONE = 6; // 0x6 + field public static final int USAGE_UNKNOWN = 0; // 0x0 + field public static final int USAGE_VOICE_COMMUNICATION = 2; // 0x2 + field public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3; // 0x3 + } + + public static class AudioAttributes.Builder { + ctor public AudioAttributes.Builder(); + ctor public AudioAttributes.Builder(android.media.AudioAttributes); + method public android.media.AudioAttributes build(); + method public android.media.AudioAttributes.Builder setContentType(int); + method public android.media.AudioAttributes.Builder setFlags(int); + method public android.media.AudioAttributes.Builder setLegacyStreamType(int); + method public android.media.AudioAttributes.Builder setUsage(int); + } + public class AudioFormat { - ctor public AudioFormat(); + method public int getChannelMask(); + method public int getEncoding(); + method public int getSampleRate(); field public static final deprecated int CHANNEL_CONFIGURATION_DEFAULT = 1; // 0x1 field public static final deprecated int CHANNEL_CONFIGURATION_INVALID = 0; // 0x0 field public static final deprecated int CHANNEL_CONFIGURATION_MONO = 2; // 0x2 @@ -11833,12 +13967,26 @@ field public static final int CHANNEL_OUT_LOW_FREQUENCY = 32; // 0x20 field public static final int CHANNEL_OUT_MONO = 4; // 0x4 field public static final int CHANNEL_OUT_QUAD = 204; // 0xcc + field public static final int CHANNEL_OUT_SIDE_LEFT = 2048; // 0x800 + field public static final int CHANNEL_OUT_SIDE_RIGHT = 4096; // 0x1000 field public static final int CHANNEL_OUT_STEREO = 12; // 0xc field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c + field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_DEFAULT = 1; // 0x1 + field public static final int ENCODING_E_AC3 = 6; // 0x6 field public static final int ENCODING_INVALID = 0; // 0x0 field public static final int ENCODING_PCM_16BIT = 2; // 0x2 field public static final int ENCODING_PCM_8BIT = 3; // 0x3 + field public static final int ENCODING_PCM_FLOAT = 4; // 0x4 + } + + public static class AudioFormat.Builder { + ctor public AudioFormat.Builder(); + ctor public AudioFormat.Builder(android.media.AudioFormat); + method public android.media.AudioFormat build(); + method public android.media.AudioFormat.Builder setChannelMask(int); + method public android.media.AudioFormat.Builder setEncoding(int) throws java.lang.IllegalArgumentException; + method public android.media.AudioFormat.Builder setSampleRate(int) throws java.lang.IllegalArgumentException; } public class AudioManager { @@ -11847,6 +13995,7 @@ method public void adjustSuggestedStreamVolume(int, int, int); method public void adjustVolume(int, int); method public void dispatchMediaKeyEvent(android.view.KeyEvent); + method public int generateAudioSessionId(); method public int getMode(); method public java.lang.String getParameters(java.lang.String); method public java.lang.String getProperty(java.lang.String); @@ -11861,14 +14010,15 @@ method public boolean isMicrophoneMute(); method public boolean isMusicActive(); method public boolean isSpeakerphoneOn(); + method public boolean isVolumeFixed(); method public deprecated boolean isWiredHeadsetOn(); method public void loadSoundEffects(); method public void playSoundEffect(int); method public void playSoundEffect(int, float); - method public void registerMediaButtonEventReceiver(android.content.ComponentName); - method public void registerMediaButtonEventReceiver(android.app.PendingIntent); - method public void registerRemoteControlClient(android.media.RemoteControlClient); - method public boolean registerRemoteController(android.media.RemoteController); + method public deprecated void registerMediaButtonEventReceiver(android.content.ComponentName); + method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent); + method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient); + method public deprecated boolean registerRemoteController(android.media.RemoteController); method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int); method public deprecated void setBluetoothA2dpOn(boolean); method public void setBluetoothScoOn(boolean); @@ -11887,11 +14037,13 @@ method public void startBluetoothSco(); method public void stopBluetoothSco(); method public void unloadSoundEffects(); - method public void unregisterMediaButtonEventReceiver(android.content.ComponentName); - method public void unregisterMediaButtonEventReceiver(android.app.PendingIntent); - method public void unregisterRemoteControlClient(android.media.RemoteControlClient); - method public void unregisterRemoteController(android.media.RemoteController); + method public deprecated void unregisterMediaButtonEventReceiver(android.content.ComponentName); + method public deprecated void unregisterMediaButtonEventReceiver(android.app.PendingIntent); + method public deprecated void unregisterRemoteControlClient(android.media.RemoteControlClient); + method public deprecated void unregisterRemoteController(android.media.RemoteController); field public static final java.lang.String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY"; + field public static final java.lang.String ACTION_HDMI_AUDIO_PLUG = "android.media.action.HDMI_AUDIO_PLUG"; + field public static final java.lang.String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG"; field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED"; field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED"; field public static final int ADJUST_LOWER = -1; // 0xffffffff @@ -11906,6 +14058,12 @@ field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0 field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1 + field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0 + field public static final int ERROR = -1; // 0xffffffff + field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa + field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE"; + field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS"; + field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT"; field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE"; field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"; field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE"; @@ -12018,6 +14176,7 @@ public class AudioTrack { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException; + ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public int attachAuxEffect(int); method public void flush(); method public int getAudioFormat(); @@ -12051,10 +14210,13 @@ method public int setPlaybackRate(int); method public int setPositionNotificationPeriod(int); method protected deprecated void setState(int); - method public int setStereoVolume(float, float); + method public deprecated int setStereoVolume(float, float); + method public int setVolume(float); method public void stop() throws java.lang.IllegalStateException; method public int write(byte[], int, int); method public int write(short[], int, int); + method public int write(float[], int, int, int); + method public int write(java.nio.ByteBuffer, int, int); field public static final int ERROR = -1; // 0xffffffff field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd @@ -12067,6 +14229,8 @@ field public static final int STATE_NO_STATIC_DATA = 2; // 0x2 field public static final int STATE_UNINITIALIZED = 0; // 0x0 field public static final int SUCCESS = 0; // 0x0 + field public static final int WRITE_BLOCKING = 0; // 0x0 + field public static final int WRITE_NON_BLOCKING = 1; // 0x1 } public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener { @@ -12080,14 +14244,22 @@ method public static boolean hasProfile(int); method public static boolean hasProfile(int, int); field public static final int QUALITY_1080P = 6; // 0x6 + field public static final int QUALITY_2160P = 8; // 0x8 field public static final int QUALITY_480P = 4; // 0x4 field public static final int QUALITY_720P = 5; // 0x5 field public static final int QUALITY_CIF = 3; // 0x3 field public static final int QUALITY_HIGH = 1; // 0x1 + field public static final int QUALITY_HIGH_SPEED_1080P = 2004; // 0x7d4 + field public static final int QUALITY_HIGH_SPEED_2160P = 2005; // 0x7d5 + field public static final int QUALITY_HIGH_SPEED_480P = 2002; // 0x7d2 + field public static final int QUALITY_HIGH_SPEED_720P = 2003; // 0x7d3 + field public static final int QUALITY_HIGH_SPEED_HIGH = 2001; // 0x7d1 + field public static final int QUALITY_HIGH_SPEED_LOW = 2000; // 0x7d0 field public static final int QUALITY_LOW = 0; // 0x0 field public static final int QUALITY_QCIF = 2; // 0x2 field public static final int QUALITY_QVGA = 7; // 0x7 field public static final int QUALITY_TIME_LAPSE_1080P = 1006; // 0x3ee + field public static final int QUALITY_TIME_LAPSE_2160P = 1008; // 0x3f0 field public static final int QUALITY_TIME_LAPSE_480P = 1004; // 0x3ec field public static final int QUALITY_TIME_LAPSE_720P = 1005; // 0x3ed field public static final int QUALITY_TIME_LAPSE_CIF = 1003; // 0x3eb @@ -12185,11 +14357,13 @@ public abstract class Image implements java.lang.AutoCloseable { method public abstract void close(); + method public android.graphics.Rect getCropRect(); method public abstract int getFormat(); method public abstract int getHeight(); method public abstract android.media.Image.Plane[] getPlanes(); method public abstract long getTimestamp(); method public abstract int getWidth(); + method public void setCropRect(android.graphics.Rect); } public static abstract class Image.Plane { @@ -12256,22 +14430,31 @@ public final class MediaCodec { method public void configure(android.media.MediaFormat, android.view.Surface, android.media.MediaCrypto, int); - method public static android.media.MediaCodec createByCodecName(java.lang.String); - method public static android.media.MediaCodec createDecoderByType(java.lang.String); - method public static android.media.MediaCodec createEncoderByType(java.lang.String); + method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException; + method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException; + method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException; method public final android.view.Surface createInputSurface(); method public final int dequeueInputBuffer(long); method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long); method public final void flush(); method public android.media.MediaCodecInfo getCodecInfo(); - method public java.nio.ByteBuffer[] getInputBuffers(); + method public java.nio.ByteBuffer getInputBuffer(int); + method public deprecated java.nio.ByteBuffer[] getInputBuffers(); + method public final android.media.MediaFormat getInputFormat(); + method public android.media.Image getInputImage(int); method public final java.lang.String getName(); - method public java.nio.ByteBuffer[] getOutputBuffers(); + method public java.nio.ByteBuffer getOutputBuffer(int); + method public deprecated java.nio.ByteBuffer[] getOutputBuffers(); method public final android.media.MediaFormat getOutputFormat(); + method public final android.media.MediaFormat getOutputFormat(int); + method public android.media.Image getOutputImage(int); method public final void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException; method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException; method public final void release(); method public final void releaseOutputBuffer(int, boolean); + method public final void releaseOutputBuffer(int, long); + method public final void reset(); + method public void setCallback(android.media.MediaCodec.Callback); method public final void setParameters(android.os.Bundle); method public final void setVideoScalingMode(int); method public final void signalEndOfInputStream(); @@ -12279,11 +14462,12 @@ method public final void stop(); field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2 field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4 - field public static final int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1 + field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1 + field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1 field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1 field public static final int CRYPTO_MODE_AES_CTR = 1; // 0x1 field public static final int CRYPTO_MODE_UNENCRYPTED = 0; // 0x0 - field public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd + field public static final deprecated int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd field public static final int INFO_OUTPUT_FORMAT_CHANGED = -2; // 0xfffffffe field public static final int INFO_TRY_AGAIN_LATER = -1; // 0xffffffff field public static final java.lang.String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync"; @@ -12302,9 +14486,24 @@ field public int size; } + public static abstract class MediaCodec.Callback { + ctor public MediaCodec.Callback(); + method public abstract void onError(android.media.MediaCodec, android.media.MediaCodec.CodecException); + method public abstract void onInputBufferAvailable(android.media.MediaCodec, int); + method public abstract void onOutputBufferAvailable(android.media.MediaCodec, int, android.media.MediaCodec.BufferInfo); + method public abstract void onOutputFormatChanged(android.media.MediaCodec, android.media.MediaFormat); + } + + public static final class MediaCodec.CodecException extends java.lang.IllegalStateException { + method public java.lang.String getDiagnosticInfo(); + method public boolean isRecoverable(); + method public boolean isTransient(); + } + public static final class MediaCodec.CryptoException extends java.lang.RuntimeException { ctor public MediaCodec.CryptoException(int, java.lang.String); method public int getErrorCode(); + field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4 field public static final int ERROR_KEY_EXPIRED = 2; // 0x2 field public static final int ERROR_NO_KEY = 1; // 0x1 field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3 @@ -12328,9 +14527,25 @@ method public final boolean isEncoder(); } + public static final class MediaCodecInfo.AudioCapabilities { + method public android.util.Range<java.lang.Integer> getBitrateRange(); + method public int getMaxInputChannelCount(); + method public android.util.Range<java.lang.Integer>[] getSupportedSampleRateRanges(); + method public int[] getSupportedSampleRates(); + method public boolean isSampleRateSupported(int); + } + public static final class MediaCodecInfo.CodecCapabilities { ctor public MediaCodecInfo.CodecCapabilities(); + method public static android.media.MediaCodecInfo.CodecCapabilities createFromProfileLevel(java.lang.String, int, int); + method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities(); + method public android.media.MediaFormat getDefaultFormat(); + method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities(); + method public java.lang.String getMimeType(); + method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities(); + method public final boolean isFeatureRequired(java.lang.String); method public final boolean isFeatureSupported(java.lang.String); + method public final boolean isFormatSupported(android.media.MediaFormat); field public static final int COLOR_Format12bitRGB444 = 3; // 0x3 field public static final int COLOR_Format16bitARGB1555 = 5; // 0x5 field public static final int COLOR_Format16bitARGB4444 = 4; // 0x4 @@ -12366,6 +14581,7 @@ field public static final int COLOR_FormatYCrYCb = 26; // 0x1a field public static final int COLOR_FormatYUV411PackedPlanar = 18; // 0x12 field public static final int COLOR_FormatYUV411Planar = 17; // 0x11 + field public static final int COLOR_FormatYUV420Flexible = 2135033992; // 0x7f420888 field public static final int COLOR_FormatYUV420PackedPlanar = 20; // 0x14 field public static final int COLOR_FormatYUV420PackedSemiPlanar = 39; // 0x27 field public static final int COLOR_FormatYUV420Planar = 19; // 0x13 @@ -12378,6 +14594,8 @@ field public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00 field public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100 field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback"; + field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback"; + field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback"; field public int[] colorFormats; field public android.media.MediaCodecInfo.CodecProfileLevel[] profileLevels; } @@ -12410,6 +14628,7 @@ field public static final int AVCLevel42 = 8192; // 0x2000 field public static final int AVCLevel5 = 16384; // 0x4000 field public static final int AVCLevel51 = 32768; // 0x8000 + field public static final int AVCLevel52 = 65536; // 0x10000 field public static final int AVCProfileBaseline = 1; // 0x1 field public static final int AVCProfileExtended = 4; // 0x4 field public static final int AVCProfileHigh = 8; // 0x8 @@ -12434,6 +14653,34 @@ field public static final int H263ProfileISWV3 = 16; // 0x10 field public static final int H263ProfileInterlace = 128; // 0x80 field public static final int H263ProfileInternet = 64; // 0x40 + field public static final int HEVCHighTierLevel1 = 2; // 0x2 + field public static final int HEVCHighTierLevel2 = 8; // 0x8 + field public static final int HEVCHighTierLevel21 = 32; // 0x20 + field public static final int HEVCHighTierLevel3 = 128; // 0x80 + field public static final int HEVCHighTierLevel31 = 512; // 0x200 + field public static final int HEVCHighTierLevel4 = 2048; // 0x800 + field public static final int HEVCHighTierLevel41 = 8192; // 0x2000 + field public static final int HEVCHighTierLevel5 = 32768; // 0x8000 + field public static final int HEVCHighTierLevel51 = 131072; // 0x20000 + field public static final int HEVCHighTierLevel52 = 524288; // 0x80000 + field public static final int HEVCHighTierLevel6 = 2097152; // 0x200000 + field public static final int HEVCHighTierLevel61 = 8388608; // 0x800000 + field public static final int HEVCHighTierLevel62 = 33554432; // 0x2000000 + field public static final int HEVCMainTierLevel1 = 1; // 0x1 + field public static final int HEVCMainTierLevel2 = 4; // 0x4 + field public static final int HEVCMainTierLevel21 = 16; // 0x10 + field public static final int HEVCMainTierLevel3 = 64; // 0x40 + field public static final int HEVCMainTierLevel31 = 256; // 0x100 + field public static final int HEVCMainTierLevel4 = 1024; // 0x400 + field public static final int HEVCMainTierLevel41 = 4096; // 0x1000 + field public static final int HEVCMainTierLevel5 = 16384; // 0x4000 + field public static final int HEVCMainTierLevel51 = 65536; // 0x10000 + field public static final int HEVCMainTierLevel52 = 262144; // 0x40000 + field public static final int HEVCMainTierLevel6 = 1048576; // 0x100000 + field public static final int HEVCMainTierLevel61 = 4194304; // 0x400000 + field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000 + field public static final int HEVCProfileMain = 1; // 0x1 + field public static final int HEVCProfileMain10 = 2; // 0x2 field public static final int MPEG4Level0 = 1; // 0x1 field public static final int MPEG4Level0b = 2; // 0x2 field public static final int MPEG4Level1 = 4; // 0x4 @@ -12467,9 +14714,37 @@ field public int profile; } + public static final class MediaCodecInfo.EncoderCapabilities { + method public android.util.Range<java.lang.Integer> getComplexityRange(); + method public boolean isBitrateModeSupported(int); + field public static final int BITRATE_MODE_CBR = 2; // 0x2 + field public static final int BITRATE_MODE_CQ = 0; // 0x0 + field public static final int BITRATE_MODE_VBR = 1; // 0x1 + } + + public static final class MediaCodecInfo.VideoCapabilities { + method public boolean areSizeAndRateSupported(int, int, double); + method public android.util.Range<java.lang.Integer> getBitrateRange(); + method public int getHeightAlignment(); + method public android.util.Range<java.lang.Integer> getSupportedFrameRates(); + method public android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int); + method public android.util.Range<java.lang.Integer> getSupportedHeights(); + method public android.util.Range<java.lang.Integer> getSupportedHeightsFor(int); + method public android.util.Range<java.lang.Integer> getSupportedWidths(); + method public android.util.Range<java.lang.Integer> getSupportedWidthsFor(int); + method public int getWidthAlignment(); + method public boolean isSizeSupported(int, int); + } + public final class MediaCodecList { - method public static final int getCodecCount(); - method public static final android.media.MediaCodecInfo getCodecInfoAt(int); + ctor public MediaCodecList(int); + method public final java.lang.String findDecoderForFormat(android.media.MediaFormat); + method public final java.lang.String findEncoderForFormat(android.media.MediaFormat); + method public static final deprecated int getCodecCount(); + method public static final deprecated android.media.MediaCodecInfo getCodecInfoAt(int); + method public final android.media.MediaCodecInfo[] getCodecInfos(); + field public static final int ALL_CODECS = 1; // 0x1 + field public static final int REGULAR_CODECS = 0; // 0x0 } public final class MediaCrypto { @@ -12483,6 +14758,31 @@ ctor public MediaCryptoException(java.lang.String); } + public class MediaDescription implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.CharSequence getDescription(); + method public android.os.Bundle getExtras(); + method public android.graphics.Bitmap getIconBitmap(); + method public android.net.Uri getIconUri(); + method public java.lang.String getMediaId(); + method public java.lang.CharSequence getSubtitle(); + method public java.lang.CharSequence getTitle(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static class MediaDescription.Builder { + ctor public MediaDescription.Builder(); + method public android.media.MediaDescription build(); + method public android.media.MediaDescription.Builder setDescription(java.lang.CharSequence); + method public android.media.MediaDescription.Builder setExtras(android.os.Bundle); + method public android.media.MediaDescription.Builder setIconBitmap(android.graphics.Bitmap); + method public android.media.MediaDescription.Builder setIconUri(android.net.Uri); + method public android.media.MediaDescription.Builder setMediaId(java.lang.String); + method public android.media.MediaDescription.Builder setSubtitle(java.lang.CharSequence); + method public android.media.MediaDescription.Builder setTitle(java.lang.CharSequence); + } + public final class MediaDrm { ctor public MediaDrm(java.util.UUID) throws android.media.UnsupportedSchemeException; method public void closeSession(byte[]); @@ -12494,7 +14794,7 @@ method public java.util.List<byte[]> getSecureStops(); method public static final boolean isCryptoSchemeSupported(java.util.UUID); method public static final boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String); - method public byte[] openSession() throws android.media.NotProvisionedException; + method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException; method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException; method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException; method public java.util.HashMap<java.lang.String, java.lang.String> queryKeyStatus(byte[]); @@ -12531,6 +14831,10 @@ method public java.lang.String getDefaultUrl(); } + public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException { + method public java.lang.String getDiagnosticInfo(); + } + public static abstract interface MediaDrm.OnEventListener { method public abstract void onEvent(android.media.MediaDrm, byte[], int, int, byte[]); } @@ -12580,20 +14884,33 @@ method public static final android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String); method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int); method public final java.nio.ByteBuffer getByteBuffer(java.lang.String); + method public boolean getFeatureEnabled(java.lang.String); method public final float getFloat(java.lang.String); method public final int getInteger(java.lang.String); method public final long getLong(java.lang.String); method public final java.lang.String getString(java.lang.String); method public final void setByteBuffer(java.lang.String, java.nio.ByteBuffer); + method public void setFeatureEnabled(java.lang.String, boolean); method public final void setFloat(java.lang.String, float); method public final void setInteger(java.lang.String, int); method public final void setLong(java.lang.String, long); method public final void setString(java.lang.String, java.lang.String); + field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level"; + field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level"; + field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression"; + field public static final java.lang.String KEY_AAC_DRC_TARGET_REFERENCE_LEVEL = "aac-target-ref-level"; + field public static final java.lang.String KEY_AAC_ENCODED_TARGET_LEVEL = "aac-encoded-target-level"; + field public static final java.lang.String KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT = "aac-max-output-channel_count"; field public static final java.lang.String KEY_AAC_PROFILE = "aac-profile"; + field public static final java.lang.String KEY_AAC_SBR_MODE = "aac-sbr-mode"; + field public static final java.lang.String KEY_AUDIO_SESSION_ID = "audio-session-id"; + field public static final java.lang.String KEY_BITRATE_MODE = "bitrate-mode"; field public static final java.lang.String KEY_BIT_RATE = "bitrate"; + field public static final java.lang.String KEY_CAPTURE_RATE = "capture-rate"; field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count"; field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask"; field public static final java.lang.String KEY_COLOR_FORMAT = "color-format"; + field public static final java.lang.String KEY_COMPLEXITY = "complexity"; field public static final java.lang.String KEY_DURATION = "durationUs"; field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level"; field public static final java.lang.String KEY_FRAME_RATE = "frame-rate"; @@ -12608,13 +14925,91 @@ field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size"; field public static final java.lang.String KEY_MAX_WIDTH = "max-width"; field public static final java.lang.String KEY_MIME = "mime"; + field public static final java.lang.String KEY_PROFILE = "profile"; field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown"; field public static final java.lang.String KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after"; field public static final java.lang.String KEY_SAMPLE_RATE = "sample-rate"; + field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema"; field public static final java.lang.String KEY_WIDTH = "width"; + field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm"; + field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3"; + field public static final java.lang.String MIMETYPE_AUDIO_AMR_NB = "audio/3gpp"; + field public static final java.lang.String MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb"; + field public static final java.lang.String MIMETYPE_AUDIO_FLAC = "audio/flac"; + field public static final java.lang.String MIMETYPE_AUDIO_G711_ALAW = "audio/g711-alaw"; + field public static final java.lang.String MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw"; + field public static final java.lang.String MIMETYPE_AUDIO_MPEG = "audio/mpeg"; + field public static final java.lang.String MIMETYPE_AUDIO_MSGSM = "audio/gsm"; + field public static final java.lang.String MIMETYPE_AUDIO_OPUS = "audio/opus"; + field public static final java.lang.String MIMETYPE_AUDIO_QCELP = "audio/qcelp"; + field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw"; + field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis"; + field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608"; + field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt"; + field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc"; + field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp"; + field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc"; + field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2"; + field public static final java.lang.String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es"; + field public static final java.lang.String MIMETYPE_VIDEO_RAW = "video/raw"; + field public static final java.lang.String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8"; + field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9"; } - public abstract class MediaMetadataEditor { + public final class MediaMetadata implements android.os.Parcelable { + method public boolean containsKey(java.lang.String); + method public int describeContents(); + method public android.graphics.Bitmap getBitmap(java.lang.String); + method public android.media.MediaDescription getDescription(); + method public long getLong(java.lang.String); + method public android.media.Rating getRating(java.lang.String); + method public java.lang.String getString(java.lang.String); + method public java.lang.CharSequence getText(java.lang.String); + method public java.util.Set<java.lang.String> keySet(); + method public int size(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final java.lang.String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM"; + field public static final java.lang.String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART"; + field public static final java.lang.String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST"; + field public static final java.lang.String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI"; + field public static final java.lang.String METADATA_KEY_ART = "android.media.metadata.ART"; + field public static final java.lang.String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST"; + field public static final java.lang.String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI"; + field public static final java.lang.String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR"; + field public static final java.lang.String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"; + field public static final java.lang.String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER"; + field public static final java.lang.String METADATA_KEY_DATE = "android.media.metadata.DATE"; + field public static final java.lang.String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER"; + field public static final java.lang.String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION"; + field public static final java.lang.String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON"; + field public static final java.lang.String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI"; + field public static final java.lang.String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE"; + field public static final java.lang.String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE"; + field public static final java.lang.String METADATA_KEY_DURATION = "android.media.metadata.DURATION"; + field public static final java.lang.String METADATA_KEY_GENRE = "android.media.metadata.GENRE"; + field public static final java.lang.String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID"; + field public static final java.lang.String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS"; + field public static final java.lang.String METADATA_KEY_RATING = "android.media.metadata.RATING"; + field public static final java.lang.String METADATA_KEY_TITLE = "android.media.metadata.TITLE"; + field public static final java.lang.String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER"; + field public static final java.lang.String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING"; + field public static final java.lang.String METADATA_KEY_WRITER = "android.media.metadata.WRITER"; + field public static final java.lang.String METADATA_KEY_YEAR = "android.media.metadata.YEAR"; + } + + public static final class MediaMetadata.Builder { + ctor public MediaMetadata.Builder(); + ctor public MediaMetadata.Builder(android.media.MediaMetadata); + method public android.media.MediaMetadata build(); + method public android.media.MediaMetadata.Builder putBitmap(java.lang.String, android.graphics.Bitmap); + method public android.media.MediaMetadata.Builder putLong(java.lang.String, long); + method public android.media.MediaMetadata.Builder putRating(java.lang.String, android.media.Rating); + method public android.media.MediaMetadata.Builder putString(java.lang.String, java.lang.String); + method public android.media.MediaMetadata.Builder putText(java.lang.String, java.lang.CharSequence); + } + + public abstract deprecated class MediaMetadataEditor { method public synchronized void addEditableKey(int); method public abstract void apply(); method public synchronized void clear(); @@ -12688,6 +15083,7 @@ public static final class MediaMuxer.OutputFormat { field public static final int MUXER_OUTPUT_MPEG_4 = 0; // 0x0 + field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1 } public class MediaPlayer { @@ -12699,11 +15095,14 @@ method public void attachAuxEffect(int); method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri); method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder); + method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int); method public static android.media.MediaPlayer create(android.content.Context, int); + method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int); method public void deselectTrack(int) throws java.lang.IllegalStateException; method public int getAudioSessionId(); method public int getCurrentPosition(); method public int getDuration(); + method public int getSelectedTrack(int) throws java.lang.IllegalStateException; method public android.media.MediaPlayer.TrackInfo[] getTrackInfo() throws java.lang.IllegalStateException; method public int getVideoHeight(); method public int getVideoWidth(); @@ -12716,6 +15115,7 @@ method public void reset(); method public void seekTo(int) throws java.lang.IllegalStateException; method public void selectTrack(int) throws java.lang.IllegalStateException; + method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException; method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException; method public void setAudioStreamType(int); method public void setAuxEffectSendLevel(float); @@ -12803,6 +15203,7 @@ method public int getTrackType(); method public void writeToParcel(android.os.Parcel, int); field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2 + field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4 field public static final int MEDIA_TRACK_TYPE_TIMEDTEXT = 3; // 0x3 field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0 field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1 @@ -12812,6 +15213,7 @@ ctor public MediaRecorder(); method public static final int getAudioSourceMax(); method public int getMaxAmplitude() throws java.lang.IllegalStateException; + method public android.view.Surface getSurface(); method public void prepare() throws java.io.IOException, java.lang.IllegalStateException; method public void release(); method public void reset(); @@ -12820,7 +15222,7 @@ method public void setAudioEncodingBitRate(int); method public void setAudioSamplingRate(int); method public void setAudioSource(int) throws java.lang.IllegalStateException; - method public void setCamera(android.hardware.Camera); + method public deprecated void setCamera(android.hardware.Camera); method public void setCaptureRate(double); method public void setLocation(float, float); method public void setMaxDuration(int) throws java.lang.IllegalArgumentException; @@ -12854,6 +15256,7 @@ field public static final int AMR_WB = 2; // 0x2 field public static final int DEFAULT = 0; // 0x0 field public static final int HE_AAC = 4; // 0x4 + field public static final int VORBIS = 6; // 0x6 } public final class MediaRecorder.AudioSource { @@ -12884,6 +15287,7 @@ field public static final int MPEG_4 = 2; // 0x2 field public static final deprecated int RAW_AMR = 3; // 0x3 field public static final int THREE_GPP = 1; // 0x1 + field public static final int WEBM = 9; // 0x9 } public final class MediaRecorder.VideoEncoder { @@ -12891,11 +15295,13 @@ field public static final int H263 = 1; // 0x1 field public static final int H264 = 2; // 0x2 field public static final int MPEG_4_SP = 3; // 0x3 + field public static final int VP8 = 4; // 0x4 } public final class MediaRecorder.VideoSource { field public static final int CAMERA = 1; // 0x1 field public static final int DEFAULT = 0; // 0x0 + field public static final int SURFACE = 2; // 0x2 } public class MediaRouter { @@ -13068,14 +15474,16 @@ field public static final int RATING_4_STARS = 4; // 0x4 field public static final int RATING_5_STARS = 5; // 0x5 field public static final int RATING_HEART = 1; // 0x1 + field public static final int RATING_NONE = 0; // 0x0 field public static final int RATING_PERCENTAGE = 6; // 0x6 field public static final int RATING_THUMB_UP_DOWN = 2; // 0x2 } - public class RemoteControlClient { + public deprecated class RemoteControlClient { ctor public RemoteControlClient(android.app.PendingIntent); ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper); method public android.media.RemoteControlClient.MetadataEditor editMetadata(boolean); + method public android.media.session.MediaSession getMediaSession(); method public void setMetadataUpdateListener(android.media.RemoteControlClient.OnMetadataUpdateListener); method public void setOnGetPlaybackPositionListener(android.media.RemoteControlClient.OnGetPlaybackPositionListener); method public void setPlaybackPositionUpdateListener(android.media.RemoteControlClient.OnPlaybackPositionUpdateListener); @@ -13103,7 +15511,7 @@ field public static final int PLAYSTATE_STOPPED = 1; // 0x1 } - public class RemoteControlClient.MetadataEditor extends android.media.MediaMetadataEditor { + public deprecated class RemoteControlClient.MetadataEditor extends android.media.MediaMetadataEditor { method public synchronized void apply(); field public static final int BITMAP_KEY_ARTWORK = 100; // 0x64 } @@ -13120,7 +15528,7 @@ method public abstract void onPlaybackPositionUpdate(long); } - public final class RemoteController { + public final deprecated class RemoteController { ctor public RemoteController(android.content.Context, android.media.RemoteController.OnClientUpdateListener) throws java.lang.IllegalArgumentException; ctor public RemoteController(android.content.Context, android.media.RemoteController.OnClientUpdateListener, android.os.Looper) throws java.lang.IllegalArgumentException; method public boolean clearArtworkConfiguration(); @@ -13151,11 +15559,13 @@ } public class Ringtone { - method public int getStreamType(); + method public android.media.AudioAttributes getAudioAttributes(); + method public deprecated int getStreamType(); method public java.lang.String getTitle(android.content.Context); method public boolean isPlaying(); method public void play(); - method public void setStreamType(int); + method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException; + method public deprecated void setStreamType(int); method public void stop(); } @@ -13199,7 +15609,7 @@ } public class SoundPool { - ctor public SoundPool(int, int, int); + ctor public deprecated SoundPool(int, int, int); method public final void autoPause(); method public final void autoResume(); method public int load(java.lang.String, int); @@ -13219,6 +15629,13 @@ method public final boolean unload(int); } + public static class SoundPool.Builder { + ctor public SoundPool.Builder(); + method public android.media.SoundPool build(); + method public android.media.SoundPool.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException; + method public android.media.SoundPool.Builder setMaxStreams(int) throws java.lang.IllegalArgumentException; + } + public static abstract interface SoundPool.OnLoadCompleteListener { method public abstract void onLoadComplete(android.media.SoundPool, int, int); } @@ -13350,6 +15767,19 @@ ctor public UnsupportedSchemeException(java.lang.String); } + public abstract class VolumeProvider { + ctor public VolumeProvider(int, int, int); + method public final int getCurrentVolume(); + method public final int getMaxVolume(); + method public final int getVolumeControl(); + method public void onAdjustVolume(int); + method public void onSetVolumeTo(int); + method public final void setCurrentVolume(int); + field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2 + field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0 + field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1 + } + } package android.media.audiofx { @@ -13582,14 +16012,22 @@ public class Virtualizer extends android.media.audiofx.AudioEffect { ctor public Virtualizer(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException; + method public boolean canVirtualize(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method public boolean forceVirtualizationMode(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; method public android.media.audiofx.Virtualizer.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method public boolean getSpeakerAngles(int, int, int[]) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; method public boolean getStrengthSupported(); + method public int getVirtualizationMode() throws java.lang.IllegalStateException, java.lang.UnsupportedOperationException; method public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener); method public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; field public static final int PARAM_STRENGTH = 1; // 0x1 field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0 + field public static final int VIRTUALIZATION_MODE_AUTO = 1; // 0x1 + field public static final int VIRTUALIZATION_MODE_BINAURAL = 2; // 0x2 + field public static final int VIRTUALIZATION_MODE_OFF = 0; // 0x0 + field public static final int VIRTUALIZATION_MODE_TRANSAURAL = 3; // 0x3 } public static abstract interface Virtualizer.OnParameterChangeListener { @@ -13650,6 +16088,50 @@ } +package android.media.browse { + + public final class MediaBrowser { + ctor public MediaBrowser(android.content.Context, android.content.ComponentName, android.media.browse.MediaBrowser.ConnectionCallback, android.os.Bundle); + method public void connect(); + method public void disconnect(); + method public android.os.Bundle getExtras(); + method public java.lang.String getRoot(); + method public android.content.ComponentName getServiceComponent(); + method public android.media.session.MediaSession.Token getSessionToken(); + method public boolean isConnected(); + method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback); + method public void unsubscribe(java.lang.String); + } + + public static class MediaBrowser.ConnectionCallback { + ctor public MediaBrowser.ConnectionCallback(); + method public void onConnected(); + method public void onConnectionFailed(); + method public void onConnectionSuspended(); + } + + public static class MediaBrowser.MediaItem implements android.os.Parcelable { + ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int); + method public int describeContents(); + method public android.media.MediaDescription getDescription(); + method public int getFlags(); + method public java.lang.String getMediaId(); + method public boolean isBrowsable(); + method public boolean isPlayable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int FLAG_BROWSABLE = 1; // 0x1 + field public static final int FLAG_PLAYABLE = 2; // 0x2 + } + + public static abstract class MediaBrowser.SubscriptionCallback { + ctor public MediaBrowser.SubscriptionCallback(); + method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>); + method public void onError(java.lang.String); + } + +} + package android.media.effect { public abstract class Effect { @@ -13705,6 +16187,540 @@ } +package android.media.projection { + + public final class MediaProjection { + method public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler); + method public void registerCallback(android.media.projection.MediaProjection.Callback, android.os.Handler); + method public void stop(); + method public void unregisterCallback(android.media.projection.MediaProjection.Callback); + } + + public static abstract class MediaProjection.Callback { + ctor public MediaProjection.Callback(); + method public void onStop(); + } + + public final class MediaProjectionManager { + method public android.content.Intent createScreenCaptureIntent(); + method public android.media.projection.MediaProjection getMediaProjection(int, android.content.Intent); + } + +} + +package android.media.session { + + public final class MediaController { + ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token); + method public void adjustVolume(int, int); + method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); + method public android.os.Bundle getExtras(); + method public long getFlags(); + method public android.media.MediaMetadata getMetadata(); + method public java.lang.String getPackageName(); + method public android.media.session.MediaController.PlaybackInfo getPlaybackInfo(); + method public android.media.session.PlaybackState getPlaybackState(); + method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue(); + method public java.lang.CharSequence getQueueTitle(); + method public int getRatingType(); + method public android.app.PendingIntent getSessionActivity(); + method public android.media.session.MediaSession.Token getSessionToken(); + method public android.media.session.MediaController.TransportControls getTransportControls(); + method public void registerCallback(android.media.session.MediaController.Callback); + method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler); + method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); + method public void setVolumeTo(int, int); + method public void unregisterCallback(android.media.session.MediaController.Callback); + } + + public static abstract class MediaController.Callback { + ctor public MediaController.Callback(); + method public void onAudioInfoChanged(android.media.session.MediaController.PlaybackInfo); + method public void onExtrasChanged(android.os.Bundle); + method public void onMetadataChanged(android.media.MediaMetadata); + method public void onPlaybackStateChanged(android.media.session.PlaybackState); + method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>); + method public void onQueueTitleChanged(java.lang.CharSequence); + method public void onSessionDestroyed(); + method public void onSessionEvent(java.lang.String, android.os.Bundle); + } + + public static final class MediaController.PlaybackInfo { + method public android.media.AudioAttributes getAudioAttributes(); + method public int getCurrentVolume(); + method public int getMaxVolume(); + method public int getPlaybackType(); + method public int getVolumeControl(); + field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1 + field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2 + } + + public final class MediaController.TransportControls { + method public void fastForward(); + method public void pause(); + method public void play(); + method public void playFromMediaId(java.lang.String, android.os.Bundle); + method public void playFromSearch(java.lang.String, android.os.Bundle); + method public void rewind(); + method public void seekTo(long); + method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle); + method public void sendCustomAction(java.lang.String, android.os.Bundle); + method public void setRating(android.media.Rating); + method public void skipToNext(); + method public void skipToPrevious(); + method public void skipToQueueItem(long); + method public void stop(); + } + + public final class MediaSession { + ctor public MediaSession(android.content.Context, java.lang.String); + method public android.media.session.MediaController getController(); + method public android.media.session.MediaSession.Token getSessionToken(); + method public boolean isActive(); + method public void release(); + method public void sendSessionEvent(java.lang.String, android.os.Bundle); + method public void setActive(boolean); + method public void setCallback(android.media.session.MediaSession.Callback); + method public void setCallback(android.media.session.MediaSession.Callback, android.os.Handler); + method public void setExtras(android.os.Bundle); + method public void setFlags(int); + method public void setMediaButtonReceiver(android.app.PendingIntent); + method public void setMetadata(android.media.MediaMetadata); + method public void setPlaybackState(android.media.session.PlaybackState); + method public void setPlaybackToLocal(android.media.AudioAttributes); + method public void setPlaybackToRemote(android.media.VolumeProvider); + method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>); + method public void setQueueTitle(java.lang.CharSequence); + method public void setSessionActivity(android.app.PendingIntent); + field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 + field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 + } + + public static abstract class MediaSession.Callback { + ctor public MediaSession.Callback(); + method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); + method public void onCustomAction(java.lang.String, android.os.Bundle); + method public void onFastForward(); + method public boolean onMediaButtonEvent(android.content.Intent); + method public void onPause(); + method public void onPlay(); + method public void onPlayFromMediaId(java.lang.String, android.os.Bundle); + method public void onPlayFromSearch(java.lang.String, android.os.Bundle); + method public void onRewind(); + method public void onSeekTo(long); + method public void onSetRating(android.media.Rating); + method public void onSkipToNext(); + method public void onSkipToPrevious(); + method public void onSkipToQueueItem(long); + method public void onStop(); + } + + public static final class MediaSession.QueueItem implements android.os.Parcelable { + ctor public MediaSession.QueueItem(android.media.MediaDescription, long); + method public int describeContents(); + method public android.media.MediaDescription getDescription(); + method public long getQueueId(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int UNKNOWN_ID = -1; // 0xffffffff + } + + public static final class MediaSession.Token implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class MediaSessionManager { + method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName); + method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler); + method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName); + method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener); + } + + public static abstract interface MediaSessionManager.OnActiveSessionsChangedListener { + method public abstract void onActiveSessionsChanged(java.util.List<android.media.session.MediaController>); + } + + public final class PlaybackState implements android.os.Parcelable { + method public int describeContents(); + method public long getActions(); + method public long getActiveQueueItemId(); + method public long getBufferedPosition(); + method public java.util.List<android.media.session.PlaybackState.CustomAction> getCustomActions(); + method public java.lang.CharSequence getErrorMessage(); + method public long getLastPositionUpdateTime(); + method public float getPlaybackSpeed(); + method public long getPosition(); + method public int getState(); + method public void writeToParcel(android.os.Parcel, int); + field public static final long ACTION_FAST_FORWARD = 64L; // 0x40L + field public static final long ACTION_PAUSE = 2L; // 0x2L + field public static final long ACTION_PLAY = 4L; // 0x4L + field public static final long ACTION_PLAY_FROM_MEDIA_ID = 1024L; // 0x400L + field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L + field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L + field public static final long ACTION_REWIND = 8L; // 0x8L + field public static final long ACTION_SEEK_TO = 256L; // 0x100L + field public static final long ACTION_SET_RATING = 128L; // 0x80L + field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L + field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L + field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L + field public static final long ACTION_STOP = 1L; // 0x1L + field public static final android.os.Parcelable.Creator CREATOR; + field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL + field public static final int STATE_BUFFERING = 6; // 0x6 + field public static final int STATE_CONNECTING = 8; // 0x8 + field public static final int STATE_ERROR = 7; // 0x7 + field public static final int STATE_FAST_FORWARDING = 4; // 0x4 + field public static final int STATE_NONE = 0; // 0x0 + field public static final int STATE_PAUSED = 2; // 0x2 + field public static final int STATE_PLAYING = 3; // 0x3 + field public static final int STATE_REWINDING = 5; // 0x5 + field public static final int STATE_SKIPPING_TO_NEXT = 10; // 0xa + field public static final int STATE_SKIPPING_TO_PREVIOUS = 9; // 0x9 + field public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11; // 0xb + field public static final int STATE_STOPPED = 1; // 0x1 + } + + public static final class PlaybackState.Builder { + ctor public PlaybackState.Builder(); + ctor public PlaybackState.Builder(android.media.session.PlaybackState); + method public android.media.session.PlaybackState.Builder addCustomAction(java.lang.String, java.lang.String, int); + method public android.media.session.PlaybackState.Builder addCustomAction(android.media.session.PlaybackState.CustomAction); + method public android.media.session.PlaybackState build(); + method public android.media.session.PlaybackState.Builder setActions(long); + method public android.media.session.PlaybackState.Builder setActiveQueueItemId(long); + method public android.media.session.PlaybackState.Builder setBufferedPosition(long); + method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence); + method public android.media.session.PlaybackState.Builder setState(int, long, float, long); + method public android.media.session.PlaybackState.Builder setState(int, long, float); + } + + public static final class PlaybackState.CustomAction implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.String getAction(); + method public android.os.Bundle getExtras(); + method public int getIcon(); + method public java.lang.CharSequence getName(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class PlaybackState.CustomAction.Builder { + ctor public PlaybackState.CustomAction.Builder(java.lang.String, java.lang.CharSequence, int); + method public android.media.session.PlaybackState.CustomAction build(); + method public android.media.session.PlaybackState.CustomAction.Builder setExtras(android.os.Bundle); + } + +} + +package android.media.tv { + + public final class TvContentRating { + method public static android.media.tv.TvContentRating createRating(java.lang.String, java.lang.String, java.lang.String, java.lang.String...); + method public java.lang.String flattenToString(); + method public java.lang.String getDomain(); + method public java.lang.String getMainRating(); + method public java.lang.String getRatingSystem(); + method public java.util.List<java.lang.String> getSubRatings(); + method public static android.media.tv.TvContentRating unflattenFromString(java.lang.String); + } + + public final class TvContract { + method public static final android.net.Uri buildChannelLogoUri(long); + method public static final android.net.Uri buildChannelLogoUri(android.net.Uri); + method public static final android.net.Uri buildChannelUri(long); + method public static final android.net.Uri buildChannelUriForPassthroughInput(java.lang.String); + method public static final android.net.Uri buildChannelsUriForInput(java.lang.String); + method public static final java.lang.String buildInputId(android.content.ComponentName); + method public static final android.net.Uri buildProgramUri(long); + method public static final android.net.Uri buildProgramsUriForChannel(long); + method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri); + method public static final android.net.Uri buildProgramsUriForChannel(long, long, long); + method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long); + field public static final java.lang.String AUTHORITY = "android.media.tv"; + } + + public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns { + field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name"; + } + + public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns { + method public static final java.lang.String getVideoResolution(java.lang.String); + field public static final java.lang.String COLUMN_DESCRIPTION = "description"; + field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name"; + field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number"; + field public static final java.lang.String COLUMN_INPUT_ID = "input_id"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; + field public static final java.lang.String COLUMN_NETWORK_AFFILIATION = "network_affiliation"; + field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id"; + field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; + field public static final java.lang.String COLUMN_SERVICE_ID = "service_id"; + field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type"; + field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id"; + field public static final java.lang.String COLUMN_TYPE = "type"; + field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_FORMAT = "video_format"; + field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel"; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/channel"; + field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO"; + field public static final java.lang.String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO"; + field public static final java.lang.String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER"; + field public static final java.lang.String TYPE_1SEG = "TYPE_1SEG"; + field public static final java.lang.String TYPE_ATSC_C = "TYPE_ATSC_C"; + field public static final java.lang.String TYPE_ATSC_M_H = "TYPE_ATSC_M_H"; + field public static final java.lang.String TYPE_ATSC_T = "TYPE_ATSC_T"; + field public static final java.lang.String TYPE_CMMB = "TYPE_CMMB"; + field public static final java.lang.String TYPE_DTMB = "TYPE_DTMB"; + field public static final java.lang.String TYPE_DVB_C = "TYPE_DVB_C"; + field public static final java.lang.String TYPE_DVB_C2 = "TYPE_DVB_C2"; + field public static final java.lang.String TYPE_DVB_H = "TYPE_DVB_H"; + field public static final java.lang.String TYPE_DVB_S = "TYPE_DVB_S"; + field public static final java.lang.String TYPE_DVB_S2 = "TYPE_DVB_S2"; + field public static final java.lang.String TYPE_DVB_SH = "TYPE_DVB_SH"; + field public static final java.lang.String TYPE_DVB_T = "TYPE_DVB_T"; + field public static final java.lang.String TYPE_DVB_T2 = "TYPE_DVB_T2"; + field public static final java.lang.String TYPE_ISDB_C = "TYPE_ISDB_C"; + field public static final java.lang.String TYPE_ISDB_S = "TYPE_ISDB_S"; + field public static final java.lang.String TYPE_ISDB_T = "TYPE_ISDB_T"; + field public static final java.lang.String TYPE_ISDB_TB = "TYPE_ISDB_TB"; + field public static final java.lang.String TYPE_NTSC = "TYPE_NTSC"; + field public static final java.lang.String TYPE_OTHER = "TYPE_OTHER"; + field public static final java.lang.String TYPE_PAL = "TYPE_PAL"; + field public static final java.lang.String TYPE_SECAM = "TYPE_SECAM"; + field public static final java.lang.String TYPE_S_DMB = "TYPE_S_DMB"; + field public static final java.lang.String TYPE_T_DMB = "TYPE_T_DMB"; + field public static final java.lang.String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I"; + field public static final java.lang.String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P"; + field public static final java.lang.String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P"; + field public static final java.lang.String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P"; + field public static final java.lang.String VIDEO_FORMAT_360P = "VIDEO_FORMAT_360P"; + field public static final java.lang.String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P"; + field public static final java.lang.String VIDEO_FORMAT_480I = "VIDEO_FORMAT_480I"; + field public static final java.lang.String VIDEO_FORMAT_480P = "VIDEO_FORMAT_480P"; + field public static final java.lang.String VIDEO_FORMAT_576I = "VIDEO_FORMAT_576I"; + field public static final java.lang.String VIDEO_FORMAT_576P = "VIDEO_FORMAT_576P"; + field public static final java.lang.String VIDEO_FORMAT_720P = "VIDEO_FORMAT_720P"; + field public static final java.lang.String VIDEO_RESOLUTION_ED = "VIDEO_RESOLUTION_ED"; + field public static final java.lang.String VIDEO_RESOLUTION_FHD = "VIDEO_RESOLUTION_FHD"; + field public static final java.lang.String VIDEO_RESOLUTION_HD = "VIDEO_RESOLUTION_HD"; + field public static final java.lang.String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD"; + field public static final java.lang.String VIDEO_RESOLUTION_UHD = "VIDEO_RESOLUTION_UHD"; + } + + public static final class TvContract.Channels.Logo { + field public static final java.lang.String CONTENT_DIRECTORY = "logo"; + } + + public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns { + field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; + field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; + field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; + field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; + field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; + field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number"; + field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; + field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; + field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; + field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number"; + field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; + field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; + field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; + field public static final java.lang.String COLUMN_TITLE = "title"; + field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; + field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; + field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program"; + field public static final android.net.Uri CONTENT_URI; + } + + public static final class TvContract.Programs.Genres { + method public static java.lang.String[] decode(java.lang.String); + method public static java.lang.String encode(java.lang.String...); + field public static final java.lang.String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE"; + field public static final java.lang.String COMEDY = "COMEDY"; + field public static final java.lang.String DRAMA = "DRAMA"; + field public static final java.lang.String EDUCATION = "EDUCATION"; + field public static final java.lang.String FAMILY_KIDS = "FAMILY_KIDS"; + field public static final java.lang.String GAMING = "GAMING"; + field public static final java.lang.String MOVIES = "MOVIES"; + field public static final java.lang.String NEWS = "NEWS"; + field public static final java.lang.String SHOPPING = "SHOPPING"; + field public static final java.lang.String SPORTS = "SPORTS"; + field public static final java.lang.String TRAVEL = "TRAVEL"; + } + + public final class TvInputInfo implements android.os.Parcelable { + method public android.content.Intent createSettingsIntent(); + method public android.content.Intent createSetupIntent(); + method public int describeContents(); + method public java.lang.String getId(); + method public java.lang.String getParentId(); + method public android.content.pm.ServiceInfo getServiceInfo(); + method public int getType(); + method public boolean isPassthroughInput(); + method public android.graphics.drawable.Drawable loadIcon(android.content.Context); + method public java.lang.CharSequence loadLabel(android.content.Context); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final java.lang.String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID"; + field public static final int TYPE_COMPONENT = 1004; // 0x3ec + field public static final int TYPE_COMPOSITE = 1001; // 0x3e9 + field public static final int TYPE_DISPLAY_PORT = 1008; // 0x3f0 + field public static final int TYPE_DVI = 1006; // 0x3ee + field public static final int TYPE_HDMI = 1007; // 0x3ef + field public static final int TYPE_OTHER = 1000; // 0x3e8 + field public static final int TYPE_SCART = 1003; // 0x3eb + field public static final int TYPE_SVIDEO = 1002; // 0x3ea + field public static final int TYPE_TUNER = 0; // 0x0 + field public static final int TYPE_VGA = 1005; // 0x3ed + } + + public final class TvInputManager { + method public int getInputState(java.lang.String); + method public android.media.tv.TvInputInfo getTvInputInfo(java.lang.String); + method public java.util.List<android.media.tv.TvInputInfo> getTvInputList(); + method public boolean isParentalControlsEnabled(); + method public boolean isRatingBlocked(android.media.tv.TvContentRating); + method public void registerCallback(android.media.tv.TvInputManager.TvInputCallback, android.os.Handler); + method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback); + field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED"; + field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED"; + field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS"; + field public static final int INPUT_STATE_CONNECTED = 0; // 0x0 + field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1 + field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2 + field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.metadata.CONTENT_RATING_SYSTEMS"; + field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3 + field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1 + field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0 + field public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2; // 0x2 + } + + public static abstract class TvInputManager.TvInputCallback { + ctor public TvInputManager.TvInputCallback(); + method public void onInputAdded(java.lang.String); + method public void onInputRemoved(java.lang.String); + method public void onInputStateChanged(java.lang.String, int); + } + + public abstract class TvInputService extends android.app.Service { + ctor public TvInputService(); + method public final android.os.IBinder onBind(android.content.Intent); + method public abstract android.media.tv.TvInputService.Session onCreateSession(java.lang.String); + field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService"; + field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input"; + } + + public static abstract class TvInputService.HardwareSession extends android.media.tv.TvInputService.Session { + ctor public TvInputService.HardwareSession(android.content.Context); + method public abstract java.lang.String getHardwareInputId(); + method public void onHardwareVideoAvailable(); + method public void onHardwareVideoUnavailable(int); + method public final boolean onSetSurface(android.view.Surface); + } + + public static abstract class TvInputService.Session implements android.view.KeyEvent.Callback { + ctor public TvInputService.Session(android.content.Context); + method public void notifyChannelRetuned(android.net.Uri); + method public void notifyContentAllowed(); + method public void notifyContentBlocked(android.media.tv.TvContentRating); + method public void notifyTrackSelected(int, java.lang.String); + method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>); + method public void notifyVideoAvailable(); + method public void notifyVideoUnavailable(int); + method public android.view.View onCreateOverlayView(); + method public boolean onGenericMotionEvent(android.view.MotionEvent); + method public boolean onKeyDown(int, android.view.KeyEvent); + method public boolean onKeyLongPress(int, android.view.KeyEvent); + method public boolean onKeyMultiple(int, int, android.view.KeyEvent); + method public boolean onKeyUp(int, android.view.KeyEvent); + method public abstract void onRelease(); + method public boolean onSelectTrack(int, java.lang.String); + method public abstract void onSetCaptionEnabled(boolean); + method public abstract void onSetStreamVolume(float); + method public abstract boolean onSetSurface(android.view.Surface); + method public void onSurfaceChanged(int, int, int); + method public boolean onTouchEvent(android.view.MotionEvent); + method public boolean onTrackballEvent(android.view.MotionEvent); + method public abstract boolean onTune(android.net.Uri); + method public void onUnblockContent(android.media.tv.TvContentRating); + method public void setOverlayViewEnabled(boolean); + } + + public final class TvTrackInfo implements android.os.Parcelable { + method public int describeContents(); + method public final int getAudioChannelCount(); + method public final int getAudioSampleRate(); + method public final android.os.Bundle getExtra(); + method public final java.lang.String getId(); + method public final java.lang.String getLanguage(); + method public final int getType(); + method public final float getVideoFrameRate(); + method public final int getVideoHeight(); + method public final int getVideoWidth(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int TYPE_AUDIO = 0; // 0x0 + field public static final int TYPE_SUBTITLE = 2; // 0x2 + field public static final int TYPE_VIDEO = 1; // 0x1 + } + + public static final class TvTrackInfo.Builder { + ctor public TvTrackInfo.Builder(int, java.lang.String); + method public android.media.tv.TvTrackInfo build(); + method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int); + method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int); + method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle); + method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String); + method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float); + method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int); + method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int); + } + + public class TvView extends android.view.ViewGroup { + ctor public TvView(android.content.Context); + ctor public TvView(android.content.Context, android.util.AttributeSet); + ctor public TvView(android.content.Context, android.util.AttributeSet, int); + method public boolean dispatchUnhandledInputEvent(android.view.InputEvent); + method public java.lang.String getSelectedTrack(int); + method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int); + method protected void onLayout(boolean, int, int, int, int); + method public boolean onUnhandledInputEvent(android.view.InputEvent); + method public void reset(); + method public void selectTrack(int, java.lang.String); + method public void setCallback(android.media.tv.TvView.TvInputCallback); + method public void setCaptionEnabled(boolean); + method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener); + method public void setStreamVolume(float); + method public void tune(java.lang.String, android.net.Uri); + } + + public static abstract interface TvView.OnUnhandledInputEventListener { + method public abstract boolean onUnhandledInputEvent(android.view.InputEvent); + } + + public static abstract class TvView.TvInputCallback { + ctor public TvView.TvInputCallback(); + method public void onChannelRetuned(java.lang.String, android.net.Uri); + method public void onConnectionFailed(java.lang.String); + method public void onContentAllowed(java.lang.String); + method public void onContentBlocked(java.lang.String, android.media.tv.TvContentRating); + method public void onDisconnected(java.lang.String); + method public void onTrackSelected(java.lang.String, int, java.lang.String); + method public void onTracksChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>); + method public void onVideoAvailable(java.lang.String); + method public void onVideoSizeChanged(java.lang.String, int, int); + method public void onVideoUnavailable(java.lang.String, int); + } + +} + package android.mtp { public final class MtpConstants { @@ -13835,17 +16851,30 @@ package android.net { public class ConnectivityManager { + method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public android.net.NetworkInfo getActiveNetworkInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo(); + method public android.net.Network[] getAllNetworks(); method public deprecated boolean getBackgroundDataSetting(); + method public android.net.LinkProperties getLinkProperties(android.net.Network); + method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network); method public android.net.NetworkInfo getNetworkInfo(int); - method public int getNetworkPreference(); + method public android.net.NetworkInfo getNetworkInfo(android.net.Network); + method public deprecated int getNetworkPreference(); + method public static android.net.Network getProcessDefaultNetwork(); method public boolean isActiveNetworkMetered(); + method public boolean isDefaultNetworkActive(); method public static boolean isNetworkTypeValid(int); - method public boolean requestRouteToHost(int, int); - method public void setNetworkPreference(int); - method public int startUsingNetworkFeature(int, java.lang.String); - method public int stopUsingNetworkFeature(int, java.lang.String); + method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); + method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); + method public void reportBadNetwork(android.net.Network); + method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); + method public deprecated boolean requestRouteToHost(int, int); + method public deprecated void setNetworkPreference(int); + method public static boolean setProcessDefaultNetwork(android.net.Network); + method public deprecated int startUsingNetworkFeature(int, java.lang.String); + method public deprecated int stopUsingNetworkFeature(int, java.lang.String); + method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback); field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1 @@ -13864,10 +16893,24 @@ field public static final int TYPE_MOBILE_HIPRI = 5; // 0x5 field public static final int TYPE_MOBILE_MMS = 2; // 0x2 field public static final int TYPE_MOBILE_SUPL = 3; // 0x3 + field public static final int TYPE_VPN = 17; // 0x11 field public static final int TYPE_WIFI = 1; // 0x1 field public static final int TYPE_WIMAX = 6; // 0x6 } + public static class ConnectivityManager.NetworkCallback { + ctor public ConnectivityManager.NetworkCallback(); + method public void onAvailable(android.net.Network); + method public void onCapabilitiesChanged(android.net.Network, android.net.NetworkCapabilities); + method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties); + method public void onLosing(android.net.Network, int); + method public void onLost(android.net.Network); + } + + public static abstract interface ConnectivityManager.OnNetworkActiveListener { + method public abstract void onNetworkActive(); + } + public class Credentials { ctor public Credentials(int, int, int); method public int getGid(); @@ -13888,6 +16931,37 @@ field public int serverAddress; } + public final class IpPrefix implements android.os.Parcelable { + method public int describeContents(); + method public java.net.InetAddress getAddress(); + method public int getPrefixLength(); + method public byte[] getRawAddress(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public class LinkAddress implements android.os.Parcelable { + method public int describeContents(); + method public java.net.InetAddress getAddress(); + method public int getFlags(); + method public int getPrefixLength(); + method public int getScope(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class LinkProperties implements android.os.Parcelable { + method public int describeContents(); + method public java.util.List<java.net.InetAddress> getDnsServers(); + method public java.lang.String getDomains(); + method public android.net.ProxyInfo getHttpProxy(); + method public java.lang.String getInterfaceName(); + method public java.util.List<android.net.LinkAddress> getLinkAddresses(); + method public java.util.List<android.net.RouteInfo> getRoutes(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class LocalServerSocket { ctor public LocalServerSocket(java.lang.String) throws java.io.IOException; ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException; @@ -13956,6 +17030,49 @@ field public static final java.lang.String MAILTO_SCHEME = "mailto:"; } + public class Network implements android.os.Parcelable { + method public void bindSocket(java.net.Socket) throws java.io.IOException; + method public int describeContents(); + method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException; + method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException; + method public javax.net.SocketFactory getSocketFactory(); + method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException; + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(android.net.NetworkCapabilities); + method public int describeContents(); + method public int getLinkDownstreamBandwidthKbps(); + method public int getLinkUpstreamBandwidthKbps(); + method public boolean hasCapability(int); + method public boolean hasTransport(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int NET_CAPABILITY_CBS = 5; // 0x5 + field public static final int NET_CAPABILITY_DUN = 2; // 0x2 + field public static final int NET_CAPABILITY_EIMS = 10; // 0xa + field public static final int NET_CAPABILITY_FOTA = 3; // 0x3 + field public static final int NET_CAPABILITY_IA = 7; // 0x7 + field public static final int NET_CAPABILITY_IMS = 4; // 0x4 + field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc + field public static final int NET_CAPABILITY_MMS = 0; // 0x0 + field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb + field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd + field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf + field public static final int NET_CAPABILITY_RCS = 8; // 0x8 + field public static final int NET_CAPABILITY_SUPL = 1; // 0x1 + field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe + field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 + field public static final int NET_CAPABILITY_XCAP = 9; // 0x9 + field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2 + field public static final int TRANSPORT_CELLULAR = 0; // 0x0 + field public static final int TRANSPORT_ETHERNET = 3; // 0x3 + field public static final int TRANSPORT_VPN = 4; // 0x4 + field public static final int TRANSPORT_WIFI = 1; // 0x1 + } + public class NetworkInfo implements android.os.Parcelable { method public int describeContents(); method public android.net.NetworkInfo.DetailedState getDetailedState(); @@ -14003,6 +17120,22 @@ enum_constant public static final android.net.NetworkInfo.State UNKNOWN; } + public class NetworkRequest implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static class NetworkRequest.Builder { + ctor public NetworkRequest.Builder(); + method public android.net.NetworkRequest.Builder addCapability(int); + method public android.net.NetworkRequest.Builder addTransportType(int); + method public android.net.NetworkRequest build(); + method public android.net.NetworkRequest.Builder removeCapability(int); + method public android.net.NetworkRequest.Builder removeTransportType(int); + method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String); + } + public class ParseException extends java.lang.RuntimeException { field public java.lang.String response; } @@ -14013,9 +17146,47 @@ method public static final deprecated int getDefaultPort(); method public static final deprecated java.lang.String getHost(android.content.Context); method public static final deprecated int getPort(android.content.Context); + field public static final java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; } + public class ProxyInfo implements android.os.Parcelable { + method public static android.net.ProxyInfo buildDirectProxy(java.lang.String, int); + method public static android.net.ProxyInfo buildDirectProxy(java.lang.String, int, java.util.List<java.lang.String>); + method public static android.net.ProxyInfo buildPacProxy(android.net.Uri); + method public int describeContents(); + method public java.lang.String[] getExclusionList(); + method public java.lang.String getHost(); + method public android.net.Uri getPacFileUrl(); + method public int getPort(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public abstract class PskKeyManager { + ctor public PskKeyManager(); + method public java.lang.String chooseClientKeyIdentity(java.lang.String, java.net.Socket); + method public java.lang.String chooseClientKeyIdentity(java.lang.String, javax.net.ssl.SSLEngine); + method public java.lang.String chooseServerKeyIdentityHint(java.net.Socket); + method public java.lang.String chooseServerKeyIdentityHint(javax.net.ssl.SSLEngine); + method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, java.net.Socket); + method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, javax.net.ssl.SSLEngine); + field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80 + field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80 + field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100 + } + + public final class RouteInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.net.IpPrefix getDestination(); + method public java.net.InetAddress getGateway(); + method public java.lang.String getInterface(); + method public boolean isDefaultRoute(); + method public boolean matches(java.net.InetAddress); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory { ctor public deprecated SSLCertificateSocketFactory(int); method public java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException; @@ -14224,12 +17395,17 @@ ctor public VpnService.Builder(); method public android.net.VpnService.Builder addAddress(java.net.InetAddress, int); method public android.net.VpnService.Builder addAddress(java.lang.String, int); + method public android.net.VpnService.Builder addAllowedApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; + method public android.net.VpnService.Builder addDisallowedApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public android.net.VpnService.Builder addDnsServer(java.net.InetAddress); method public android.net.VpnService.Builder addDnsServer(java.lang.String); method public android.net.VpnService.Builder addRoute(java.net.InetAddress, int); method public android.net.VpnService.Builder addRoute(java.lang.String, int); method public android.net.VpnService.Builder addSearchDomain(java.lang.String); + method public android.net.VpnService.Builder allowBypass(); + method public android.net.VpnService.Builder allowFamily(int); method public android.os.ParcelFileDescriptor establish(); + method public android.net.VpnService.Builder setBlocking(boolean); method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent); method public android.net.VpnService.Builder setMtu(int); method public android.net.VpnService.Builder setSession(java.lang.String); @@ -14322,6 +17498,7 @@ public class X509TrustManagerExtensions { ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException; method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String) throws java.security.cert.CertificateException; + method public boolean isUserAddedCertificate(java.security.cert.X509Certificate); } } @@ -14368,10 +17545,13 @@ public final class NsdServiceInfo implements android.os.Parcelable { ctor public NsdServiceInfo(); method public int describeContents(); + method public java.util.Map<java.lang.String, byte[]> getAttributes(); method public java.net.InetAddress getHost(); method public int getPort(); method public java.lang.String getServiceName(); method public java.lang.String getServiceType(); + method public void removeAttribute(java.lang.String); + method public void setAttribute(java.lang.String, java.lang.String); method public void setHost(java.net.InetAddress); method public void setPort(int); method public void setServiceName(java.lang.String); @@ -14655,6 +17835,7 @@ method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public java.lang.String BSSID; + field public java.lang.String FQDN; field public java.lang.String SSID; field public java.util.BitSet allowedAuthAlgorithms; field public java.util.BitSet allowedGroupCiphers; @@ -14744,9 +17925,11 @@ } public static final class WifiEnterpriseConfig.Eap { + field public static final int AKA = 5; // 0x5 field public static final int NONE = -1; // 0xffffffff field public static final int PEAP = 0; // 0x0 field public static final int PWD = 3; // 0x3 + field public static final int SIM = 4; // 0x4 field public static final int TLS = 1; // 0x1 field public static final int TTLS = 2; // 0x2 } @@ -14763,6 +17946,7 @@ method public int describeContents(); method public java.lang.String getBSSID(); method public static android.net.NetworkInfo.DetailedState getDetailedStateOf(android.net.wifi.SupplicantState); + method public int getFrequency(); method public boolean getHiddenSSID(); method public int getIpAddress(); method public int getLinkSpeed(); @@ -14772,12 +17956,14 @@ method public java.lang.String getSSID(); method public android.net.wifi.SupplicantState getSupplicantState(); method public void writeToParcel(android.os.Parcel, int); + field public static final java.lang.String FREQUENCY_UNITS = "MHz"; field public static final java.lang.String LINK_SPEED_UNITS = "Mbps"; } public class WifiManager { method public int addNetwork(android.net.wifi.WifiConfiguration); method public static int calculateSignalLevel(int, int); + method public void cancelWps(android.net.wifi.WifiManager.WpsCallback); method public static int compareSignalLevel(int, int); method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String); method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String); @@ -14790,7 +17976,13 @@ method public android.net.DhcpInfo getDhcpInfo(); method public java.util.List<android.net.wifi.ScanResult> getScanResults(); method public int getWifiState(); + method public boolean is5GHzBandSupported(); + method public boolean isDeviceToApRttSupported(); + method public boolean isEnhancedPowerReportingSupported(); + method public boolean isP2pSupported(); + method public boolean isPreferredNetworkOffloadSupported(); method public boolean isScanAlwaysAvailable(); + method public boolean isTdlsSupported(); method public boolean isWifiEnabled(); method public boolean pingSupplicant(); method public boolean reassociate(); @@ -14801,6 +17993,7 @@ method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean); method public boolean setWifiEnabled(boolean); method public boolean startScan(); + method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback); method public int updateNetwork(android.net.wifi.WifiConfiguration); field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; @@ -14829,6 +18022,11 @@ field public static final int WIFI_STATE_ENABLED = 3; // 0x3 field public static final int WIFI_STATE_ENABLING = 2; // 0x2 field public static final int WIFI_STATE_UNKNOWN = 4; // 0x4 + field public static final int WPS_AUTH_FAILURE = 6; // 0x6 + field public static final int WPS_OVERLAP_ERROR = 3; // 0x3 + field public static final int WPS_TIMED_OUT = 7; // 0x7 + field public static final int WPS_TKIP_ONLY_PROHIBITED = 5; // 0x5 + field public static final int WPS_WEP_PROHIBITED = 4; // 0x4 } public class WifiManager.MulticastLock { @@ -14846,11 +18044,19 @@ method public void setWorkSource(android.os.WorkSource); } + public static abstract class WifiManager.WpsCallback { + ctor public WifiManager.WpsCallback(); + method public abstract void onFailed(int); + method public abstract void onStarted(java.lang.String); + method public abstract void onSucceeded(); + } + public class WpsInfo implements android.os.Parcelable { ctor public WpsInfo(); ctor public WpsInfo(android.net.wifi.WpsInfo); method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); + field public java.lang.String BSSID; field public static final android.os.Parcelable.Creator CREATOR; field public static final int DISPLAY = 1; // 0x1 field public static final int INVALID = 4; // 0x4 @@ -15084,6 +18290,7 @@ method public static android.nfc.NdefRecord createApplicationRecord(java.lang.String); method public static android.nfc.NdefRecord createExternal(java.lang.String, java.lang.String, byte[]); method public static android.nfc.NdefRecord createMime(java.lang.String, byte[]); + method public static android.nfc.NdefRecord createTextRecord(java.lang.String, java.lang.String); method public static android.nfc.NdefRecord createUri(android.net.Uri); method public static android.nfc.NdefRecord createUri(java.lang.String); method public int describeContents(); @@ -15120,6 +18327,7 @@ method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); + method public boolean invokeBeam(android.app.Activity); method public boolean isEnabled(); method public boolean isNdefPushEnabled(); method public void setBeamPushUris(android.net.Uri[], android.app.Activity); @@ -15191,10 +18399,17 @@ package android.nfc.cardemulation { public final class CardEmulation { + method public boolean categoryAllowsForegroundPreference(java.lang.String); + method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, java.lang.String); method public static synchronized android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter); method public int getSelectionModeForCategory(java.lang.String); method public boolean isDefaultServiceForAid(android.content.ComponentName, java.lang.String); method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String); + method public boolean registerAidsForService(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); + method public boolean removeAidsForService(android.content.ComponentName, java.lang.String); + method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); + method public boolean supportsAidPrefixRegistration(); + method public boolean unsetPreferredService(android.app.Activity); field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; field public static final java.lang.String CATEGORY_OTHER = "other"; field public static final java.lang.String CATEGORY_PAYMENT = "payment"; @@ -15545,8 +18760,10 @@ } public abstract class EGLObjectHandle { - ctor protected EGLObjectHandle(int); - method public int getHandle(); + ctor protected deprecated EGLObjectHandle(int); + ctor protected EGLObjectHandle(long); + method public deprecated int getHandle(); + method public long getNativeHandle(); } public class EGLSurface extends android.opengl.EGLObjectHandle { @@ -16458,11 +19675,9 @@ method public static void glGenTextures(int, java.nio.IntBuffer); method public static void glGenerateMipmap(int); method public static void glGetActiveAttrib(int, int, int, int[], int, int[], int, int[], int, byte[], int); - method public static void glGetActiveAttrib(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte); method public static java.lang.String glGetActiveAttrib(int, int, int[], int, int[], int); method public static java.lang.String glGetActiveAttrib(int, int, java.nio.IntBuffer, java.nio.IntBuffer); method public static void glGetActiveUniform(int, int, int, int[], int, int[], int, int[], int, byte[], int); - method public static void glGetActiveUniform(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte); method public static java.lang.String glGetActiveUniform(int, int, int[], int, int[], int); method public static java.lang.String glGetActiveUniform(int, int, java.nio.IntBuffer, java.nio.IntBuffer); method public static void glGetAttachedShaders(int, int, int[], int, int[], int); @@ -16488,7 +19703,6 @@ method public static void glGetShaderPrecisionFormat(int, int, int[], int, int[], int); method public static void glGetShaderPrecisionFormat(int, int, java.nio.IntBuffer, java.nio.IntBuffer); method public static void glGetShaderSource(int, int, int[], int, byte[], int); - method public static void glGetShaderSource(int, int, java.nio.IntBuffer, byte); method public static java.lang.String glGetShaderSource(int); method public static void glGetShaderiv(int, int, int[], int); method public static void glGetShaderiv(int, int, java.nio.IntBuffer); @@ -17361,6 +20575,532 @@ field public static final int GL_WAIT_FAILED = 37149; // 0x911d } + public class GLES31 extends android.opengl.GLES30 { + method public static void glActiveShaderProgram(int, int); + method public static void glBindImageTexture(int, int, int, boolean, int, int, int); + method public static void glBindProgramPipeline(int); + method public static void glBindVertexBuffer(int, int, long, int); + method public static int glCreateShaderProgramv(int, java.lang.String[]); + method public static void glDeleteProgramPipelines(int, int[], int); + method public static void glDeleteProgramPipelines(int, java.nio.IntBuffer); + method public static void glDispatchCompute(int, int, int); + method public static void glDispatchComputeIndirect(long); + method public static void glDrawArraysIndirect(int, long); + method public static void glDrawElementsIndirect(int, int, long); + method public static void glFramebufferParameteri(int, int, int); + method public static void glGenProgramPipelines(int, int[], int); + method public static void glGenProgramPipelines(int, java.nio.IntBuffer); + method public static void glGetBooleani_v(int, int, boolean[], int); + method public static void glGetBooleani_v(int, int, java.nio.IntBuffer); + method public static void glGetFramebufferParameteriv(int, int, int[], int); + method public static void glGetFramebufferParameteriv(int, int, java.nio.IntBuffer); + method public static void glGetMultisamplefv(int, int, float[], int); + method public static void glGetMultisamplefv(int, int, java.nio.FloatBuffer); + method public static void glGetProgramInterfaceiv(int, int, int, int[], int); + method public static void glGetProgramInterfaceiv(int, int, int, java.nio.IntBuffer); + method public static java.lang.String glGetProgramPipelineInfoLog(int); + method public static void glGetProgramPipelineiv(int, int, int[], int); + method public static void glGetProgramPipelineiv(int, int, java.nio.IntBuffer); + method public static int glGetProgramResourceIndex(int, int, java.lang.String); + method public static int glGetProgramResourceLocation(int, int, java.lang.String); + method public static java.lang.String glGetProgramResourceName(int, int, int); + method public static void glGetProgramResourceiv(int, int, int, int, int[], int, int, int[], int, int[], int); + method public static void glGetProgramResourceiv(int, int, int, int, java.nio.IntBuffer, int, java.nio.IntBuffer, java.nio.IntBuffer); + method public static void glGetTexLevelParameterfv(int, int, int, float[], int); + method public static void glGetTexLevelParameterfv(int, int, int, java.nio.FloatBuffer); + method public static void glGetTexLevelParameteriv(int, int, int, int[], int); + method public static void glGetTexLevelParameteriv(int, int, int, java.nio.IntBuffer); + method public static boolean glIsProgramPipeline(int); + method public static void glMemoryBarrier(int); + method public static void glMemoryBarrierByRegion(int); + method public static void glProgramUniform1f(int, int, float); + method public static void glProgramUniform1fv(int, int, int, float[], int); + method public static void glProgramUniform1fv(int, int, int, java.nio.FloatBuffer); + method public static void glProgramUniform1i(int, int, int); + method public static void glProgramUniform1iv(int, int, int, int[], int); + method public static void glProgramUniform1iv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform1ui(int, int, int); + method public static void glProgramUniform1uiv(int, int, int, int[], int); + method public static void glProgramUniform1uiv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform2f(int, int, float, float); + method public static void glProgramUniform2fv(int, int, int, float[], int); + method public static void glProgramUniform2fv(int, int, int, java.nio.FloatBuffer); + method public static void glProgramUniform2i(int, int, int, int); + method public static void glProgramUniform2iv(int, int, int, int[], int); + method public static void glProgramUniform2iv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform2ui(int, int, int, int); + method public static void glProgramUniform2uiv(int, int, int, int[], int); + method public static void glProgramUniform2uiv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform3f(int, int, float, float, float); + method public static void glProgramUniform3fv(int, int, int, float[], int); + method public static void glProgramUniform3fv(int, int, int, java.nio.FloatBuffer); + method public static void glProgramUniform3i(int, int, int, int, int); + method public static void glProgramUniform3iv(int, int, int, int[], int); + method public static void glProgramUniform3iv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform3ui(int, int, int, int, int); + method public static void glProgramUniform3uiv(int, int, int, int[], int); + method public static void glProgramUniform3uiv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform4f(int, int, float, float, float, float); + method public static void glProgramUniform4fv(int, int, int, float[], int); + method public static void glProgramUniform4fv(int, int, int, java.nio.FloatBuffer); + method public static void glProgramUniform4i(int, int, int, int, int, int); + method public static void glProgramUniform4iv(int, int, int, int[], int); + method public static void glProgramUniform4iv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniform4ui(int, int, int, int, int, int); + method public static void glProgramUniform4uiv(int, int, int, int[], int); + method public static void glProgramUniform4uiv(int, int, int, java.nio.IntBuffer); + method public static void glProgramUniformMatrix2fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix2fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix2x3fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix2x3fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix2x4fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix2x4fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix3fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix3fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix3x2fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix3x2fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix3x4fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix3x4fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix4fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix4fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix4x2fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix4x2fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glProgramUniformMatrix4x3fv(int, int, int, boolean, float[], int); + method public static void glProgramUniformMatrix4x3fv(int, int, int, boolean, java.nio.FloatBuffer); + method public static void glSampleMaski(int, int); + method public static void glTexStorage2DMultisample(int, int, int, int, int, boolean); + method public static void glUseProgramStages(int, int, int); + method public static void glValidateProgramPipeline(int); + method public static void glVertexAttribBinding(int, int); + method public static void glVertexAttribFormat(int, int, int, boolean, int); + method public static void glVertexAttribIFormat(int, int, int, int); + method public static void glVertexBindingDivisor(int, int); + field public static final int GL_ACTIVE_ATOMIC_COUNTER_BUFFERS = 37593; // 0x92d9 + field public static final int GL_ACTIVE_PROGRAM = 33369; // 0x8259 + field public static final int GL_ACTIVE_RESOURCES = 37621; // 0x92f5 + field public static final int GL_ACTIVE_VARIABLES = 37637; // 0x9305 + field public static final int GL_ALL_SHADER_BITS = -1; // 0xffffffff + field public static final int GL_ARRAY_SIZE = 37627; // 0x92fb + field public static final int GL_ARRAY_STRIDE = 37630; // 0x92fe + field public static final int GL_ATOMIC_COUNTER_BARRIER_BIT = 4096; // 0x1000 + field public static final int GL_ATOMIC_COUNTER_BUFFER = 37568; // 0x92c0 + field public static final int GL_ATOMIC_COUNTER_BUFFER_BINDING = 37569; // 0x92c1 + field public static final int GL_ATOMIC_COUNTER_BUFFER_INDEX = 37633; // 0x9301 + field public static final int GL_ATOMIC_COUNTER_BUFFER_SIZE = 37571; // 0x92c3 + field public static final int GL_ATOMIC_COUNTER_BUFFER_START = 37570; // 0x92c2 + field public static final int GL_BLOCK_INDEX = 37629; // 0x92fd + field public static final int GL_BUFFER_BINDING = 37634; // 0x9302 + field public static final int GL_BUFFER_DATA_SIZE = 37635; // 0x9303 + field public static final int GL_BUFFER_UPDATE_BARRIER_BIT = 512; // 0x200 + field public static final int GL_BUFFER_VARIABLE = 37605; // 0x92e5 + field public static final int GL_COMMAND_BARRIER_BIT = 64; // 0x40 + field public static final int GL_COMPUTE_SHADER = 37305; // 0x91b9 + field public static final int GL_COMPUTE_SHADER_BIT = 32; // 0x20 + field public static final int GL_COMPUTE_WORK_GROUP_SIZE = 33383; // 0x8267 + field public static final int GL_DEPTH_STENCIL_TEXTURE_MODE = 37098; // 0x90ea + field public static final int GL_DISPATCH_INDIRECT_BUFFER = 37102; // 0x90ee + field public static final int GL_DISPATCH_INDIRECT_BUFFER_BINDING = 37103; // 0x90ef + field public static final int GL_DRAW_INDIRECT_BUFFER = 36671; // 0x8f3f + field public static final int GL_DRAW_INDIRECT_BUFFER_BINDING = 36675; // 0x8f43 + field public static final int GL_FRAGMENT_SHADER_BIT = 2; // 0x2 + field public static final int GL_FRAMEBUFFER_BARRIER_BIT = 1024; // 0x400 + field public static final int GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS = 37652; // 0x9314 + field public static final int GL_FRAMEBUFFER_DEFAULT_HEIGHT = 37649; // 0x9311 + field public static final int GL_FRAMEBUFFER_DEFAULT_SAMPLES = 37651; // 0x9313 + field public static final int GL_FRAMEBUFFER_DEFAULT_WIDTH = 37648; // 0x9310 + field public static final int GL_IMAGE_2D = 36941; // 0x904d + field public static final int GL_IMAGE_2D_ARRAY = 36947; // 0x9053 + field public static final int GL_IMAGE_3D = 36942; // 0x904e + field public static final int GL_IMAGE_BINDING_ACCESS = 36670; // 0x8f3e + field public static final int GL_IMAGE_BINDING_FORMAT = 36974; // 0x906e + field public static final int GL_IMAGE_BINDING_LAYER = 36669; // 0x8f3d + field public static final int GL_IMAGE_BINDING_LAYERED = 36668; // 0x8f3c + field public static final int GL_IMAGE_BINDING_LEVEL = 36667; // 0x8f3b + field public static final int GL_IMAGE_BINDING_NAME = 36666; // 0x8f3a + field public static final int GL_IMAGE_CUBE = 36944; // 0x9050 + field public static final int GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS = 37065; // 0x90c9 + field public static final int GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE = 37064; // 0x90c8 + field public static final int GL_IMAGE_FORMAT_COMPATIBILITY_TYPE = 37063; // 0x90c7 + field public static final int GL_INT_IMAGE_2D = 36952; // 0x9058 + field public static final int GL_INT_IMAGE_2D_ARRAY = 36958; // 0x905e + field public static final int GL_INT_IMAGE_3D = 36953; // 0x9059 + field public static final int GL_INT_IMAGE_CUBE = 36955; // 0x905b + field public static final int GL_INT_SAMPLER_2D_MULTISAMPLE = 37129; // 0x9109 + field public static final int GL_IS_ROW_MAJOR = 37632; // 0x9300 + field public static final int GL_LOCATION = 37646; // 0x930e + field public static final int GL_MATRIX_STRIDE = 37631; // 0x92ff + field public static final int GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = 37596; // 0x92dc + field public static final int GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE = 37592; // 0x92d8 + field public static final int GL_MAX_COLOR_TEXTURE_SAMPLES = 37134; // 0x910e + field public static final int GL_MAX_COMBINED_ATOMIC_COUNTERS = 37591; // 0x92d7 + field public static final int GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS = 37585; // 0x92d1 + field public static final int GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS = 33382; // 0x8266 + field public static final int GL_MAX_COMBINED_IMAGE_UNIFORMS = 37071; // 0x90cf + field public static final int GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES = 36665; // 0x8f39 + field public static final int GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS = 37084; // 0x90dc + field public static final int GL_MAX_COMPUTE_ATOMIC_COUNTERS = 33381; // 0x8265 + field public static final int GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS = 33380; // 0x8264 + field public static final int GL_MAX_COMPUTE_IMAGE_UNIFORMS = 37309; // 0x91bd + field public static final int GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS = 37083; // 0x90db + field public static final int GL_MAX_COMPUTE_SHARED_MEMORY_SIZE = 33378; // 0x8262 + field public static final int GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS = 37308; // 0x91bc + field public static final int GL_MAX_COMPUTE_UNIFORM_BLOCKS = 37307; // 0x91bb + field public static final int GL_MAX_COMPUTE_UNIFORM_COMPONENTS = 33379; // 0x8263 + field public static final int GL_MAX_COMPUTE_WORK_GROUP_COUNT = 37310; // 0x91be + field public static final int GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS = 37099; // 0x90eb + field public static final int GL_MAX_COMPUTE_WORK_GROUP_SIZE = 37311; // 0x91bf + field public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES = 37135; // 0x910f + field public static final int GL_MAX_FRAGMENT_ATOMIC_COUNTERS = 37590; // 0x92d6 + field public static final int GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS = 37584; // 0x92d0 + field public static final int GL_MAX_FRAGMENT_IMAGE_UNIFORMS = 37070; // 0x90ce + field public static final int GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS = 37082; // 0x90da + field public static final int GL_MAX_FRAMEBUFFER_HEIGHT = 37654; // 0x9316 + field public static final int GL_MAX_FRAMEBUFFER_SAMPLES = 37656; // 0x9318 + field public static final int GL_MAX_FRAMEBUFFER_WIDTH = 37653; // 0x9315 + field public static final int GL_MAX_IMAGE_UNITS = 36664; // 0x8f38 + field public static final int GL_MAX_INTEGER_SAMPLES = 37136; // 0x9110 + field public static final int GL_MAX_NAME_LENGTH = 37622; // 0x92f6 + field public static final int GL_MAX_NUM_ACTIVE_VARIABLES = 37623; // 0x92f7 + field public static final int GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET = 36447; // 0x8e5f + field public static final int GL_MAX_SAMPLE_MASK_WORDS = 36441; // 0x8e59 + field public static final int GL_MAX_SHADER_STORAGE_BLOCK_SIZE = 37086; // 0x90de + field public static final int GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS = 37085; // 0x90dd + field public static final int GL_MAX_UNIFORM_LOCATIONS = 33390; // 0x826e + field public static final int GL_MAX_VERTEX_ATOMIC_COUNTERS = 37586; // 0x92d2 + field public static final int GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS = 37580; // 0x92cc + field public static final int GL_MAX_VERTEX_ATTRIB_BINDINGS = 33498; // 0x82da + field public static final int GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET = 33497; // 0x82d9 + field public static final int GL_MAX_VERTEX_ATTRIB_STRIDE = 33509; // 0x82e5 + field public static final int GL_MAX_VERTEX_IMAGE_UNIFORMS = 37066; // 0x90ca + field public static final int GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS = 37078; // 0x90d6 + field public static final int GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET = 36446; // 0x8e5e + field public static final int GL_NAME_LENGTH = 37625; // 0x92f9 + field public static final int GL_NUM_ACTIVE_VARIABLES = 37636; // 0x9304 + field public static final int GL_OFFSET = 37628; // 0x92fc + field public static final int GL_PIXEL_BUFFER_BARRIER_BIT = 128; // 0x80 + field public static final int GL_PROGRAM_INPUT = 37603; // 0x92e3 + field public static final int GL_PROGRAM_OUTPUT = 37604; // 0x92e4 + field public static final int GL_PROGRAM_PIPELINE_BINDING = 33370; // 0x825a + field public static final int GL_PROGRAM_SEPARABLE = 33368; // 0x8258 + field public static final int GL_READ_ONLY = 35000; // 0x88b8 + field public static final int GL_READ_WRITE = 35002; // 0x88ba + field public static final int GL_REFERENCED_BY_COMPUTE_SHADER = 37643; // 0x930b + field public static final int GL_REFERENCED_BY_FRAGMENT_SHADER = 37642; // 0x930a + field public static final int GL_REFERENCED_BY_VERTEX_SHADER = 37638; // 0x9306 + field public static final int GL_SAMPLER_2D_MULTISAMPLE = 37128; // 0x9108 + field public static final int GL_SAMPLE_MASK = 36433; // 0x8e51 + field public static final int GL_SAMPLE_MASK_VALUE = 36434; // 0x8e52 + field public static final int GL_SAMPLE_POSITION = 36432; // 0x8e50 + field public static final int GL_SHADER_STORAGE_BARRIER_BIT = 8192; // 0x2000 + field public static final int GL_SHADER_STORAGE_BLOCK = 37606; // 0x92e6 + field public static final int GL_SHADER_STORAGE_BUFFER = 37074; // 0x90d2 + field public static final int GL_SHADER_STORAGE_BUFFER_BINDING = 37075; // 0x90d3 + field public static final int GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = 37087; // 0x90df + field public static final int GL_SHADER_STORAGE_BUFFER_SIZE = 37077; // 0x90d5 + field public static final int GL_SHADER_STORAGE_BUFFER_START = 37076; // 0x90d4 + field public static final int GL_STENCIL_INDEX = 6401; // 0x1901 + field public static final int GL_TEXTURE_2D_MULTISAMPLE = 37120; // 0x9100 + field public static final int GL_TEXTURE_ALPHA_SIZE = 32863; // 0x805f + field public static final int GL_TEXTURE_ALPHA_TYPE = 35859; // 0x8c13 + field public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE = 37124; // 0x9104 + field public static final int GL_TEXTURE_BLUE_SIZE = 32862; // 0x805e + field public static final int GL_TEXTURE_BLUE_TYPE = 35858; // 0x8c12 + field public static final int GL_TEXTURE_COMPRESSED = 34465; // 0x86a1 + field public static final int GL_TEXTURE_DEPTH = 32881; // 0x8071 + field public static final int GL_TEXTURE_DEPTH_SIZE = 34890; // 0x884a + field public static final int GL_TEXTURE_DEPTH_TYPE = 35862; // 0x8c16 + field public static final int GL_TEXTURE_FETCH_BARRIER_BIT = 8; // 0x8 + field public static final int GL_TEXTURE_FIXED_SAMPLE_LOCATIONS = 37127; // 0x9107 + field public static final int GL_TEXTURE_GREEN_SIZE = 32861; // 0x805d + field public static final int GL_TEXTURE_GREEN_TYPE = 35857; // 0x8c11 + field public static final int GL_TEXTURE_HEIGHT = 4097; // 0x1001 + field public static final int GL_TEXTURE_INTERNAL_FORMAT = 4099; // 0x1003 + field public static final int GL_TEXTURE_RED_SIZE = 32860; // 0x805c + field public static final int GL_TEXTURE_RED_TYPE = 35856; // 0x8c10 + field public static final int GL_TEXTURE_SAMPLES = 37126; // 0x9106 + field public static final int GL_TEXTURE_SHARED_SIZE = 35903; // 0x8c3f + field public static final int GL_TEXTURE_STENCIL_SIZE = 35057; // 0x88f1 + field public static final int GL_TEXTURE_UPDATE_BARRIER_BIT = 256; // 0x100 + field public static final int GL_TEXTURE_WIDTH = 4096; // 0x1000 + field public static final int GL_TOP_LEVEL_ARRAY_SIZE = 37644; // 0x930c + field public static final int GL_TOP_LEVEL_ARRAY_STRIDE = 37645; // 0x930d + field public static final int GL_TRANSFORM_FEEDBACK_BARRIER_BIT = 2048; // 0x800 + field public static final int GL_TRANSFORM_FEEDBACK_VARYING = 37620; // 0x92f4 + field public static final int GL_TYPE = 37626; // 0x92fa + field public static final int GL_UNIFORM = 37601; // 0x92e1 + field public static final int GL_UNIFORM_BARRIER_BIT = 4; // 0x4 + field public static final int GL_UNIFORM_BLOCK = 37602; // 0x92e2 + field public static final int GL_UNSIGNED_INT_ATOMIC_COUNTER = 37595; // 0x92db + field public static final int GL_UNSIGNED_INT_IMAGE_2D = 36963; // 0x9063 + field public static final int GL_UNSIGNED_INT_IMAGE_2D_ARRAY = 36969; // 0x9069 + field public static final int GL_UNSIGNED_INT_IMAGE_3D = 36964; // 0x9064 + field public static final int GL_UNSIGNED_INT_IMAGE_CUBE = 36966; // 0x9066 + field public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = 37130; // 0x910a + field public static final int GL_VERTEX_ATTRIB_BINDING = 33492; // 0x82d4 + field public static final int GL_VERTEX_ATTRIB_RELATIVE_OFFSET = 33493; // 0x82d5 + field public static final int GL_VERTEX_BINDING_BUFFER = 36687; // 0x8f4f + field public static final int GL_VERTEX_BINDING_DIVISOR = 33494; // 0x82d6 + field public static final int GL_VERTEX_BINDING_OFFSET = 33495; // 0x82d7 + field public static final int GL_VERTEX_BINDING_STRIDE = 33496; // 0x82d8 + field public static final int GL_VERTEX_SHADER_BIT = 1; // 0x1 + field public static final int GL_WRITE_ONLY = 35001; // 0x88b9 + } + + public class GLES31Ext { + method public static void glBlendBarrierKHR(); + method public static void glBlendEquationSeparateiEXT(int, int, int); + method public static void glBlendEquationiEXT(int, int); + method public static void glBlendFuncSeparateiEXT(int, int, int, int, int); + method public static void glBlendFunciEXT(int, int, int); + method public static void glColorMaskiEXT(int, boolean, boolean, boolean, boolean); + method public static void glCopyImageSubDataEXT(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); + method public static void glDebugMessageCallbackKHR(android.opengl.GLES31Ext.DebugProcKHR); + method public static void glDebugMessageControlKHR(int, int, int, int, int[], int, boolean); + method public static void glDebugMessageControlKHR(int, int, int, int, java.nio.IntBuffer, boolean); + method public static void glDebugMessageInsertKHR(int, int, int, int, java.lang.String); + method public static void glDisableiEXT(int, int); + method public static void glEnableiEXT(int, int); + method public static void glFramebufferTextureEXT(int, int, int, int); + method public static android.opengl.GLES31Ext.DebugProcKHR glGetDebugMessageCallbackKHR(); + method public static int glGetDebugMessageLogKHR(int, int, int[], int, int[], int, int[], int, int[], int, int[], int, byte[], int); + method public static int glGetDebugMessageLogKHR(int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer); + method public static java.lang.String[] glGetDebugMessageLogKHR(int, int[], int, int[], int, int[], int, int[], int); + method public static java.lang.String[] glGetDebugMessageLogKHR(int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer); + method public static java.lang.String glGetObjectLabelKHR(int, int); + method public static java.lang.String glGetObjectPtrLabelKHR(long); + method public static void glGetSamplerParameterIivEXT(int, int, int[], int); + method public static void glGetSamplerParameterIivEXT(int, int, java.nio.IntBuffer); + method public static void glGetSamplerParameterIuivEXT(int, int, int[], int); + method public static void glGetSamplerParameterIuivEXT(int, int, java.nio.IntBuffer); + method public static void glGetTexParameterIivEXT(int, int, int[], int); + method public static void glGetTexParameterIivEXT(int, int, java.nio.IntBuffer); + method public static void glGetTexParameterIuivEXT(int, int, int[], int); + method public static void glGetTexParameterIuivEXT(int, int, java.nio.IntBuffer); + method public static boolean glIsEnablediEXT(int, int); + method public static void glMinSampleShadingOES(float); + method public static void glObjectLabelKHR(int, int, int, java.lang.String); + method public static void glObjectPtrLabelKHR(long, java.lang.String); + method public static void glPatchParameteriEXT(int, int); + method public static void glPopDebugGroupKHR(); + method public static void glPrimitiveBoundingBoxEXT(float, float, float, float, float, float, float, float); + method public static void glPushDebugGroupKHR(int, int, int, java.lang.String); + method public static void glSamplerParameterIivEXT(int, int, int[], int); + method public static void glSamplerParameterIivEXT(int, int, java.nio.IntBuffer); + method public static void glSamplerParameterIuivEXT(int, int, int[], int); + method public static void glSamplerParameterIuivEXT(int, int, java.nio.IntBuffer); + method public static void glTexBufferEXT(int, int, int); + method public static void glTexBufferRangeEXT(int, int, int, int, int); + method public static void glTexParameterIivEXT(int, int, int[], int); + method public static void glTexParameterIivEXT(int, int, java.nio.IntBuffer); + method public static void glTexParameterIuivEXT(int, int, int[], int); + method public static void glTexParameterIuivEXT(int, int, java.nio.IntBuffer); + method public static void glTexStorage3DMultisampleOES(int, int, int, int, int, int, boolean); + field public static final int GL_BLEND_ADVANCED_COHERENT_KHR = 37509; // 0x9285 + field public static final int GL_BUFFER_KHR = 33504; // 0x82e0 + field public static final int GL_CLAMP_TO_BORDER_EXT = 33069; // 0x812d + field public static final int GL_COLORBURN_KHR = 37530; // 0x929a + field public static final int GL_COLORDODGE_KHR = 37529; // 0x9299 + field public static final int GL_COMPRESSED_RGBA_ASTC_10x10_KHR = 37819; // 0x93bb + field public static final int GL_COMPRESSED_RGBA_ASTC_10x5_KHR = 37816; // 0x93b8 + field public static final int GL_COMPRESSED_RGBA_ASTC_10x6_KHR = 37817; // 0x93b9 + field public static final int GL_COMPRESSED_RGBA_ASTC_10x8_KHR = 37818; // 0x93ba + field public static final int GL_COMPRESSED_RGBA_ASTC_12x10_KHR = 37820; // 0x93bc + field public static final int GL_COMPRESSED_RGBA_ASTC_12x12_KHR = 37821; // 0x93bd + field public static final int GL_COMPRESSED_RGBA_ASTC_4x4_KHR = 37808; // 0x93b0 + field public static final int GL_COMPRESSED_RGBA_ASTC_5x4_KHR = 37809; // 0x93b1 + field public static final int GL_COMPRESSED_RGBA_ASTC_5x5_KHR = 37810; // 0x93b2 + field public static final int GL_COMPRESSED_RGBA_ASTC_6x5_KHR = 37811; // 0x93b3 + field public static final int GL_COMPRESSED_RGBA_ASTC_6x6_KHR = 37812; // 0x93b4 + field public static final int GL_COMPRESSED_RGBA_ASTC_8x5_KHR = 37813; // 0x93b5 + field public static final int GL_COMPRESSED_RGBA_ASTC_8x6_KHR = 37814; // 0x93b6 + field public static final int GL_COMPRESSED_RGBA_ASTC_8x8_KHR = 37815; // 0x93b7 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 37851; // 0x93db + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 37848; // 0x93d8 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 37849; // 0x93d9 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 37850; // 0x93da + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 37852; // 0x93dc + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 37853; // 0x93dd + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 37840; // 0x93d0 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 37841; // 0x93d1 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 37842; // 0x93d2 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 37843; // 0x93d3 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 37844; // 0x93d4 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 37845; // 0x93d5 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 37846; // 0x93d6 + field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 37847; // 0x93d7 + field public static final int GL_CONTEXT_FLAG_DEBUG_BIT_KHR = 2; // 0x2 + field public static final int GL_DARKEN_KHR = 37527; // 0x9297 + field public static final int GL_DEBUG_CALLBACK_FUNCTION_KHR = 33348; // 0x8244 + field public static final int GL_DEBUG_CALLBACK_USER_PARAM_KHR = 33349; // 0x8245 + field public static final int GL_DEBUG_GROUP_STACK_DEPTH_KHR = 33389; // 0x826d + field public static final int GL_DEBUG_LOGGED_MESSAGES_KHR = 37189; // 0x9145 + field public static final int GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR = 33347; // 0x8243 + field public static final int GL_DEBUG_OUTPUT_KHR = 37600; // 0x92e0 + field public static final int GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR = 33346; // 0x8242 + field public static final int GL_DEBUG_SEVERITY_HIGH_KHR = 37190; // 0x9146 + field public static final int GL_DEBUG_SEVERITY_LOW_KHR = 37192; // 0x9148 + field public static final int GL_DEBUG_SEVERITY_MEDIUM_KHR = 37191; // 0x9147 + field public static final int GL_DEBUG_SEVERITY_NOTIFICATION_KHR = 33387; // 0x826b + field public static final int GL_DEBUG_SOURCE_API_KHR = 33350; // 0x8246 + field public static final int GL_DEBUG_SOURCE_APPLICATION_KHR = 33354; // 0x824a + field public static final int GL_DEBUG_SOURCE_OTHER_KHR = 33355; // 0x824b + field public static final int GL_DEBUG_SOURCE_SHADER_COMPILER_KHR = 33352; // 0x8248 + field public static final int GL_DEBUG_SOURCE_THIRD_PARTY_KHR = 33353; // 0x8249 + field public static final int GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR = 33351; // 0x8247 + field public static final int GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR = 33357; // 0x824d + field public static final int GL_DEBUG_TYPE_ERROR_KHR = 33356; // 0x824c + field public static final int GL_DEBUG_TYPE_MARKER_KHR = 33384; // 0x8268 + field public static final int GL_DEBUG_TYPE_OTHER_KHR = 33361; // 0x8251 + field public static final int GL_DEBUG_TYPE_PERFORMANCE_KHR = 33360; // 0x8250 + field public static final int GL_DEBUG_TYPE_POP_GROUP_KHR = 33386; // 0x826a + field public static final int GL_DEBUG_TYPE_PORTABILITY_KHR = 33359; // 0x824f + field public static final int GL_DEBUG_TYPE_PUSH_GROUP_KHR = 33385; // 0x8269 + field public static final int GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR = 33358; // 0x824e + field public static final int GL_DECODE_EXT = 35401; // 0x8a49 + field public static final int GL_DIFFERENCE_KHR = 37534; // 0x929e + field public static final int GL_EXCLUSION_KHR = 37536; // 0x92a0 + field public static final int GL_FIRST_VERTEX_CONVENTION_EXT = 36429; // 0x8e4d + field public static final int GL_FRACTIONAL_EVEN_EXT = 36476; // 0x8e7c + field public static final int GL_FRACTIONAL_ODD_EXT = 36475; // 0x8e7b + field public static final int GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES = 36445; // 0x8e5d + field public static final int GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT = 36263; // 0x8da7 + field public static final int GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT = 37650; // 0x9312 + field public static final int GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT = 36264; // 0x8da8 + field public static final int GL_GEOMETRY_LINKED_INPUT_TYPE_EXT = 35095; // 0x8917 + field public static final int GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT = 35096; // 0x8918 + field public static final int GL_GEOMETRY_LINKED_VERTICES_OUT_EXT = 35094; // 0x8916 + field public static final int GL_GEOMETRY_SHADER_BIT_EXT = 4; // 0x4 + field public static final int GL_GEOMETRY_SHADER_EXT = 36313; // 0x8dd9 + field public static final int GL_GEOMETRY_SHADER_INVOCATIONS_EXT = 34943; // 0x887f + field public static final int GL_HARDLIGHT_KHR = 37531; // 0x929b + field public static final int GL_HSL_COLOR_KHR = 37551; // 0x92af + field public static final int GL_HSL_HUE_KHR = 37549; // 0x92ad + field public static final int GL_HSL_LUMINOSITY_KHR = 37552; // 0x92b0 + field public static final int GL_HSL_SATURATION_KHR = 37550; // 0x92ae + field public static final int GL_IMAGE_BUFFER_EXT = 36945; // 0x9051 + field public static final int GL_IMAGE_CUBE_MAP_ARRAY_EXT = 36948; // 0x9054 + field public static final int GL_INT_IMAGE_BUFFER_EXT = 36956; // 0x905c + field public static final int GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT = 36959; // 0x905f + field public static final int GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES = 37132; // 0x910c + field public static final int GL_INT_SAMPLER_BUFFER_EXT = 36304; // 0x8dd0 + field public static final int GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT = 36878; // 0x900e + field public static final int GL_ISOLINES_EXT = 36474; // 0x8e7a + field public static final int GL_IS_PER_PATCH_EXT = 37607; // 0x92e7 + field public static final int GL_LAST_VERTEX_CONVENTION_EXT = 36430; // 0x8e4e + field public static final int GL_LAYER_PROVOKING_VERTEX_EXT = 33374; // 0x825e + field public static final int GL_LIGHTEN_KHR = 37528; // 0x9298 + field public static final int GL_LINES_ADJACENCY_EXT = 10; // 0xa + field public static final int GL_LINE_STRIP_ADJACENCY_EXT = 11; // 0xb + field public static final int GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT = 35378; // 0x8a32 + field public static final int GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT = 36382; // 0x8e1e + field public static final int GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT = 36383; // 0x8e1f + field public static final int GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR = 33388; // 0x826c + field public static final int GL_MAX_DEBUG_LOGGED_MESSAGES_KHR = 37188; // 0x9144 + field public static final int GL_MAX_DEBUG_MESSAGE_LENGTH_KHR = 37187; // 0x9143 + field public static final int GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES = 36444; // 0x8e5c + field public static final int GL_MAX_FRAMEBUFFER_LAYERS_EXT = 37655; // 0x9317 + field public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT = 37589; // 0x92d5 + field public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT = 37583; // 0x92cf + field public static final int GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT = 37069; // 0x90cd + field public static final int GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT = 37155; // 0x9123 + field public static final int GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT = 37156; // 0x9124 + field public static final int GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT = 36320; // 0x8de0 + field public static final int GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT = 36442; // 0x8e5a + field public static final int GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT = 37079; // 0x90d7 + field public static final int GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT = 35881; // 0x8c29 + field public static final int GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT = 36321; // 0x8de1 + field public static final int GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT = 35372; // 0x8a2c + field public static final int GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT = 36319; // 0x8ddf + field public static final int GL_MAX_LABEL_LENGTH_KHR = 33512; // 0x82e8 + field public static final int GL_MAX_PATCH_VERTICES_EXT = 36477; // 0x8e7d + field public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT = 37587; // 0x92d3 + field public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT = 37581; // 0x92cd + field public static final int GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT = 37067; // 0x90cb + field public static final int GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT = 34924; // 0x886c + field public static final int GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT = 36483; // 0x8e83 + field public static final int GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT = 37080; // 0x90d8 + field public static final int GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT = 36481; // 0x8e81 + field public static final int GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT = 36485; // 0x8e85 + field public static final int GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT = 36489; // 0x8e89 + field public static final int GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT = 36479; // 0x8e7f + field public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT = 37588; // 0x92d4 + field public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT = 37582; // 0x92ce + field public static final int GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT = 37068; // 0x90cc + field public static final int GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT = 34925; // 0x886d + field public static final int GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT = 36486; // 0x8e86 + field public static final int GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT = 37081; // 0x90d9 + field public static final int GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT = 36482; // 0x8e82 + field public static final int GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT = 36490; // 0x8e8a + field public static final int GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT = 36480; // 0x8e80 + field public static final int GL_MAX_TESS_GEN_LEVEL_EXT = 36478; // 0x8e7e + field public static final int GL_MAX_TESS_PATCH_COMPONENTS_EXT = 36484; // 0x8e84 + field public static final int GL_MAX_TEXTURE_BUFFER_SIZE_EXT = 35883; // 0x8c2b + field public static final int GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES = 36443; // 0x8e5b + field public static final int GL_MIN_SAMPLE_SHADING_VALUE_OES = 35895; // 0x8c37 + field public static final int GL_MULTIPLY_KHR = 37524; // 0x9294 + field public static final int GL_OVERLAY_KHR = 37526; // 0x9296 + field public static final int GL_PATCHES_EXT = 14; // 0xe + field public static final int GL_PATCH_VERTICES_EXT = 36466; // 0x8e72 + field public static final int GL_PRIMITIVES_GENERATED_EXT = 35975; // 0x8c87 + field public static final int GL_PRIMITIVE_BOUNDING_BOX_EXT = 37566; // 0x92be + field public static final int GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED = 33313; // 0x8221 + field public static final int GL_PROGRAM_KHR = 33506; // 0x82e2 + field public static final int GL_QUADS_EXT = 7; // 0x7 + field public static final int GL_QUERY_KHR = 33507; // 0x82e3 + field public static final int GL_REFERENCED_BY_GEOMETRY_SHADER_EXT = 37641; // 0x9309 + field public static final int GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT = 37639; // 0x9307 + field public static final int GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT = 37640; // 0x9308 + field public static final int GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES = 37131; // 0x910b + field public static final int GL_SAMPLER_BUFFER_EXT = 36290; // 0x8dc2 + field public static final int GL_SAMPLER_CUBE_MAP_ARRAY_EXT = 36876; // 0x900c + field public static final int GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT = 36877; // 0x900d + field public static final int GL_SAMPLER_KHR = 33510; // 0x82e6 + field public static final int GL_SAMPLE_SHADING_OES = 35894; // 0x8c36 + field public static final int GL_SCREEN_KHR = 37525; // 0x9295 + field public static final int GL_SHADER_KHR = 33505; // 0x82e1 + field public static final int GL_SKIP_DECODE_EXT = 35402; // 0x8a4a + field public static final int GL_SOFTLIGHT_KHR = 37532; // 0x929c + field public static final int GL_STACK_OVERFLOW_KHR = 1283; // 0x503 + field public static final int GL_STACK_UNDERFLOW_KHR = 1284; // 0x504 + field public static final int GL_STENCIL_INDEX8_OES = 36168; // 0x8d48 + field public static final int GL_STENCIL_INDEX_OES = 6401; // 0x1901 + field public static final int GL_TESS_CONTROL_OUTPUT_VERTICES_EXT = 36469; // 0x8e75 + field public static final int GL_TESS_CONTROL_SHADER_BIT_EXT = 8; // 0x8 + field public static final int GL_TESS_CONTROL_SHADER_EXT = 36488; // 0x8e88 + field public static final int GL_TESS_EVALUATION_SHADER_BIT_EXT = 16; // 0x10 + field public static final int GL_TESS_EVALUATION_SHADER_EXT = 36487; // 0x8e87 + field public static final int GL_TESS_GEN_MODE_EXT = 36470; // 0x8e76 + field public static final int GL_TESS_GEN_POINT_MODE_EXT = 36473; // 0x8e79 + field public static final int GL_TESS_GEN_SPACING_EXT = 36471; // 0x8e77 + field public static final int GL_TESS_GEN_VERTEX_ORDER_EXT = 36472; // 0x8e78 + field public static final int GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES = 37122; // 0x9102 + field public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES = 37125; // 0x9105 + field public static final int GL_TEXTURE_BINDING_BUFFER_EXT = 35884; // 0x8c2c + field public static final int GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT = 36874; // 0x900a + field public static final int GL_TEXTURE_BORDER_COLOR_EXT = 4100; // 0x1004 + field public static final int GL_TEXTURE_BUFFER_BINDING_EXT = 35882; // 0x8c2a + field public static final int GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT = 35885; // 0x8c2d + field public static final int GL_TEXTURE_BUFFER_EXT = 35882; // 0x8c2a + field public static final int GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT = 37279; // 0x919f + field public static final int GL_TEXTURE_BUFFER_OFFSET_EXT = 37277; // 0x919d + field public static final int GL_TEXTURE_BUFFER_SIZE_EXT = 37278; // 0x919e + field public static final int GL_TEXTURE_CUBE_MAP_ARRAY_EXT = 36873; // 0x9009 + field public static final int GL_TEXTURE_SRGB_DECODE_EXT = 35400; // 0x8a48 + field public static final int GL_TRIANGLES_ADJACENCY_EXT = 12; // 0xc + field public static final int GL_TRIANGLE_STRIP_ADJACENCY_EXT = 13; // 0xd + field public static final int GL_UNDEFINED_VERTEX_EXT = 33376; // 0x8260 + field public static final int GL_UNSIGNED_INT_IMAGE_BUFFER_EXT = 36967; // 0x9067 + field public static final int GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT = 36970; // 0x906a + field public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES = 37133; // 0x910d + field public static final int GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT = 36312; // 0x8dd8 + field public static final int GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT = 36879; // 0x900f + field public static final int GL_VERTEX_ARRAY_KHR = 32884; // 0x8074 + } + + public static abstract interface GLES31Ext.DebugProcKHR { + method public abstract void onMessage(int, int, int, int, java.lang.String); + } + public class GLException extends java.lang.RuntimeException { ctor public GLException(int); ctor public GLException(int, java.lang.String); @@ -17508,8 +21248,41 @@ ctor public BadParcelableException(java.lang.Exception); } + public class BaseBundle { + method public void clear(); + method public boolean containsKey(java.lang.String); + method public java.lang.Object get(java.lang.String); + method public double getDouble(java.lang.String); + method public double getDouble(java.lang.String, double); + method public double[] getDoubleArray(java.lang.String); + method public int getInt(java.lang.String); + method public int getInt(java.lang.String, int); + method public int[] getIntArray(java.lang.String); + method public long getLong(java.lang.String); + method public long getLong(java.lang.String, long); + method public long[] getLongArray(java.lang.String); + method public java.lang.String getString(java.lang.String); + method public java.lang.String getString(java.lang.String, java.lang.String); + method public java.lang.String[] getStringArray(java.lang.String); + method public boolean isEmpty(); + method public java.util.Set<java.lang.String> keySet(); + method public void putAll(android.os.PersistableBundle); + method public void putDouble(java.lang.String, double); + method public void putDoubleArray(java.lang.String, double[]); + method public void putInt(java.lang.String, int); + method public void putIntArray(java.lang.String, int[]); + method public void putLong(java.lang.String, long); + method public void putLongArray(java.lang.String, long[]); + method public void putString(java.lang.String, java.lang.String); + method public void putStringArray(java.lang.String, java.lang.String[]); + method public void remove(java.lang.String); + method public int size(); + } + public class BatteryManager { ctor public BatteryManager(); + method public int getIntProperty(int); + method public long getLongProperty(int); field public static final int BATTERY_HEALTH_COLD = 7; // 0x7 field public static final int BATTERY_HEALTH_DEAD = 4; // 0x4 field public static final int BATTERY_HEALTH_GOOD = 2; // 0x2 @@ -17520,6 +21293,11 @@ field public static final int BATTERY_PLUGGED_AC = 1; // 0x1 field public static final int BATTERY_PLUGGED_USB = 2; // 0x2 field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4 + field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4 + field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1 + field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3 + field public static final int BATTERY_PROPERTY_CURRENT_NOW = 2; // 0x2 + field public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; // 0x5 field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2 field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3 field public static final int BATTERY_STATUS_FULL = 5; // 0x5 @@ -17566,8 +21344,8 @@ field public static final java.lang.String BOARD; field public static final java.lang.String BOOTLOADER; field public static final java.lang.String BRAND; - field public static final java.lang.String CPU_ABI; - field public static final java.lang.String CPU_ABI2; + field public static final deprecated java.lang.String CPU_ABI; + field public static final deprecated java.lang.String CPU_ABI2; field public static final java.lang.String DEVICE; field public static final java.lang.String DISPLAY; field public static final java.lang.String FINGERPRINT; @@ -17579,6 +21357,9 @@ field public static final java.lang.String PRODUCT; field public static final deprecated java.lang.String RADIO; field public static final java.lang.String SERIAL; + field public static final java.lang.String[] SUPPORTED_32_BIT_ABIS; + field public static final java.lang.String[] SUPPORTED_64_BIT_ABIS; + field public static final java.lang.String[] SUPPORTED_ABIS; field public static final java.lang.String TAGS; field public static final long TIME; field public static final java.lang.String TYPE; @@ -17618,18 +21399,17 @@ field public static final int JELLY_BEAN_MR2 = 18; // 0x12 field public static final int KITKAT = 19; // 0x13 field public static final int KITKAT_WATCH = 20; // 0x14 + field public static final int L = 21; // 0x15 } - public final class Bundle implements java.lang.Cloneable android.os.Parcelable { + public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { ctor public Bundle(); ctor public Bundle(java.lang.ClassLoader); ctor public Bundle(int); ctor public Bundle(android.os.Bundle); - method public void clear(); + ctor public Bundle(android.os.PersistableBundle); method public java.lang.Object clone(); - method public boolean containsKey(java.lang.String); method public int describeContents(); - method public java.lang.Object get(java.lang.String); method public android.os.IBinder getBinder(java.lang.String); method public boolean getBoolean(java.lang.String); method public boolean getBoolean(java.lang.String, boolean); @@ -17646,19 +21426,10 @@ method public java.lang.CharSequence[] getCharSequenceArray(java.lang.String); method public java.util.ArrayList<java.lang.CharSequence> getCharSequenceArrayList(java.lang.String); method public java.lang.ClassLoader getClassLoader(); - method public double getDouble(java.lang.String); - method public double getDouble(java.lang.String, double); - method public double[] getDoubleArray(java.lang.String); method public float getFloat(java.lang.String); method public float getFloat(java.lang.String, float); method public float[] getFloatArray(java.lang.String); - method public int getInt(java.lang.String); - method public int getInt(java.lang.String, int); - method public int[] getIntArray(java.lang.String); method public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(java.lang.String); - method public long getLong(java.lang.String); - method public long getLong(java.lang.String, long); - method public long[] getLongArray(java.lang.String); method public T getParcelable(java.lang.String); method public android.os.Parcelable[] getParcelableArray(java.lang.String); method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String); @@ -17666,14 +21437,11 @@ method public short getShort(java.lang.String); method public short getShort(java.lang.String, short); method public short[] getShortArray(java.lang.String); + method public android.util.Size getSize(java.lang.String); + method public android.util.SizeF getSizeF(java.lang.String); method public android.util.SparseArray<T> getSparseParcelableArray(java.lang.String); - method public java.lang.String getString(java.lang.String); - method public java.lang.String getString(java.lang.String, java.lang.String); - method public java.lang.String[] getStringArray(java.lang.String); method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String); method public boolean hasFileDescriptors(); - method public boolean isEmpty(); - method public java.util.Set<java.lang.String> keySet(); method public void putAll(android.os.Bundle); method public void putBinder(java.lang.String, android.os.IBinder); method public void putBoolean(java.lang.String, boolean); @@ -17686,29 +21454,21 @@ method public void putCharSequence(java.lang.String, java.lang.CharSequence); method public void putCharSequenceArray(java.lang.String, java.lang.CharSequence[]); method public void putCharSequenceArrayList(java.lang.String, java.util.ArrayList<java.lang.CharSequence>); - method public void putDouble(java.lang.String, double); - method public void putDoubleArray(java.lang.String, double[]); method public void putFloat(java.lang.String, float); method public void putFloatArray(java.lang.String, float[]); - method public void putInt(java.lang.String, int); - method public void putIntArray(java.lang.String, int[]); method public void putIntegerArrayList(java.lang.String, java.util.ArrayList<java.lang.Integer>); - method public void putLong(java.lang.String, long); - method public void putLongArray(java.lang.String, long[]); method public void putParcelable(java.lang.String, android.os.Parcelable); method public void putParcelableArray(java.lang.String, android.os.Parcelable[]); method public void putParcelableArrayList(java.lang.String, java.util.ArrayList<? extends android.os.Parcelable>); method public void putSerializable(java.lang.String, java.io.Serializable); method public void putShort(java.lang.String, short); method public void putShortArray(java.lang.String, short[]); + method public void putSize(java.lang.String, android.util.Size); + method public void putSizeF(java.lang.String, android.util.SizeF); method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>); - method public void putString(java.lang.String, java.lang.String); - method public void putStringArray(java.lang.String, java.lang.String[]); method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>); method public void readFromParcel(android.os.Parcel); - method public void remove(java.lang.String); method public void setClassLoader(java.lang.ClassLoader); - method public int size(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final android.os.Bundle EMPTY; @@ -17737,7 +21497,7 @@ public abstract class CountDownTimer { ctor public CountDownTimer(long, long); - method public final void cancel(); + method public final synchronized void cancel(); method public abstract void onFinish(); method public abstract void onTick(long); method public final synchronized android.os.CountDownTimer start(); @@ -17805,6 +21565,7 @@ method public static void startMethodTracing(java.lang.String); method public static void startMethodTracing(java.lang.String, int); method public static void startMethodTracing(java.lang.String, int, int); + method public static void startMethodTracingSampling(java.lang.String, int, int); method public static void startNativeTracing(); method public static deprecated void stopAllocCounting(); method public static void stopMethodTracing(); @@ -17888,10 +21649,13 @@ method public static java.io.File getExternalStorageDirectory(); method public static java.io.File getExternalStoragePublicDirectory(java.lang.String); method public static java.lang.String getExternalStorageState(); + method public static java.lang.String getExternalStorageState(java.io.File); method public static java.io.File getRootDirectory(); - method public static java.lang.String getStorageState(java.io.File); + method public static deprecated java.lang.String getStorageState(java.io.File); method public static boolean isExternalStorageEmulated(); + method public static boolean isExternalStorageEmulated(java.io.File); method public static boolean isExternalStorageRemovable(); + method public static boolean isExternalStorageRemovable(java.io.File); field public static java.lang.String DIRECTORY_ALARMS; field public static java.lang.String DIRECTORY_DCIM; field public static java.lang.String DIRECTORY_DOCUMENTS; @@ -18066,6 +21830,7 @@ field public int arg2; field public java.lang.Object obj; field public android.os.Messenger replyTo; + field public int sendingUid; field public int what; } @@ -18122,7 +21887,6 @@ method public final boolean hasFileDescriptors(); method public final byte[] marshall(); method public static android.os.Parcel obtain(); - method protected static final android.os.Parcel obtain(int); method public final java.lang.Object[] readArray(java.lang.ClassLoader); method public final java.util.ArrayList readArrayList(java.lang.ClassLoader); method public final void readBinderArray(android.os.IBinder[]); @@ -18149,7 +21913,11 @@ method public final void readMap(java.util.Map, java.lang.ClassLoader); method public final T readParcelable(java.lang.ClassLoader); method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader); + method public final android.os.PersistableBundle readPersistableBundle(); + method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader); method public final java.io.Serializable readSerializable(); + method public final android.util.Size readSize(); + method public final android.util.SizeF readSizeF(); method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader); method public final android.util.SparseBooleanArray readSparseBooleanArray(); method public final java.lang.String readString(); @@ -18189,7 +21957,10 @@ method public final void writeNoException(); method public final void writeParcelable(android.os.Parcelable, int); method public final void writeParcelableArray(T[], int); + method public final void writePersistableBundle(android.os.PersistableBundle); method public final void writeSerializable(java.io.Serializable); + method public final void writeSize(android.util.Size); + method public final void writeSizeF(android.util.SizeF); method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>); method public final void writeSparseBooleanArray(android.util.SparseBooleanArray); method public final void writeString(java.lang.String); @@ -18299,18 +22070,33 @@ field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2 } + public final class PersistableBundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { + ctor public PersistableBundle(); + ctor public PersistableBundle(int); + ctor public PersistableBundle(android.os.PersistableBundle); + method public java.lang.Object clone(); + method public int describeContents(); + method public android.os.PersistableBundle getPersistableBundle(java.lang.String); + method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final android.os.PersistableBundle EMPTY; + } + public final class PowerManager { - method public void goToSleep(long); method public boolean isInteractive(); + method public boolean isPowerSaveMode(); method public deprecated boolean isScreenOn(); + method public boolean isWakeLockLevelSupported(int); method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String); method public void reboot(java.lang.String); - method public void userActivity(long, boolean); - method public void wakeUp(long); field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000 + field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED"; field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000 field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1 + field public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; // 0x20 + field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1 field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6 } @@ -18320,6 +22106,7 @@ method public void acquire(long); method public boolean isHeld(); method public void release(); + method public void release(int); method public void setReferenceCounted(boolean); method public void setWorkSource(android.os.WorkSource); } @@ -18517,32 +22304,53 @@ method public int getUserCount(); method public android.os.UserHandle getUserForSerialNumber(long); method public java.lang.String getUserName(); + method public java.util.List<android.os.UserHandle> getUserProfiles(); method public android.os.Bundle getUserRestrictions(); method public android.os.Bundle getUserRestrictions(android.os.UserHandle); + method public boolean hasUserRestriction(java.lang.String); method public boolean isUserAGoat(); method public boolean isUserRunning(android.os.UserHandle); method public boolean isUserRunningOrStopping(android.os.UserHandle); method public boolean setRestrictionsChallenge(java.lang.String); - method public void setUserRestriction(java.lang.String, boolean); - method public void setUserRestrictions(android.os.Bundle); - method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle); + method public deprecated void setUserRestriction(java.lang.String, boolean); + method public deprecated void setUserRestrictions(android.os.Bundle); + method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle); + field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user"; + field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume"; + field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; + field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; + field public static final java.lang.String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks"; + field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering"; + field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn"; field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi"; + field public static final java.lang.String DISALLOW_CREATE_WINDOWS = "no_create_windows"; + field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste"; + field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features"; + field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset"; field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps"; field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources"; field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts"; + field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media"; + field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam"; + field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls"; field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user"; field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location"; + field public static final java.lang.String DISALLOW_SMS = "no_sms"; field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps"; + field public static final java.lang.String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone"; field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer"; + field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps"; } public abstract class Vibrator { method public abstract void cancel(); method public abstract boolean hasVibrator(); - method public abstract void vibrate(long); - method public abstract void vibrate(long[], int); + method public void vibrate(long); + method public void vibrate(long, android.media.AudioAttributes); + method public void vibrate(long[], int); + method public void vibrate(long[], int, android.media.AudioAttributes); } public class WorkSource implements android.os.Parcelable { @@ -18588,13 +22396,16 @@ public class CheckBoxPreference extends android.preference.TwoStatePreference { ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet, int); + ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet, int, int); ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet); ctor public CheckBoxPreference(android.content.Context); } public abstract class DialogPreference extends android.preference.Preference implements android.content.DialogInterface.OnClickListener android.content.DialogInterface.OnDismissListener android.preference.PreferenceManager.OnActivityDestroyListener { + ctor public DialogPreference(android.content.Context, android.util.AttributeSet, int, int); ctor public DialogPreference(android.content.Context, android.util.AttributeSet, int); ctor public DialogPreference(android.content.Context, android.util.AttributeSet); + ctor public DialogPreference(android.content.Context); method public android.app.Dialog getDialog(); method public android.graphics.drawable.Drawable getDialogIcon(); method public int getDialogLayoutResource(); @@ -18624,6 +22435,7 @@ } public class EditTextPreference extends android.preference.DialogPreference { + ctor public EditTextPreference(android.content.Context, android.util.AttributeSet, int, int); ctor public EditTextPreference(android.content.Context, android.util.AttributeSet, int); ctor public EditTextPreference(android.content.Context, android.util.AttributeSet); ctor public EditTextPreference(android.content.Context); @@ -18634,6 +22446,8 @@ } public class ListPreference extends android.preference.DialogPreference { + ctor public ListPreference(android.content.Context, android.util.AttributeSet, int, int); + ctor public ListPreference(android.content.Context, android.util.AttributeSet, int); ctor public ListPreference(android.content.Context, android.util.AttributeSet); ctor public ListPreference(android.content.Context); method public int findIndexOfValue(java.lang.String); @@ -18650,6 +22464,8 @@ } public class MultiSelectListPreference extends android.preference.DialogPreference { + ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet, int, int); + ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet, int); ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet); ctor public MultiSelectListPreference(android.content.Context); method public int findIndexOfValue(java.lang.String); @@ -18664,6 +22480,7 @@ } public class Preference implements java.lang.Comparable { + ctor public Preference(android.content.Context, android.util.AttributeSet, int, int); ctor public Preference(android.content.Context, android.util.AttributeSet, int); ctor public Preference(android.content.Context, android.util.AttributeSet); ctor public Preference(android.content.Context); @@ -18829,6 +22646,7 @@ } public class PreferenceCategory extends android.preference.PreferenceGroup { + ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet, int, int); ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet, int); ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet); ctor public PreferenceCategory(android.content.Context); @@ -18850,6 +22668,7 @@ } public abstract class PreferenceGroup extends android.preference.Preference { + ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet, int, int); ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet, int); ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet); method public void addItemFromInflater(android.preference.Preference); @@ -18904,6 +22723,7 @@ } public class RingtonePreference extends android.preference.Preference implements android.preference.PreferenceManager.OnActivityResultListener { + ctor public RingtonePreference(android.content.Context, android.util.AttributeSet, int, int); ctor public RingtonePreference(android.content.Context, android.util.AttributeSet, int); ctor public RingtonePreference(android.content.Context, android.util.AttributeSet); ctor public RingtonePreference(android.content.Context); @@ -18920,6 +22740,7 @@ } public class SwitchPreference extends android.preference.TwoStatePreference { + ctor public SwitchPreference(android.content.Context, android.util.AttributeSet, int, int); ctor public SwitchPreference(android.content.Context, android.util.AttributeSet, int); ctor public SwitchPreference(android.content.Context, android.util.AttributeSet); ctor public SwitchPreference(android.content.Context); @@ -18932,6 +22753,7 @@ } public abstract class TwoStatePreference extends android.preference.Preference { + ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet, int, int); ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet, int); ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet); ctor public TwoStatePreference(android.content.Context); @@ -19295,6 +23117,7 @@ method protected void onDisconnected(); method protected abstract void onPrintJobQueued(android.printservice.PrintJob); method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob); + field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO"; field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO"; field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService"; field public static final java.lang.String SERVICE_META_DATA = "android.printservice"; @@ -19687,16 +23510,28 @@ public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; + field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; + field public static final java.lang.String CACHED_MATCHED_NUMBER = "matched_number"; field public static final java.lang.String CACHED_NAME = "name"; + field public static final java.lang.String CACHED_NORMALIZED_NUMBER = "normalized_number"; field public static final java.lang.String CACHED_NUMBER_LABEL = "numberlabel"; field public static final java.lang.String CACHED_NUMBER_TYPE = "numbertype"; + field public static final java.lang.String CACHED_PHOTO_ID = "photo_id"; field public static final android.net.Uri CONTENT_FILTER_URI; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/calls"; field public static final android.net.Uri CONTENT_URI; + field public static final android.net.Uri CONTENT_URI_WITH_VOICEMAIL; + field public static final java.lang.String COUNTRY_ISO = "countryiso"; + field public static final java.lang.String DATA_USAGE = "data_usage"; field public static final java.lang.String DATE = "date"; field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC"; field public static final java.lang.String DURATION = "duration"; + field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; + field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_VIDEO = 1; // 0x1 + field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 field public static final java.lang.String IS_READ = "is_read"; field public static final java.lang.String LIMIT_PARAM_KEY = "limit"; @@ -19706,11 +23541,16 @@ field public static final java.lang.String NUMBER_PRESENTATION = "presentation"; field public static final java.lang.String OFFSET_PARAM_KEY = "offset"; field public static final int OUTGOING_TYPE = 2; // 0x2 + field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name"; + field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 field public static final int PRESENTATION_PAYPHONE = 4; // 0x4 field public static final int PRESENTATION_RESTRICTED = 2; // 0x2 field public static final int PRESENTATION_UNKNOWN = 3; // 0x3 + field public static final java.lang.String TRANSCRIPTION = "transcription"; field public static final java.lang.String TYPE = "type"; + field public static final int VOICEMAIL_TYPE = 4; // 0x4 + field public static final java.lang.String VOICEMAIL_URI = "voicemail_uri"; } public deprecated class Contacts { @@ -20013,10 +23853,14 @@ field public static final java.lang.String AUTHORITY = "com.android.contacts"; field public static final android.net.Uri AUTHORITY_URI; field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; + field public static final java.lang.String DEFERRED_SNIPPETING = "deferred_snippeting"; + field public static final java.lang.String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query"; field public static final java.lang.String DIRECTORY_PARAM_KEY = "directory"; field public static final java.lang.String LIMIT_PARAM_KEY = "limit"; field public static final java.lang.String PRIMARY_ACCOUNT_NAME = "name_for_primary_account"; field public static final java.lang.String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account"; + field public static final java.lang.String REMOVE_DUPLICATE_ENTRIES = "remove_duplicate_entries"; + field public static final java.lang.String STREQUENT_PHONE_ONLY = "strequent_phone_only"; } public static final class ContactsContract.AggregationExceptions implements android.provider.BaseColumns { @@ -20045,6 +23889,15 @@ field public static final int TYPE_CUSTOM = 0; // 0x0 } + public static final class ContactsContract.CommonDataKinds.Callable implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { + ctor public ContactsContract.CommonDataKinds.Callable(); + field public static final android.net.Uri CONTENT_FILTER_URI; + field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; + } + protected static abstract interface ContactsContract.CommonDataKinds.CommonColumns implements android.provider.ContactsContract.CommonDataKinds.BaseTypes { field public static final java.lang.String DATA = "data1"; field public static final java.lang.String LABEL = "data3"; @@ -20055,6 +23908,9 @@ ctor public ContactsContract.CommonDataKinds.Contactables(); field public static final android.net.Uri CONTENT_FILTER_URI; field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only"; } @@ -20068,6 +23924,9 @@ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2"; field public static final android.net.Uri CONTENT_URI; field public static final java.lang.String DISPLAY_NAME = "data4"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final int TYPE_HOME = 1; // 0x1 field public static final int TYPE_MOBILE = 4; // 0x4 field public static final int TYPE_OTHER = 3; // 0x3 @@ -20075,8 +23934,12 @@ } public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { + method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); method public static int getTypeResource(java.lang.Integer); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String START_DATE = "data1"; field public static final int TYPE_ANNIVERSARY = 1; // 0x1 field public static final int TYPE_BIRTHDAY = 3; // 0x3 @@ -20085,12 +23948,18 @@ public static final class ContactsContract.CommonDataKinds.GroupMembership implements android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group_membership"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String GROUP_ROW_ID = "data1"; field public static final java.lang.String GROUP_SOURCE_ID = "group_sourceid"; } public static final class ContactsContract.CommonDataKinds.Identity implements android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String IDENTITY = "data1"; field public static final java.lang.String NAMESPACE = "data2"; } @@ -20102,6 +23971,9 @@ method public static final int getTypeLabelResource(int); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; field public static final java.lang.String CUSTOM_PROTOCOL = "data6"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String PROTOCOL = "data5"; field public static final int PROTOCOL_AIM = 0; // 0x0 field public static final int PROTOCOL_CUSTOM = -1; // 0xffffffff @@ -20120,6 +23992,9 @@ public static final class ContactsContract.CommonDataKinds.Nickname implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String NAME = "data1"; field public static final int TYPE_DEFAULT = 1; // 0x1 field public static final int TYPE_INITIALS = 5; // 0x5 @@ -20131,6 +24006,9 @@ public static final class ContactsContract.CommonDataKinds.Note implements android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String NOTE = "data1"; } @@ -20140,6 +24018,9 @@ field public static final java.lang.String COMPANY = "data1"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; field public static final java.lang.String DEPARTMENT = "data5"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String JOB_DESCRIPTION = "data6"; field public static final java.lang.String OFFICE_LOCATION = "data9"; field public static final java.lang.String PHONETIC_NAME = "data8"; @@ -20156,6 +24037,9 @@ field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2"; field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String NORMALIZED_NUMBER = "data4"; field public static final java.lang.String NUMBER = "data1"; field public static final java.lang.String SEARCH_DISPLAY_NAME_KEY = "search_display_name"; @@ -20184,6 +24068,9 @@ public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String PHOTO = "data15"; field public static final java.lang.String PHOTO_FILE_ID = "data14"; } @@ -20192,6 +24079,9 @@ method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); method public static final int getTypeLabelResource(int); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String NAME = "data1"; field public static final int TYPE_ASSISTANT = 1; // 0x1 field public static final int TYPE_BROTHER = 2; // 0x2 @@ -20213,6 +24103,9 @@ method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); method public static final int getTypeLabelResource(int); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String SIP_ADDRESS = "data1"; field public static final int TYPE_HOME = 1; // 0x1 field public static final int TYPE_OTHER = 3; // 0x3 @@ -20222,7 +24115,11 @@ public static final class ContactsContract.CommonDataKinds.StructuredName implements android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name"; field public static final java.lang.String DISPLAY_NAME = "data1"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String FAMILY_NAME = "data3"; + field public static final java.lang.String FULL_NAME_STYLE = "data10"; field public static final java.lang.String GIVEN_NAME = "data2"; field public static final java.lang.String MIDDLE_NAME = "data5"; field public static final java.lang.String PHONETIC_FAMILY_NAME = "data9"; @@ -20240,6 +24137,9 @@ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2"; field public static final android.net.Uri CONTENT_URI; field public static final java.lang.String COUNTRY = "data10"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String FORMATTED_ADDRESS = "data1"; field public static final java.lang.String NEIGHBORHOOD = "data6"; field public static final java.lang.String POBOX = "data5"; @@ -20253,6 +24153,9 @@ public static final class ContactsContract.CommonDataKinds.Website implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final int TYPE_BLOG = 2; // 0x2 field public static final int TYPE_FTP = 6; // 0x6 field public static final int TYPE_HOME = 4; // 0x4 @@ -20276,6 +24179,7 @@ protected static abstract interface ContactsContract.ContactOptionsColumns { field public static final java.lang.String CUSTOM_RINGTONE = "custom_ringtone"; field public static final java.lang.String LAST_TIME_CONTACTED = "last_time_contacted"; + field public static final java.lang.String PINNED = "pinned"; field public static final java.lang.String SEND_TO_VOICEMAIL = "send_to_voicemail"; field public static final java.lang.String STARRED = "starred"; field public static final java.lang.String TIMES_CONTACTED = "times_contacted"; @@ -20294,20 +24198,26 @@ public static class ContactsContract.Contacts implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns { method public static android.net.Uri getLookupUri(android.content.ContentResolver, android.net.Uri); method public static android.net.Uri getLookupUri(long, java.lang.String); + method public static boolean isEnterpriseContactId(long); method public static android.net.Uri lookupContact(android.content.ContentResolver, android.net.Uri); method public static deprecated void markAsContacted(android.content.ContentResolver, long); method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean); method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri); field public static final android.net.Uri CONTENT_FILTER_URI; + field public static final android.net.Uri CONTENT_FREQUENT_URI; field public static final android.net.Uri CONTENT_GROUP_URI; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact"; field public static final android.net.Uri CONTENT_LOOKUP_URI; + field public static final android.net.Uri CONTENT_MULTI_VCARD_URI; field public static final android.net.Uri CONTENT_STREQUENT_FILTER_URI; field public static final android.net.Uri CONTENT_STREQUENT_URI; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact"; field public static final android.net.Uri CONTENT_URI; field public static final java.lang.String CONTENT_VCARD_TYPE = "text/x-vcard"; field public static final android.net.Uri CONTENT_VCARD_URI; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; } public static final class ContactsContract.Contacts.AggregationSuggestions implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns { @@ -20318,7 +24228,7 @@ field public static final java.lang.String CONTENT_DIRECTORY = "data"; } - public static final class ContactsContract.Contacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.BaseSyncColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns android.provider.ContactsContract.SyncColumns { + public static final class ContactsContract.Contacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.BaseSyncColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.DataUsageStatColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns android.provider.ContactsContract.SyncColumns { field public static final java.lang.String CONTENT_DIRECTORY = "entities"; field public static final java.lang.String DATA_ID = "data_id"; field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id"; @@ -20331,17 +24241,19 @@ field public static final java.lang.String PHOTO_FILE_ID = "data14"; } - public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns { - field public static final java.lang.String CONTENT_DIRECTORY = "stream_items"; + public static final deprecated class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns { + field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items"; } protected static abstract interface ContactsContract.ContactsColumns { field public static final java.lang.String CONTACT_LAST_UPDATED_TIMESTAMP = "contact_last_updated_timestamp"; field public static final java.lang.String DISPLAY_NAME = "display_name"; field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number"; + field public static final java.lang.String IN_DEFAULT_DIRECTORY = "in_default_directory"; field public static final java.lang.String IN_VISIBLE_GROUP = "in_visible_group"; field public static final java.lang.String IS_USER_PROFILE = "is_user_profile"; field public static final java.lang.String LOOKUP_KEY = "lookup"; + field public static final java.lang.String NAME_RAW_CONTACT_ID = "name_raw_contact_id"; field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id"; field public static final java.lang.String PHOTO_ID = "photo_id"; field public static final java.lang.String PHOTO_THUMBNAIL_URI = "photo_thumb_uri"; @@ -20352,6 +24264,9 @@ method public static android.net.Uri getContactLookupUri(android.content.ContentResolver, android.net.Uri); field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/data"; field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; + field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES"; field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only"; } @@ -20377,6 +24292,7 @@ field public static final java.lang.String IS_SUPER_PRIMARY = "is_super_primary"; field public static final java.lang.String MIMETYPE = "mimetype"; field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id"; + field public static final java.lang.String RES_PACKAGE = "res_package"; field public static final java.lang.String SYNC1 = "data_sync1"; field public static final java.lang.String SYNC2 = "data_sync2"; field public static final java.lang.String SYNC3 = "data_sync3"; @@ -20480,11 +24396,13 @@ field public static final java.lang.String GROUP_IS_READ_ONLY = "group_is_read_only"; field public static final java.lang.String GROUP_VISIBLE = "group_visible"; field public static final java.lang.String NOTES = "notes"; + field public static final java.lang.String RES_PACKAGE = "res_package"; field public static final java.lang.String SHOULD_SYNC = "should_sync"; field public static final java.lang.String SUMMARY_COUNT = "summ_count"; field public static final java.lang.String SUMMARY_WITH_PHONES = "summ_phones"; field public static final java.lang.String SYSTEM_ID = "system_id"; field public static final java.lang.String TITLE = "title"; + field public static final java.lang.String TITLE_RES = "title_res"; } public static final class ContactsContract.Intents { @@ -20534,6 +24452,8 @@ public static final class ContactsContract.PhoneLookup implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.PhoneLookupColumns { field public static final android.net.Uri CONTENT_FILTER_URI; + field public static final android.net.Uri ENTERPRISE_CONTENT_FILTER_URI; + field public static final java.lang.String QUERY_PARAMETER_SIP_ADDRESS = "sip"; } protected static abstract interface ContactsContract.PhoneLookupColumns { @@ -20550,6 +24470,14 @@ field public static final int UNDEFINED = 0; // 0x0 } + public static final class ContactsContract.PinnedPositions { + ctor public ContactsContract.PinnedPositions(); + method public static void pin(android.content.ContentResolver, long, int); + method public static void undemote(android.content.ContentResolver, long); + field public static final int DEMOTED = -1; // 0xffffffff + field public static final int UNPINNED = 0; // 0x0 + } + public static final deprecated class ContactsContract.Presence extends android.provider.ContactsContract.StatusUpdates { ctor public ContactsContract.Presence(); } @@ -20582,6 +24510,8 @@ ctor public ContactsContract.QuickContact(); method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]); method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]); + field public static final java.lang.String ACTION_QUICK_CONTACT = "android.provider.action.QUICK_CONTACT"; + field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES"; field public static final int MODE_LARGE = 3; // 0x3 field public static final int MODE_MEDIUM = 2; // 0x2 field public static final int MODE_SMALL = 1; // 0x1 @@ -20612,11 +24542,12 @@ field public static final java.lang.String DATA_ID = "data_id"; } - public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { - field public static final java.lang.String CONTENT_DIRECTORY = "stream_items"; + public static final deprecated class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { + field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items"; } protected static abstract interface ContactsContract.RawContactsColumns { + field public static final java.lang.String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set"; field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode"; field public static final java.lang.String CONTACT_ID = "contact_id"; field public static final java.lang.String DATA_SET = "data_set"; @@ -20632,6 +24563,12 @@ field public static final android.net.Uri PROFILE_CONTENT_URI; } + public static class ContactsContract.SearchSnippets { + ctor public ContactsContract.SearchSnippets(); + field public static final java.lang.String DEFERRED_SNIPPETING_KEY = "deferred_snippeting"; + field public static final java.lang.String SNIPPET = "snippet"; + } + public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns { field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/setting"; @@ -20679,54 +24616,54 @@ field public static final android.net.Uri PROFILE_CONTENT_URI; } - public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { - field public static final java.lang.String PHOTO = "photo"; + public static final deprecated class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { + field public static final deprecated java.lang.String PHOTO = "photo"; } - protected static abstract interface ContactsContract.StreamItemPhotosColumns { - field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id"; - field public static final java.lang.String PHOTO_URI = "photo_uri"; - field public static final java.lang.String SORT_INDEX = "sort_index"; - field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id"; - field public static final java.lang.String SYNC1 = "stream_item_photo_sync1"; - field public static final java.lang.String SYNC2 = "stream_item_photo_sync2"; - field public static final java.lang.String SYNC3 = "stream_item_photo_sync3"; - field public static final java.lang.String SYNC4 = "stream_item_photo_sync4"; + protected static abstract deprecated interface ContactsContract.StreamItemPhotosColumns { + field public static final deprecated java.lang.String PHOTO_FILE_ID = "photo_file_id"; + field public static final deprecated java.lang.String PHOTO_URI = "photo_uri"; + field public static final deprecated java.lang.String SORT_INDEX = "sort_index"; + field public static final deprecated java.lang.String STREAM_ITEM_ID = "stream_item_id"; + field public static final deprecated java.lang.String SYNC1 = "stream_item_photo_sync1"; + field public static final deprecated java.lang.String SYNC2 = "stream_item_photo_sync2"; + field public static final deprecated java.lang.String SYNC3 = "stream_item_photo_sync3"; + field public static final deprecated java.lang.String SYNC4 = "stream_item_photo_sync4"; } - public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { - field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item"; - field public static final android.net.Uri CONTENT_LIMIT_URI; - field public static final android.net.Uri CONTENT_PHOTO_URI; - field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item"; - field public static final android.net.Uri CONTENT_URI; - field public static final java.lang.String MAX_ITEMS = "max_items"; + public static final deprecated class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { + field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item"; + field public static final deprecated android.net.Uri CONTENT_LIMIT_URI; + field public static final deprecated android.net.Uri CONTENT_PHOTO_URI; + field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item"; + field public static final deprecated android.net.Uri CONTENT_URI; + field public static final deprecated java.lang.String MAX_ITEMS = "max_items"; } - public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { - field public static final java.lang.String CONTENT_DIRECTORY = "photo"; - field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo"; - field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo"; + public static final deprecated class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { + field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo"; + field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo"; + field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo"; } - protected static abstract interface ContactsContract.StreamItemsColumns { - field public static final java.lang.String ACCOUNT_NAME = "account_name"; - field public static final java.lang.String ACCOUNT_TYPE = "account_type"; - field public static final java.lang.String COMMENTS = "comments"; - field public static final java.lang.String CONTACT_ID = "contact_id"; - field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup"; - field public static final java.lang.String DATA_SET = "data_set"; - field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id"; - field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id"; - field public static final java.lang.String RES_ICON = "icon"; - field public static final java.lang.String RES_LABEL = "label"; - field public static final java.lang.String RES_PACKAGE = "res_package"; - field public static final java.lang.String SYNC1 = "stream_item_sync1"; - field public static final java.lang.String SYNC2 = "stream_item_sync2"; - field public static final java.lang.String SYNC3 = "stream_item_sync3"; - field public static final java.lang.String SYNC4 = "stream_item_sync4"; - field public static final java.lang.String TEXT = "text"; - field public static final java.lang.String TIMESTAMP = "timestamp"; + protected static abstract deprecated interface ContactsContract.StreamItemsColumns { + field public static final deprecated java.lang.String ACCOUNT_NAME = "account_name"; + field public static final deprecated java.lang.String ACCOUNT_TYPE = "account_type"; + field public static final deprecated java.lang.String COMMENTS = "comments"; + field public static final deprecated java.lang.String CONTACT_ID = "contact_id"; + field public static final deprecated java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup"; + field public static final deprecated java.lang.String DATA_SET = "data_set"; + field public static final deprecated java.lang.String RAW_CONTACT_ID = "raw_contact_id"; + field public static final deprecated java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id"; + field public static final deprecated java.lang.String RES_ICON = "icon"; + field public static final deprecated java.lang.String RES_LABEL = "label"; + field public static final deprecated java.lang.String RES_PACKAGE = "res_package"; + field public static final deprecated java.lang.String SYNC1 = "stream_item_sync1"; + field public static final deprecated java.lang.String SYNC2 = "stream_item_sync2"; + field public static final deprecated java.lang.String SYNC3 = "stream_item_sync3"; + field public static final deprecated java.lang.String SYNC4 = "stream_item_sync4"; + field public static final deprecated java.lang.String TEXT = "text"; + field public static final deprecated java.lang.String TIMESTAMP = "timestamp"; } protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns { @@ -20748,17 +24685,23 @@ public final class DocumentsContract { method public static android.net.Uri buildChildDocumentsUri(java.lang.String, java.lang.String); + method public static android.net.Uri buildChildDocumentsUriUsingTree(android.net.Uri, java.lang.String); method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String); + method public static android.net.Uri buildDocumentUriUsingTree(android.net.Uri, java.lang.String); method public static android.net.Uri buildRecentDocumentsUri(java.lang.String, java.lang.String); method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String); method public static android.net.Uri buildRootsUri(java.lang.String); method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String); + method public static android.net.Uri buildTreeDocumentUri(java.lang.String, java.lang.String); + method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String); method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri); method public static java.lang.String getDocumentId(android.net.Uri); method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal); method public static java.lang.String getRootId(android.net.Uri); method public static java.lang.String getSearchDocumentsQuery(android.net.Uri); + method public static java.lang.String getTreeDocumentId(android.net.Uri); method public static boolean isDocumentUri(android.content.Context, android.net.Uri); + method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String); field public static final java.lang.String EXTRA_ERROR = "error"; field public static final java.lang.String EXTRA_INFO = "info"; field public static final java.lang.String EXTRA_LOADING = "loading"; @@ -20778,6 +24721,7 @@ field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20 field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8 field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4 + field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40 field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1 field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2 field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory"; @@ -20794,6 +24738,7 @@ field public static final java.lang.String COLUMN_TITLE = "title"; field public static final int FLAG_LOCAL_ONLY = 2; // 0x2 field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1 + field public static final int FLAG_SUPPORTS_IS_CHILD = 16; // 0x10 field public static final int FLAG_SUPPORTS_RECENTS = 4; // 0x4 field public static final int FLAG_SUPPORTS_SEARCH = 8; // 0x8 } @@ -20806,6 +24751,9 @@ method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException; method public final java.lang.String getType(android.net.Uri); method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues); + method public boolean isChildDocument(java.lang.String, java.lang.String); + method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; + method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException; method public abstract android.os.ParcelFileDescriptor openDocument(java.lang.String, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException; method public android.content.res.AssetFileDescriptor openDocumentThumbnail(java.lang.String, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException; method public final android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; @@ -20818,6 +24766,8 @@ method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException; method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException; method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException; + method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException; + method public final void revokeDocumentPermission(java.lang.String); method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); } @@ -20851,6 +24801,9 @@ field public static final java.lang.String EXTRA_MEDIA_ALBUM = "android.intent.extra.album"; field public static final java.lang.String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist"; field public static final java.lang.String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus"; + field public static final java.lang.String EXTRA_MEDIA_GENRE = "android.intent.extra.genre"; + field public static final java.lang.String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist"; + field public static final java.lang.String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel"; field public static final java.lang.String EXTRA_MEDIA_TITLE = "android.intent.extra.title"; field public static final java.lang.String EXTRA_OUTPUT = "output"; field public static final java.lang.String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation"; @@ -20969,6 +24922,7 @@ method public static android.net.Uri getContentUriForPath(java.lang.String); field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/audio"; field public static final java.lang.String DEFAULT_SORT_ORDER = "title_key"; + field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/audio"; field public static final android.net.Uri EXTERNAL_CONTENT_URI; field public static final java.lang.String EXTRA_MAX_BYTES = "android.provider.MediaStore.extra.MAX_BYTES"; field public static final android.net.Uri INTERNAL_CONTENT_URI; @@ -21004,6 +24958,10 @@ field public static final java.lang.String NAME = "name"; } + public static final class MediaStore.Audio.Radio { + field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/radio"; + } + public static final class MediaStore.Files { ctor public MediaStore.Files(); method public static android.net.Uri getContentUri(java.lang.String); @@ -21173,11 +25131,13 @@ field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS"; field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS"; field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS"; + field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS"; field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS"; field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS"; field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS"; field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS"; field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS"; + field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS"; field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS"; field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS"; field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS"; @@ -21196,9 +25156,12 @@ field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; + field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO"; field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS"; field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS"; + field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS"; field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS"; + field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS"; field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS"; field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS"; field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS"; @@ -21236,7 +25199,7 @@ field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned"; field public static final java.lang.String HTTP_PROXY = "http_proxy"; - field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; + field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; field public static final java.lang.String MODE_RINGER = "mode_ringer"; field public static final java.lang.String NETWORK_PREFERENCE = "network_preference"; field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth"; @@ -21288,6 +25251,7 @@ method public static boolean putLong(android.content.ContentResolver, java.lang.String, long); method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String); method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean); + field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled"; field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled"; field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password"; field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled"; @@ -21305,7 +25269,7 @@ field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods"; field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy"; field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility"; - field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; + field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; field public static final java.lang.String LOCATION_MODE = "location_mode"; field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2 field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3 @@ -21322,6 +25286,7 @@ field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url"; field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype"; field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname"; + field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints"; field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version"; field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled"; field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country"; @@ -21414,7 +25379,7 @@ field public static final java.lang.String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected"; field public static final java.lang.String MUTE_STREAMS_AFFECTED = "mute_streams_affected"; field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference"; - field public static final java.lang.String NEXT_ALARM_FORMATTED = "next_alarm_formatted"; + field public static final deprecated java.lang.String NEXT_ALARM_FORMATTED = "next_alarm_formatted"; field public static final java.lang.String NOTIFICATION_SOUND = "notification_sound"; field public static final deprecated java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled"; field public static final deprecated java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update"; @@ -21520,6 +25485,7 @@ field public static final java.lang.String CONTENT_CLASS = "ct_cls"; field public static final java.lang.String CONTENT_LOCATION = "ct_l"; field public static final java.lang.String CONTENT_TYPE = "ct_t"; + field public static final java.lang.String CREATOR = "creator"; field public static final java.lang.String DATE = "date"; field public static final java.lang.String DATE_SENT = "date_sent"; field public static final java.lang.String DELIVERY_REPORT = "d_rpt"; @@ -21529,6 +25495,7 @@ field public static final java.lang.String MESSAGE_BOX = "msg_box"; field public static final int MESSAGE_BOX_ALL = 0; // 0x0 field public static final int MESSAGE_BOX_DRAFTS = 3; // 0x3 + field public static final int MESSAGE_BOX_FAILED = 5; // 0x5 field public static final int MESSAGE_BOX_INBOX = 1; // 0x1 field public static final int MESSAGE_BOX_OUTBOX = 4; // 0x4 field public static final int MESSAGE_BOX_SENT = 2; // 0x2 @@ -21738,6 +25705,7 @@ public static abstract interface Telephony.TextBasedSmsColumns { field public static final java.lang.String ADDRESS = "address"; field public static final java.lang.String BODY = "body"; + field public static final java.lang.String CREATOR = "creator"; field public static final java.lang.String DATE = "date"; field public static final java.lang.String DATE_SENT = "date_sent"; field public static final java.lang.String ERROR_CODE = "error_code"; @@ -21773,6 +25741,7 @@ } public static abstract interface Telephony.ThreadsColumns implements android.provider.BaseColumns { + field public static final java.lang.String ARCHIVED = "archived"; field public static final java.lang.String DATE = "date"; field public static final java.lang.String ERROR = "error"; field public static final java.lang.String HAS_ATTACHMENT = "has_attachment"; @@ -21850,6 +25819,7 @@ field public static final java.lang.String NUMBER = "number"; field public static final java.lang.String SOURCE_DATA = "source_data"; field public static final java.lang.String SOURCE_PACKAGE = "source_package"; + field public static final java.lang.String TRANSCRIPTION = "transcription"; } } @@ -21857,15 +25827,18 @@ package android.renderscript { public class Allocation extends android.renderscript.BaseObj { + method public void copy1DRangeFrom(int, int, java.lang.Object); method public void copy1DRangeFrom(int, int, int[]); method public void copy1DRangeFrom(int, int, short[]); method public void copy1DRangeFrom(int, int, byte[]); method public void copy1DRangeFrom(int, int, float[]); method public void copy1DRangeFrom(int, int, android.renderscript.Allocation, int); + method public void copy1DRangeFromUnchecked(int, int, java.lang.Object); method public void copy1DRangeFromUnchecked(int, int, int[]); method public void copy1DRangeFromUnchecked(int, int, short[]); method public void copy1DRangeFromUnchecked(int, int, byte[]); method public void copy1DRangeFromUnchecked(int, int, float[]); + method public void copy2DRangeFrom(int, int, int, int, java.lang.Object); method public void copy2DRangeFrom(int, int, int, int, byte[]); method public void copy2DRangeFrom(int, int, int, int, short[]); method public void copy2DRangeFrom(int, int, int, int, int[]); @@ -21873,17 +25846,20 @@ method public void copy2DRangeFrom(int, int, int, int, android.renderscript.Allocation, int, int); method public void copy2DRangeFrom(int, int, android.graphics.Bitmap); method public void copyFrom(android.renderscript.BaseObj[]); + method public void copyFrom(java.lang.Object); method public void copyFrom(int[]); method public void copyFrom(short[]); method public void copyFrom(byte[]); method public void copyFrom(float[]); method public void copyFrom(android.graphics.Bitmap); method public void copyFrom(android.renderscript.Allocation); + method public void copyFromUnchecked(java.lang.Object); method public void copyFromUnchecked(int[]); method public void copyFromUnchecked(short[]); method public void copyFromUnchecked(byte[]); method public void copyFromUnchecked(float[]); method public void copyTo(android.graphics.Bitmap); + method public void copyTo(java.lang.Object); method public void copyTo(byte[]); method public void copyTo(short[]); method public void copyTo(int[]); @@ -22376,6 +26352,7 @@ method public void contextDump(); method public static android.renderscript.RenderScript create(android.content.Context); method public static android.renderscript.RenderScript create(android.content.Context, android.renderscript.RenderScript.ContextType); + method public static android.renderscript.RenderScript create(android.content.Context, android.renderscript.RenderScript.ContextType, int); method public void destroy(); method public void finish(); method public final android.content.Context getApplicationContext(); @@ -22385,6 +26362,9 @@ method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler); method public void setMessageHandler(android.renderscript.RenderScript.RSMessageHandler); method public void setPriority(android.renderscript.RenderScript.Priority); + field public static final int CREATE_FLAG_LOW_LATENCY = 2; // 0x2 + field public static final int CREATE_FLAG_LOW_POWER = 4; // 0x4 + field public static final int CREATE_FLAG_NONE = 0; // 0x0 } public static final class RenderScript.ContextType extends java.lang.Enum { @@ -22517,7 +26497,9 @@ public class ScriptC extends android.renderscript.Script { ctor protected ScriptC(int, android.renderscript.RenderScript); + ctor protected ScriptC(long, android.renderscript.RenderScript); ctor protected ScriptC(android.renderscript.RenderScript, android.content.res.Resources, int); + ctor protected ScriptC(android.renderscript.RenderScript, java.lang.String, byte[], byte[]); } public final class ScriptGroup extends android.renderscript.BaseObj { @@ -22540,6 +26522,7 @@ public final class ScriptIntrinsic3DLUT extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsic3DLUT create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.KernelID getKernelID(); method public void setLUT(android.renderscript.Allocation); } @@ -22547,20 +26530,35 @@ public class ScriptIntrinsicBlend extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsicBlend create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEachAdd(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachAdd(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachClear(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachClear(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachDst(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachDst(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachDstAtop(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachDstAtop(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachDstIn(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachDstIn(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachDstOut(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachDstOut(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachDstOver(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachDstOver(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachMultiply(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachMultiply(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachSrc(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachSrc(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachSrcAtop(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachSrcAtop(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachSrcIn(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachSrcIn(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachSrcOut(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachSrcOut(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachSrcOver(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachSrcOver(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachSubtract(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachSubtract(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEachXor(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEachXor(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.KernelID getKernelIDAdd(); method public android.renderscript.Script.KernelID getKernelIDClear(); method public android.renderscript.Script.KernelID getKernelIDDst(); @@ -22581,6 +26579,7 @@ public final class ScriptIntrinsicBlur extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsicBlur create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEach(android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.FieldID getFieldID_Input(); method public android.renderscript.Script.KernelID getKernelID(); method public void setInput(android.renderscript.Allocation); @@ -22591,6 +26590,7 @@ method public static deprecated android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript, android.renderscript.Element); method public static android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript); method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.KernelID getKernelID(); method public void setAdd(android.renderscript.Float4); method public void setAdd(float, float, float, float); @@ -22604,6 +26604,7 @@ public final class ScriptIntrinsicConvolve3x3 extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsicConvolve3x3 create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEach(android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.FieldID getFieldID_Input(); method public android.renderscript.Script.KernelID getKernelID(); method public void setCoefficients(float[]); @@ -22613,6 +26614,7 @@ public final class ScriptIntrinsicConvolve5x5 extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsicConvolve5x5 create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEach(android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.FieldID getFieldID_Input(); method public android.renderscript.Script.KernelID getKernelID(); method public void setCoefficients(float[]); @@ -22622,7 +26624,9 @@ public final class ScriptIntrinsicHistogram extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsicHistogram create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEach(android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public void forEach_Dot(android.renderscript.Allocation); + method public void forEach_Dot(android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.FieldID getFieldID_Input(); method public android.renderscript.Script.KernelID getKernelID_Separate(); method public void setDotCoefficients(float, float, float, float); @@ -22632,6 +26636,7 @@ public final class ScriptIntrinsicLUT extends android.renderscript.ScriptIntrinsic { method public static android.renderscript.ScriptIntrinsicLUT create(android.renderscript.RenderScript, android.renderscript.Element); method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation); + method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.Script.LaunchOptions); method public android.renderscript.Script.KernelID getKernelID(); method public void setAlpha(int, int); method public void setBlue(int, int); @@ -22681,6 +26686,9 @@ } public class Type extends android.renderscript.BaseObj { + method public static android.renderscript.Type createX(android.renderscript.RenderScript, android.renderscript.Element, int); + method public static android.renderscript.Type createXY(android.renderscript.RenderScript, android.renderscript.Element, int, int); + method public static android.renderscript.Type createXYZ(android.renderscript.RenderScript, android.renderscript.Element, int, int, int); method public int getCount(); method public android.renderscript.Element getElement(); method public int getX(); @@ -22857,6 +26865,7 @@ method public void onPanelClosed(int, android.view.Menu); method public boolean onPreparePanel(int, android.view.View, android.view.Menu); method public boolean onSearchRequested(); + method public void onWakeUp(); method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams); method public void onWindowFocusChanged(boolean); method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback); @@ -22866,37 +26875,101 @@ method public void setFullscreen(boolean); method public void setInteractive(boolean); method public void setScreenBright(boolean); + method public final void wakeUp(); field public static final java.lang.String DREAM_META_DATA = "android.service.dream"; field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.DreamService"; } } +package android.service.media { + + public abstract class MediaBrowserService extends android.app.Service { + ctor public MediaBrowserService(); + method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); + method public android.media.session.MediaSession.Token getSessionToken(); + method public void notifyChildrenChanged(java.lang.String); + method public android.os.IBinder onBind(android.content.Intent); + method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle); + method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>); + method public void setSessionToken(android.media.session.MediaSession.Token); + field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; + } + + public static final class MediaBrowserService.BrowserRoot { + ctor public MediaBrowserService.BrowserRoot(java.lang.String, android.os.Bundle); + method public android.os.Bundle getExtras(); + method public java.lang.String getRootId(); + } + + public class MediaBrowserService.Result { + method public void detach(); + method public void sendResult(T); + } + +} + package android.service.notification { public abstract class NotificationListenerService extends android.app.Service { ctor public NotificationListenerService(); method public final void cancelAllNotifications(); - method public final void cancelNotification(java.lang.String, java.lang.String, int); + method public final deprecated void cancelNotification(java.lang.String, java.lang.String, int); + method public final void cancelNotification(java.lang.String); + method public final void cancelNotifications(java.lang.String[]); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); + method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]); + method public final int getCurrentInterruptionFilter(); + method public final int getCurrentListenerHints(); + method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking(); method public android.os.IBinder onBind(android.content.Intent); - method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification); - method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification); + method public void onInterruptionFilterChanged(int); + method public void onListenerConnected(); + method public void onListenerHintsChanged(int); + method public void onNotificationPosted(android.service.notification.StatusBarNotification); + method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap); + method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap); + method public void onNotificationRemoved(android.service.notification.StatusBarNotification); + method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap); + method public final void requestInterruptionFilter(int); + method public final void requestListenerHints(int); + field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1 + field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1 + field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3 + field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2 field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService"; } + public static class NotificationListenerService.Ranking { + ctor public NotificationListenerService.Ranking(); + method public java.lang.String getKey(); + method public int getRank(); + method public boolean isAmbient(); + method public boolean matchesInterruptionFilter(); + } + + public static class NotificationListenerService.RankingMap implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.String[] getOrderedKeys(); + method public boolean getRanking(java.lang.String, android.service.notification.NotificationListenerService.Ranking); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class StatusBarNotification implements android.os.Parcelable { ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long); ctor public StatusBarNotification(android.os.Parcel); method public android.service.notification.StatusBarNotification clone(); method public int describeContents(); + method public java.lang.String getGroupKey(); method public int getId(); method public java.lang.String getKey(); method public android.app.Notification getNotification(); method public java.lang.String getPackageName(); method public long getPostTime(); method public java.lang.String getTag(); - method public int getUserId(); + method public android.os.UserHandle getUser(); + method public deprecated int getUserId(); method public boolean isClearable(); method public boolean isOngoing(); method public void writeToParcel(android.os.Parcel, int); @@ -22905,6 +26978,16 @@ } +package android.service.restrictions { + + public abstract class RestrictionsReceiver extends android.content.BroadcastReceiver { + ctor public RestrictionsReceiver(); + method public void onReceive(android.content.Context, android.content.Intent); + method public abstract void onRequestPermission(android.content.Context, java.lang.String, java.lang.String, java.lang.String, android.os.PersistableBundle); + } + +} + package android.service.textservice { public abstract class SpellCheckerService extends android.app.Service { @@ -22928,6 +27011,73 @@ } +package android.service.voice { + + public class AlwaysOnHotwordDetector { + method public android.content.Intent createEnrollIntent(); + method public android.content.Intent createReEnrollIntent(); + method public android.content.Intent createUnEnrollIntent(); + method public int getSupportedRecognitionModes(); + method public boolean startRecognition(int); + method public boolean stopRecognition(); + field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2 + field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1 + field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2 + field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1 + field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe + field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2 + field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1 + field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff + } + + public static abstract class AlwaysOnHotwordDetector.Callback { + ctor public AlwaysOnHotwordDetector.Callback(); + method public abstract void onAvailabilityChanged(int); + method public abstract void onDetected(android.service.voice.AlwaysOnHotwordDetector.EventPayload); + method public abstract void onError(); + method public abstract void onRecognitionPaused(); + method public abstract void onRecognitionResumed(); + } + + public static class AlwaysOnHotwordDetector.EventPayload { + method public android.media.AudioFormat getCaptureAudioFormat(); + method public byte[] getTriggerAudio(); + } + + public class VoiceInteractionService extends android.app.Service { + ctor public VoiceInteractionService(); + method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback); + method public static boolean isActiveService(android.content.Context, android.content.ComponentName); + method public android.os.IBinder onBind(android.content.Intent); + method public void onReady(); + method public void onShutdown(); + method public void startSession(android.os.Bundle); + field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService"; + field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction"; + } + + public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback { + ctor public VoiceInteractionSession(android.content.Context); + ctor public VoiceInteractionSession(android.content.Context, android.os.Handler); + method public void finish(); + method public void onCloseSystemDialogs(); + method public void onCreate(android.os.Bundle); + method public void onDestroy(); + method public boolean onKeyDown(int, android.view.KeyEvent); + method public boolean onKeyLongPress(int, android.view.KeyEvent); + method public boolean onKeyMultiple(int, int, android.view.KeyEvent); + method public boolean onKeyUp(int, android.view.KeyEvent); + method public void setContentView(android.view.View); + } + + public abstract class VoiceInteractionSessionService extends android.app.Service { + ctor public VoiceInteractionSessionService(); + method public android.os.IBinder onBind(android.content.Intent); + method public abstract android.service.voice.VoiceInteractionSession onNewSession(android.os.Bundle); + } + +} + package android.service.wallpaper { public abstract class WallpaperService extends android.app.Service { @@ -22946,6 +27096,7 @@ method public android.view.SurfaceHolder getSurfaceHolder(); method public boolean isPreview(); method public boolean isVisible(); + method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); @@ -23073,52 +27224,78 @@ method public abstract int audioAvailable(byte[], int, int); method public abstract int done(); method public abstract void error(); + method public abstract void error(int); method public abstract int getMaxBufferSize(); + method public abstract boolean hasFinished(); + method public abstract boolean hasStarted(); method public abstract int start(int, int, int); } public final class SynthesisRequest { ctor public SynthesisRequest(java.lang.String, android.os.Bundle); + ctor public SynthesisRequest(java.lang.CharSequence, android.os.Bundle); method public int getCallerUid(); + method public java.lang.CharSequence getCharSequenceText(); method public java.lang.String getCountry(); method public java.lang.String getLanguage(); method public android.os.Bundle getParams(); method public int getPitch(); method public int getSpeechRate(); - method public java.lang.String getText(); + method public deprecated java.lang.String getText(); method public java.lang.String getVariant(); + method public java.lang.String getVoiceName(); } public class TextToSpeech { ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener); ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String); method public int addEarcon(java.lang.String, java.lang.String, int); - method public int addEarcon(java.lang.String, java.lang.String); + method public deprecated int addEarcon(java.lang.String, java.lang.String); + method public int addEarcon(java.lang.String, java.io.File); method public int addSpeech(java.lang.String, java.lang.String, int); + method public int addSpeech(java.lang.CharSequence, java.lang.String, int); method public int addSpeech(java.lang.String, java.lang.String); - method public boolean areDefaultsEnforced(); + method public int addSpeech(java.lang.CharSequence, java.io.File); + method public deprecated boolean areDefaultsEnforced(); + method public java.util.Set<java.util.Locale> getAvailableLanguages(); method public java.lang.String getDefaultEngine(); - method public java.util.Locale getDefaultLanguage(); + method public deprecated java.util.Locale getDefaultLanguage(); + method public android.speech.tts.Voice getDefaultVoice(); method public java.util.List<android.speech.tts.TextToSpeech.EngineInfo> getEngines(); - method public java.util.Set<java.lang.String> getFeatures(java.util.Locale); - method public java.util.Locale getLanguage(); + method public deprecated java.util.Set<java.lang.String> getFeatures(java.util.Locale); + method public deprecated java.util.Locale getLanguage(); method public static int getMaxSpeechInputLength(); + method public android.speech.tts.Voice getVoice(); + method public java.util.Set<android.speech.tts.Voice> getVoices(); method public int isLanguageAvailable(java.util.Locale); method public boolean isSpeaking(); - method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); - method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>); + method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String); + method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); + method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>); + method public int playSilentUtterance(long, int, java.lang.String); + method public int setAudioAttributes(android.media.AudioAttributes); method public deprecated int setEngineByPackageName(java.lang.String); method public int setLanguage(java.util.Locale); method public deprecated int setOnUtteranceCompletedListener(android.speech.tts.TextToSpeech.OnUtteranceCompletedListener); method public int setOnUtteranceProgressListener(android.speech.tts.UtteranceProgressListener); method public int setPitch(float); method public int setSpeechRate(float); + method public int setVoice(android.speech.tts.Voice); method public void shutdown(); - method public int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); + method public int speak(java.lang.CharSequence, int, android.os.Bundle, java.lang.String); + method public deprecated int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); method public int stop(); - method public int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String); + method public int synthesizeToFile(java.lang.CharSequence, android.os.Bundle, java.io.File, java.lang.String); + method public deprecated int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String); field public static final java.lang.String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED"; field public static final int ERROR = -1; // 0xffffffff + field public static final int ERROR_INVALID_REQUEST = -8; // 0xfffffff8 + field public static final int ERROR_NETWORK = -6; // 0xfffffffa + field public static final int ERROR_NETWORK_TIMEOUT = -7; // 0xfffffff9 + field public static final int ERROR_NOT_INSTALLED_YET = -9; // 0xfffffff7 + field public static final int ERROR_OUTPUT = -5; // 0xfffffffb + field public static final int ERROR_SERVICE = -4; // 0xfffffffc + field public static final int ERROR_SYNTHESIS = -3; // 0xfffffffd field public static final int LANG_AVAILABLE = 0; // 0x0 field public static final int LANG_COUNTRY_AVAILABLE = 1; // 0x1 field public static final int LANG_COUNTRY_VAR_AVAILABLE = 2; // 0x2 @@ -23126,6 +27303,7 @@ field public static final int LANG_NOT_SUPPORTED = -2; // 0xfffffffe field public static final int QUEUE_ADD = 1; // 0x1 field public static final int QUEUE_FLUSH = 0; // 0x0 + field public static final int STOPPED = -2; // 0xfffffffe field public static final int SUCCESS = 0; // 0x0 } @@ -23150,9 +27328,13 @@ field public static final deprecated java.lang.String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo"; field public static final deprecated java.lang.String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; field public static final java.lang.String INTENT_ACTION_TTS_SERVICE = "android.intent.action.TTS_SERVICE"; - field public static final java.lang.String KEY_FEATURE_EMBEDDED_SYNTHESIS = "embeddedTts"; - field public static final java.lang.String KEY_FEATURE_NETWORK_SYNTHESIS = "networkTts"; + field public static final deprecated java.lang.String KEY_FEATURE_EMBEDDED_SYNTHESIS = "embeddedTts"; + field public static final java.lang.String KEY_FEATURE_NETWORK_RETRIES_COUNT = "networkRetriesCount"; + field public static final deprecated java.lang.String KEY_FEATURE_NETWORK_SYNTHESIS = "networkTts"; + field public static final java.lang.String KEY_FEATURE_NETWORK_TIMEOUT_MS = "networkTimeoutMs"; + field public static final java.lang.String KEY_FEATURE_NOT_INSTALLED = "notInstalled"; field public static final java.lang.String KEY_PARAM_PAN = "pan"; + field public static final java.lang.String KEY_PARAM_SESSION_ID = "sessionId"; field public static final java.lang.String KEY_PARAM_STREAM = "streamType"; field public static final java.lang.String KEY_PARAM_UTTERANCE_ID = "utteranceId"; field public static final java.lang.String KEY_PARAM_VOLUME = "volume"; @@ -23177,10 +27359,14 @@ public abstract class TextToSpeechService extends android.app.Service { ctor public TextToSpeechService(); method public android.os.IBinder onBind(android.content.Intent); + method public java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String); method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String); method protected abstract java.lang.String[] onGetLanguage(); + method public java.util.List<android.speech.tts.Voice> onGetVoices(); method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String); + method public int onIsValidVoiceName(java.lang.String); method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String); + method public int onLoadVoice(java.lang.String); method protected abstract void onStop(); method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback); } @@ -23188,10 +27374,690 @@ public abstract class UtteranceProgressListener { ctor public UtteranceProgressListener(); method public abstract void onDone(java.lang.String); - method public abstract void onError(java.lang.String); + method public abstract deprecated void onError(java.lang.String); + method public void onError(java.lang.String, int); method public abstract void onStart(java.lang.String); } + public class Voice implements android.os.Parcelable { + ctor public Voice(java.lang.String, java.util.Locale, int, int, boolean, java.util.Set<java.lang.String>); + method public int describeContents(); + method public java.util.Set<java.lang.String> getFeatures(); + method public int getLatency(); + method public java.util.Locale getLocale(); + method public java.lang.String getName(); + method public int getQuality(); + method public boolean isNetworkConnectionRequired(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int LATENCY_HIGH = 400; // 0x190 + field public static final int LATENCY_LOW = 200; // 0xc8 + field public static final int LATENCY_NORMAL = 300; // 0x12c + field public static final int LATENCY_VERY_HIGH = 500; // 0x1f4 + field public static final int LATENCY_VERY_LOW = 100; // 0x64 + field public static final int QUALITY_HIGH = 400; // 0x190 + field public static final int QUALITY_LOW = 200; // 0xc8 + field public static final int QUALITY_NORMAL = 300; // 0x12c + field public static final int QUALITY_VERY_HIGH = 500; // 0x1f4 + field public static final int QUALITY_VERY_LOW = 100; // 0x64 + } + +} + +package android.system { + + public final class ErrnoException extends java.lang.Exception { + ctor public ErrnoException(java.lang.String, int); + ctor public ErrnoException(java.lang.String, int, java.lang.Throwable); + field public final int errno; + } + + public final class Os { + method public static java.io.FileDescriptor accept(java.io.FileDescriptor, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException; + method public static boolean access(java.lang.String, int) throws android.system.ErrnoException; + method public static void bind(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; + method public static void chmod(java.lang.String, int) throws android.system.ErrnoException; + method public static void chown(java.lang.String, int, int) throws android.system.ErrnoException; + method public static void close(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static void connect(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; + method public static java.io.FileDescriptor dup(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static java.io.FileDescriptor dup2(java.io.FileDescriptor, int) throws android.system.ErrnoException; + method public static java.lang.String[] environ(); + method public static void execv(java.lang.String, java.lang.String[]) throws android.system.ErrnoException; + method public static void execve(java.lang.String, java.lang.String[], java.lang.String[]) throws android.system.ErrnoException; + method public static void fchmod(java.io.FileDescriptor, int) throws android.system.ErrnoException; + method public static void fchown(java.io.FileDescriptor, int, int) throws android.system.ErrnoException; + method public static void fdatasync(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static android.system.StructStat fstat(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static android.system.StructStatVfs fstatvfs(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static void fsync(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static void ftruncate(java.io.FileDescriptor, long) throws android.system.ErrnoException; + method public static java.lang.String gai_strerror(int); + method public static int getegid(); + method public static java.lang.String getenv(java.lang.String); + method public static int geteuid(); + method public static int getgid(); + method public static java.net.SocketAddress getpeername(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static int getpid(); + method public static int getppid(); + method public static java.net.SocketAddress getsockname(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static int gettid(); + method public static int getuid(); + method public static java.lang.String if_indextoname(int); + method public static java.net.InetAddress inet_pton(int, java.lang.String); + method public static boolean isatty(java.io.FileDescriptor); + method public static void kill(int, int) throws android.system.ErrnoException; + method public static void lchown(java.lang.String, int, int) throws android.system.ErrnoException; + method public static void link(java.lang.String, java.lang.String) throws android.system.ErrnoException; + method public static void listen(java.io.FileDescriptor, int) throws android.system.ErrnoException; + method public static long lseek(java.io.FileDescriptor, long, int) throws android.system.ErrnoException; + method public static android.system.StructStat lstat(java.lang.String) throws android.system.ErrnoException; + method public static void mincore(long, long, byte[]) throws android.system.ErrnoException; + method public static void mkdir(java.lang.String, int) throws android.system.ErrnoException; + method public static void mkfifo(java.lang.String, int) throws android.system.ErrnoException; + method public static void mlock(long, long) throws android.system.ErrnoException; + method public static long mmap(long, long, int, int, java.io.FileDescriptor, long) throws android.system.ErrnoException; + method public static void msync(long, long, int) throws android.system.ErrnoException; + method public static void munlock(long, long) throws android.system.ErrnoException; + method public static void munmap(long, long) throws android.system.ErrnoException; + method public static java.io.FileDescriptor open(java.lang.String, int, int) throws android.system.ErrnoException; + method public static java.io.FileDescriptor[] pipe() throws android.system.ErrnoException; + method public static int poll(android.system.StructPollfd[], int) throws android.system.ErrnoException; + method public static void posix_fallocate(java.io.FileDescriptor, long, long) throws android.system.ErrnoException; + method public static int prctl(int, long, long, long, long) throws android.system.ErrnoException; + method public static int pread(java.io.FileDescriptor, java.nio.ByteBuffer, long) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int pread(java.io.FileDescriptor, byte[], int, int, long) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int pwrite(java.io.FileDescriptor, java.nio.ByteBuffer, long) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int pwrite(java.io.FileDescriptor, byte[], int, int, long) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int read(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int read(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static java.lang.String readlink(java.lang.String) throws android.system.ErrnoException; + method public static int readv(java.io.FileDescriptor, java.lang.Object[], int[], int[]) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int recvfrom(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException; + method public static int recvfrom(java.io.FileDescriptor, byte[], int, int, int, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException; + method public static void remove(java.lang.String) throws android.system.ErrnoException; + method public static void rename(java.lang.String, java.lang.String) throws android.system.ErrnoException; + method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.util.MutableLong, long) throws android.system.ErrnoException; + method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; + method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; + method public static void setegid(int) throws android.system.ErrnoException; + method public static void setenv(java.lang.String, java.lang.String, boolean) throws android.system.ErrnoException; + method public static void seteuid(int) throws android.system.ErrnoException; + method public static void setgid(int) throws android.system.ErrnoException; + method public static int setsid() throws android.system.ErrnoException; + method public static void setuid(int) throws android.system.ErrnoException; + method public static void shutdown(java.io.FileDescriptor, int) throws android.system.ErrnoException; + method public static java.io.FileDescriptor socket(int, int, int) throws android.system.ErrnoException; + method public static void socketpair(int, int, int, java.io.FileDescriptor, java.io.FileDescriptor) throws android.system.ErrnoException; + method public static android.system.StructStat stat(java.lang.String) throws android.system.ErrnoException; + method public static android.system.StructStatVfs statvfs(java.lang.String) throws android.system.ErrnoException; + method public static java.lang.String strerror(int); + method public static java.lang.String strsignal(int); + method public static void symlink(java.lang.String, java.lang.String) throws android.system.ErrnoException; + method public static long sysconf(int); + method public static void tcdrain(java.io.FileDescriptor) throws android.system.ErrnoException; + method public static void tcsendbreak(java.io.FileDescriptor, int) throws android.system.ErrnoException; + method public static int umask(int); + method public static android.system.StructUtsname uname(); + method public static void unsetenv(java.lang.String) throws android.system.ErrnoException; + method public static int waitpid(int, android.util.MutableInt, int) throws android.system.ErrnoException; + method public static int write(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int write(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException; + method public static int writev(java.io.FileDescriptor, java.lang.Object[], int[], int[]) throws android.system.ErrnoException, java.io.InterruptedIOException; + } + + public final class OsConstants { + method public static boolean S_ISBLK(int); + method public static boolean S_ISCHR(int); + method public static boolean S_ISDIR(int); + method public static boolean S_ISFIFO(int); + method public static boolean S_ISLNK(int); + method public static boolean S_ISREG(int); + method public static boolean S_ISSOCK(int); + method public static boolean WCOREDUMP(int); + method public static int WEXITSTATUS(int); + method public static boolean WIFEXITED(int); + method public static boolean WIFSIGNALED(int); + method public static boolean WIFSTOPPED(int); + method public static int WSTOPSIG(int); + method public static int WTERMSIG(int); + method public static java.lang.String errnoName(int); + method public static java.lang.String gaiName(int); + field public static final int AF_INET; + field public static final int AF_INET6; + field public static final int AF_UNIX; + field public static final int AF_UNSPEC; + field public static final int AI_ADDRCONFIG; + field public static final int AI_ALL; + field public static final int AI_CANONNAME; + field public static final int AI_NUMERICHOST; + field public static final int AI_NUMERICSERV; + field public static final int AI_PASSIVE; + field public static final int AI_V4MAPPED; + field public static final int CAP_AUDIT_CONTROL; + field public static final int CAP_AUDIT_WRITE; + field public static final int CAP_BLOCK_SUSPEND; + field public static final int CAP_CHOWN; + field public static final int CAP_DAC_OVERRIDE; + field public static final int CAP_DAC_READ_SEARCH; + field public static final int CAP_FOWNER; + field public static final int CAP_FSETID; + field public static final int CAP_IPC_LOCK; + field public static final int CAP_IPC_OWNER; + field public static final int CAP_KILL; + field public static final int CAP_LAST_CAP; + field public static final int CAP_LEASE; + field public static final int CAP_LINUX_IMMUTABLE; + field public static final int CAP_MAC_ADMIN; + field public static final int CAP_MAC_OVERRIDE; + field public static final int CAP_MKNOD; + field public static final int CAP_NET_ADMIN; + field public static final int CAP_NET_BIND_SERVICE; + field public static final int CAP_NET_BROADCAST; + field public static final int CAP_NET_RAW; + field public static final int CAP_SETFCAP; + field public static final int CAP_SETGID; + field public static final int CAP_SETPCAP; + field public static final int CAP_SETUID; + field public static final int CAP_SYSLOG; + field public static final int CAP_SYS_ADMIN; + field public static final int CAP_SYS_BOOT; + field public static final int CAP_SYS_CHROOT; + field public static final int CAP_SYS_MODULE; + field public static final int CAP_SYS_NICE; + field public static final int CAP_SYS_PACCT; + field public static final int CAP_SYS_PTRACE; + field public static final int CAP_SYS_RAWIO; + field public static final int CAP_SYS_RESOURCE; + field public static final int CAP_SYS_TIME; + field public static final int CAP_SYS_TTY_CONFIG; + field public static final int CAP_WAKE_ALARM; + field public static final int E2BIG; + field public static final int EACCES; + field public static final int EADDRINUSE; + field public static final int EADDRNOTAVAIL; + field public static final int EAFNOSUPPORT; + field public static final int EAGAIN; + field public static final int EAI_AGAIN; + field public static final int EAI_BADFLAGS; + field public static final int EAI_FAIL; + field public static final int EAI_FAMILY; + field public static final int EAI_MEMORY; + field public static final int EAI_NODATA; + field public static final int EAI_NONAME; + field public static final int EAI_OVERFLOW; + field public static final int EAI_SERVICE; + field public static final int EAI_SOCKTYPE; + field public static final int EAI_SYSTEM; + field public static final int EALREADY; + field public static final int EBADF; + field public static final int EBADMSG; + field public static final int EBUSY; + field public static final int ECANCELED; + field public static final int ECHILD; + field public static final int ECONNABORTED; + field public static final int ECONNREFUSED; + field public static final int ECONNRESET; + field public static final int EDEADLK; + field public static final int EDESTADDRREQ; + field public static final int EDOM; + field public static final int EDQUOT; + field public static final int EEXIST; + field public static final int EFAULT; + field public static final int EFBIG; + field public static final int EHOSTUNREACH; + field public static final int EIDRM; + field public static final int EILSEQ; + field public static final int EINPROGRESS; + field public static final int EINTR; + field public static final int EINVAL; + field public static final int EIO; + field public static final int EISCONN; + field public static final int EISDIR; + field public static final int ELOOP; + field public static final int EMFILE; + field public static final int EMLINK; + field public static final int EMSGSIZE; + field public static final int EMULTIHOP; + field public static final int ENAMETOOLONG; + field public static final int ENETDOWN; + field public static final int ENETRESET; + field public static final int ENETUNREACH; + field public static final int ENFILE; + field public static final int ENOBUFS; + field public static final int ENODATA; + field public static final int ENODEV; + field public static final int ENOENT; + field public static final int ENOEXEC; + field public static final int ENOLCK; + field public static final int ENOLINK; + field public static final int ENOMEM; + field public static final int ENOMSG; + field public static final int ENOPROTOOPT; + field public static final int ENOSPC; + field public static final int ENOSR; + field public static final int ENOSTR; + field public static final int ENOSYS; + field public static final int ENOTCONN; + field public static final int ENOTDIR; + field public static final int ENOTEMPTY; + field public static final int ENOTSOCK; + field public static final int ENOTSUP; + field public static final int ENOTTY; + field public static final int ENXIO; + field public static final int EOPNOTSUPP; + field public static final int EOVERFLOW; + field public static final int EPERM; + field public static final int EPIPE; + field public static final int EPROTO; + field public static final int EPROTONOSUPPORT; + field public static final int EPROTOTYPE; + field public static final int ERANGE; + field public static final int EROFS; + field public static final int ESPIPE; + field public static final int ESRCH; + field public static final int ESTALE; + field public static final int ETIME; + field public static final int ETIMEDOUT; + field public static final int ETXTBSY; + field public static final int EXDEV; + field public static final int EXIT_FAILURE; + field public static final int EXIT_SUCCESS; + field public static final int FD_CLOEXEC; + field public static final int FIONREAD; + field public static final int F_DUPFD; + field public static final int F_GETFD; + field public static final int F_GETFL; + field public static final int F_GETLK; + field public static final int F_GETLK64; + field public static final int F_GETOWN; + field public static final int F_OK; + field public static final int F_RDLCK; + field public static final int F_SETFD; + field public static final int F_SETFL; + field public static final int F_SETLK; + field public static final int F_SETLK64; + field public static final int F_SETLKW; + field public static final int F_SETLKW64; + field public static final int F_SETOWN; + field public static final int F_UNLCK; + field public static final int F_WRLCK; + field public static final int IFA_F_DADFAILED; + field public static final int IFA_F_DEPRECATED; + field public static final int IFA_F_HOMEADDRESS; + field public static final int IFA_F_NODAD; + field public static final int IFA_F_OPTIMISTIC; + field public static final int IFA_F_PERMANENT; + field public static final int IFA_F_SECONDARY; + field public static final int IFA_F_TEMPORARY; + field public static final int IFA_F_TENTATIVE; + field public static final int IFF_ALLMULTI; + field public static final int IFF_AUTOMEDIA; + field public static final int IFF_BROADCAST; + field public static final int IFF_DEBUG; + field public static final int IFF_DYNAMIC; + field public static final int IFF_LOOPBACK; + field public static final int IFF_MASTER; + field public static final int IFF_MULTICAST; + field public static final int IFF_NOARP; + field public static final int IFF_NOTRAILERS; + field public static final int IFF_POINTOPOINT; + field public static final int IFF_PORTSEL; + field public static final int IFF_PROMISC; + field public static final int IFF_RUNNING; + field public static final int IFF_SLAVE; + field public static final int IFF_UP; + field public static final int IPPROTO_ICMP; + field public static final int IPPROTO_ICMPV6; + field public static final int IPPROTO_IP; + field public static final int IPPROTO_IPV6; + field public static final int IPPROTO_RAW; + field public static final int IPPROTO_TCP; + field public static final int IPPROTO_UDP; + field public static final int IPV6_CHECKSUM; + field public static final int IPV6_MULTICAST_HOPS; + field public static final int IPV6_MULTICAST_IF; + field public static final int IPV6_MULTICAST_LOOP; + field public static final int IPV6_RECVDSTOPTS; + field public static final int IPV6_RECVHOPLIMIT; + field public static final int IPV6_RECVHOPOPTS; + field public static final int IPV6_RECVPKTINFO; + field public static final int IPV6_RECVRTHDR; + field public static final int IPV6_RECVTCLASS; + field public static final int IPV6_TCLASS; + field public static final int IPV6_UNICAST_HOPS; + field public static final int IPV6_V6ONLY; + field public static final int IP_MULTICAST_IF; + field public static final int IP_MULTICAST_LOOP; + field public static final int IP_MULTICAST_TTL; + field public static final int IP_TOS; + field public static final int IP_TTL; + field public static final int MAP_FIXED; + field public static final int MAP_PRIVATE; + field public static final int MAP_SHARED; + field public static final int MCAST_BLOCK_SOURCE; + field public static final int MCAST_JOIN_GROUP; + field public static final int MCAST_JOIN_SOURCE_GROUP; + field public static final int MCAST_LEAVE_GROUP; + field public static final int MCAST_LEAVE_SOURCE_GROUP; + field public static final int MCAST_UNBLOCK_SOURCE; + field public static final int MCL_CURRENT; + field public static final int MCL_FUTURE; + field public static final int MSG_CTRUNC; + field public static final int MSG_DONTROUTE; + field public static final int MSG_EOR; + field public static final int MSG_OOB; + field public static final int MSG_PEEK; + field public static final int MSG_TRUNC; + field public static final int MSG_WAITALL; + field public static final int MS_ASYNC; + field public static final int MS_INVALIDATE; + field public static final int MS_SYNC; + field public static final int NI_DGRAM; + field public static final int NI_NAMEREQD; + field public static final int NI_NOFQDN; + field public static final int NI_NUMERICHOST; + field public static final int NI_NUMERICSERV; + field public static final int O_ACCMODE; + field public static final int O_APPEND; + field public static final int O_CREAT; + field public static final int O_EXCL; + field public static final int O_NOCTTY; + field public static final int O_NOFOLLOW; + field public static final int O_NONBLOCK; + field public static final int O_RDONLY; + field public static final int O_RDWR; + field public static final int O_SYNC; + field public static final int O_TRUNC; + field public static final int O_WRONLY; + field public static final int POLLERR; + field public static final int POLLHUP; + field public static final int POLLIN; + field public static final int POLLNVAL; + field public static final int POLLOUT; + field public static final int POLLPRI; + field public static final int POLLRDBAND; + field public static final int POLLRDNORM; + field public static final int POLLWRBAND; + field public static final int POLLWRNORM; + field public static final int PROT_EXEC; + field public static final int PROT_NONE; + field public static final int PROT_READ; + field public static final int PROT_WRITE; + field public static final int PR_GET_DUMPABLE; + field public static final int PR_SET_DUMPABLE; + field public static final int PR_SET_NO_NEW_PRIVS; + field public static final int RT_SCOPE_HOST; + field public static final int RT_SCOPE_LINK; + field public static final int RT_SCOPE_NOWHERE; + field public static final int RT_SCOPE_SITE; + field public static final int RT_SCOPE_UNIVERSE; + field public static final int R_OK; + field public static final int SEEK_CUR; + field public static final int SEEK_END; + field public static final int SEEK_SET; + field public static final int SHUT_RD; + field public static final int SHUT_RDWR; + field public static final int SHUT_WR; + field public static final int SIGABRT; + field public static final int SIGALRM; + field public static final int SIGBUS; + field public static final int SIGCHLD; + field public static final int SIGCONT; + field public static final int SIGFPE; + field public static final int SIGHUP; + field public static final int SIGILL; + field public static final int SIGINT; + field public static final int SIGIO; + field public static final int SIGKILL; + field public static final int SIGPIPE; + field public static final int SIGPROF; + field public static final int SIGPWR; + field public static final int SIGQUIT; + field public static final int SIGRTMAX; + field public static final int SIGRTMIN; + field public static final int SIGSEGV; + field public static final int SIGSTKFLT; + field public static final int SIGSTOP; + field public static final int SIGSYS; + field public static final int SIGTERM; + field public static final int SIGTRAP; + field public static final int SIGTSTP; + field public static final int SIGTTIN; + field public static final int SIGTTOU; + field public static final int SIGURG; + field public static final int SIGUSR1; + field public static final int SIGUSR2; + field public static final int SIGVTALRM; + field public static final int SIGWINCH; + field public static final int SIGXCPU; + field public static final int SIGXFSZ; + field public static final int SIOCGIFADDR; + field public static final int SIOCGIFBRDADDR; + field public static final int SIOCGIFDSTADDR; + field public static final int SIOCGIFNETMASK; + field public static final int SOCK_DGRAM; + field public static final int SOCK_RAW; + field public static final int SOCK_SEQPACKET; + field public static final int SOCK_STREAM; + field public static final int SOL_SOCKET; + field public static final int SO_BINDTODEVICE; + field public static final int SO_BROADCAST; + field public static final int SO_DEBUG; + field public static final int SO_DONTROUTE; + field public static final int SO_ERROR; + field public static final int SO_KEEPALIVE; + field public static final int SO_LINGER; + field public static final int SO_OOBINLINE; + field public static final int SO_PASSCRED; + field public static final int SO_PEERCRED; + field public static final int SO_RCVBUF; + field public static final int SO_RCVLOWAT; + field public static final int SO_RCVTIMEO; + field public static final int SO_REUSEADDR; + field public static final int SO_SNDBUF; + field public static final int SO_SNDLOWAT; + field public static final int SO_SNDTIMEO; + field public static final int SO_TYPE; + field public static final int STDERR_FILENO; + field public static final int STDIN_FILENO; + field public static final int STDOUT_FILENO; + field public static final int S_IFBLK; + field public static final int S_IFCHR; + field public static final int S_IFDIR; + field public static final int S_IFIFO; + field public static final int S_IFLNK; + field public static final int S_IFMT; + field public static final int S_IFREG; + field public static final int S_IFSOCK; + field public static final int S_IRGRP; + field public static final int S_IROTH; + field public static final int S_IRUSR; + field public static final int S_IRWXG; + field public static final int S_IRWXO; + field public static final int S_IRWXU; + field public static final int S_ISGID; + field public static final int S_ISUID; + field public static final int S_ISVTX; + field public static final int S_IWGRP; + field public static final int S_IWOTH; + field public static final int S_IWUSR; + field public static final int S_IXGRP; + field public static final int S_IXOTH; + field public static final int S_IXUSR; + field public static final int TCP_NODELAY; + field public static final int WCONTINUED; + field public static final int WEXITED; + field public static final int WNOHANG; + field public static final int WNOWAIT; + field public static final int WSTOPPED; + field public static final int WUNTRACED; + field public static final int W_OK; + field public static final int X_OK; + field public static final int _SC_2_CHAR_TERM; + field public static final int _SC_2_C_BIND; + field public static final int _SC_2_C_DEV; + field public static final int _SC_2_C_VERSION; + field public static final int _SC_2_FORT_DEV; + field public static final int _SC_2_FORT_RUN; + field public static final int _SC_2_LOCALEDEF; + field public static final int _SC_2_SW_DEV; + field public static final int _SC_2_UPE; + field public static final int _SC_2_VERSION; + field public static final int _SC_AIO_LISTIO_MAX; + field public static final int _SC_AIO_MAX; + field public static final int _SC_AIO_PRIO_DELTA_MAX; + field public static final int _SC_ARG_MAX; + field public static final int _SC_ASYNCHRONOUS_IO; + field public static final int _SC_ATEXIT_MAX; + field public static final int _SC_AVPHYS_PAGES; + field public static final int _SC_BC_BASE_MAX; + field public static final int _SC_BC_DIM_MAX; + field public static final int _SC_BC_SCALE_MAX; + field public static final int _SC_BC_STRING_MAX; + field public static final int _SC_CHILD_MAX; + field public static final int _SC_CLK_TCK; + field public static final int _SC_COLL_WEIGHTS_MAX; + field public static final int _SC_DELAYTIMER_MAX; + field public static final int _SC_EXPR_NEST_MAX; + field public static final int _SC_FSYNC; + field public static final int _SC_GETGR_R_SIZE_MAX; + field public static final int _SC_GETPW_R_SIZE_MAX; + field public static final int _SC_IOV_MAX; + field public static final int _SC_JOB_CONTROL; + field public static final int _SC_LINE_MAX; + field public static final int _SC_LOGIN_NAME_MAX; + field public static final int _SC_MAPPED_FILES; + field public static final int _SC_MEMLOCK; + field public static final int _SC_MEMLOCK_RANGE; + field public static final int _SC_MEMORY_PROTECTION; + field public static final int _SC_MESSAGE_PASSING; + field public static final int _SC_MQ_OPEN_MAX; + field public static final int _SC_MQ_PRIO_MAX; + field public static final int _SC_NGROUPS_MAX; + field public static final int _SC_NPROCESSORS_CONF; + field public static final int _SC_NPROCESSORS_ONLN; + field public static final int _SC_OPEN_MAX; + field public static final int _SC_PAGESIZE; + field public static final int _SC_PAGE_SIZE; + field public static final int _SC_PASS_MAX; + field public static final int _SC_PHYS_PAGES; + field public static final int _SC_PRIORITIZED_IO; + field public static final int _SC_PRIORITY_SCHEDULING; + field public static final int _SC_REALTIME_SIGNALS; + field public static final int _SC_RE_DUP_MAX; + field public static final int _SC_RTSIG_MAX; + field public static final int _SC_SAVED_IDS; + field public static final int _SC_SEMAPHORES; + field public static final int _SC_SEM_NSEMS_MAX; + field public static final int _SC_SEM_VALUE_MAX; + field public static final int _SC_SHARED_MEMORY_OBJECTS; + field public static final int _SC_SIGQUEUE_MAX; + field public static final int _SC_STREAM_MAX; + field public static final int _SC_SYNCHRONIZED_IO; + field public static final int _SC_THREADS; + field public static final int _SC_THREAD_ATTR_STACKADDR; + field public static final int _SC_THREAD_ATTR_STACKSIZE; + field public static final int _SC_THREAD_DESTRUCTOR_ITERATIONS; + field public static final int _SC_THREAD_KEYS_MAX; + field public static final int _SC_THREAD_PRIORITY_SCHEDULING; + field public static final int _SC_THREAD_PRIO_INHERIT; + field public static final int _SC_THREAD_PRIO_PROTECT; + field public static final int _SC_THREAD_SAFE_FUNCTIONS; + field public static final int _SC_THREAD_STACK_MIN; + field public static final int _SC_THREAD_THREADS_MAX; + field public static final int _SC_TIMERS; + field public static final int _SC_TIMER_MAX; + field public static final int _SC_TTY_NAME_MAX; + field public static final int _SC_TZNAME_MAX; + field public static final int _SC_VERSION; + field public static final int _SC_XBS5_ILP32_OFF32; + field public static final int _SC_XBS5_ILP32_OFFBIG; + field public static final int _SC_XBS5_LP64_OFF64; + field public static final int _SC_XBS5_LPBIG_OFFBIG; + field public static final int _SC_XOPEN_CRYPT; + field public static final int _SC_XOPEN_ENH_I18N; + field public static final int _SC_XOPEN_LEGACY; + field public static final int _SC_XOPEN_REALTIME; + field public static final int _SC_XOPEN_REALTIME_THREADS; + field public static final int _SC_XOPEN_SHM; + field public static final int _SC_XOPEN_UNIX; + field public static final int _SC_XOPEN_VERSION; + field public static final int _SC_XOPEN_XCU_VERSION; + } + + public final class StructPollfd { + ctor public StructPollfd(); + field public short events; + field public java.io.FileDescriptor fd; + field public short revents; + field public java.lang.Object userData; + } + + public final class StructStat { + ctor public StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long); + field public final long st_atime; + field public final long st_blksize; + field public final long st_blocks; + field public final long st_ctime; + field public final long st_dev; + field public final int st_gid; + field public final long st_ino; + field public final int st_mode; + field public final long st_mtime; + field public final long st_nlink; + field public final long st_rdev; + field public final long st_size; + field public final int st_uid; + } + + public final class StructStatVfs { + ctor public StructStatVfs(long, long, long, long, long, long, long, long, long, long, long); + field public final long f_bavail; + field public final long f_bfree; + field public final long f_blocks; + field public final long f_bsize; + field public final long f_favail; + field public final long f_ffree; + field public final long f_files; + field public final long f_flag; + field public final long f_frsize; + field public final long f_fsid; + field public final long f_namemax; + } + + public final class StructUtsname { + ctor public StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String); + field public final java.lang.String machine; + field public final java.lang.String nodename; + field public final java.lang.String release; + field public final java.lang.String sysname; + field public final java.lang.String version; + } + +} + +package android.telecom { + + public class TelecomManager { + method public void cancelMissedCallsNotification(); + method public boolean handleMmi(java.lang.String); + method public boolean isInCall(); + method public void showInCallScreen(boolean); + field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"; + field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ',' + field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';' + field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE"; + field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE"; + field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE"; + field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; + field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final int PRESENTATION_ALLOWED = 1; // 0x1 + field public static final int PRESENTATION_PAYPHONE = 4; // 0x4 + field public static final int PRESENTATION_RESTRICTED = 2; // 0x2 + field public static final int PRESENTATION_UNKNOWN = 3; // 0x3 + } + } package android.telephony { @@ -23342,6 +28208,20 @@ field public static final android.os.Parcelable.Creator CREATOR; } + public class IccOpenLogicalChannelResponse implements android.os.Parcelable { + method public int describeContents(); + method public int getChannel(); + method public byte[] getSelectResponse(); + method public int getStatus(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int INVALID_CHANNEL = -1; // 0xffffffff + field public static final int STATUS_MISSING_RESOURCE = 2; // 0x2 + field public static final int STATUS_NO_ERROR = 1; // 0x1 + field public static final int STATUS_NO_SUCH_ELEMENT = 3; // 0x3 + field public static final int STATUS_UNKNOWN_ERROR = 4; // 0x4 + } + public class NeighboringCellInfo implements android.os.Parcelable { ctor public deprecated NeighboringCellInfo(); ctor public deprecated NeighboringCellInfo(int, int); @@ -23363,6 +28243,7 @@ public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher { ctor public PhoneNumberFormattingTextWatcher(); + ctor public PhoneNumberFormattingTextWatcher(java.lang.String); method public synchronized void afterTextChanged(android.text.Editable); method public void beforeTextChanged(java.lang.CharSequence, int, int, int); method public void onTextChanged(java.lang.CharSequence, int, int, int); @@ -23377,11 +28258,14 @@ method public static java.lang.String convertKeypadLettersToDigits(java.lang.String); method public static java.lang.String extractNetworkPortion(java.lang.String); method public static java.lang.String extractPostDialPortion(java.lang.String); - method public static void formatJapaneseNumber(android.text.Editable); - method public static void formatNanpNumber(android.text.Editable); - method public static java.lang.String formatNumber(java.lang.String); - method public static void formatNumber(android.text.Editable, int); - method public static int getFormatTypeForLocale(java.util.Locale); + method public static deprecated void formatJapaneseNumber(android.text.Editable); + method public static deprecated void formatNanpNumber(android.text.Editable); + method public static deprecated java.lang.String formatNumber(java.lang.String); + method public static deprecated void formatNumber(android.text.Editable, int); + method public static java.lang.String formatNumber(java.lang.String, java.lang.String); + method public static java.lang.String formatNumber(java.lang.String, java.lang.String, java.lang.String); + method public static java.lang.String formatNumberToE164(java.lang.String, java.lang.String); + method public static deprecated int getFormatTypeForLocale(java.util.Locale); method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context); method public static java.lang.String getStrippedReversed(java.lang.String); method public static final boolean is12Key(char); @@ -23389,13 +28273,17 @@ method public static boolean isEmergencyNumber(java.lang.String); method public static boolean isGlobalPhoneNumber(java.lang.String); method public static boolean isISODigit(char); + method public static boolean isLocalEmergencyNumber(android.content.Context, java.lang.String); method public static final boolean isNonSeparator(char); method public static final boolean isReallyDialable(char); method public static final boolean isStartsPostDial(char); + method public static boolean isVoiceMailNumber(java.lang.String); method public static boolean isWellFormedSmsAddress(java.lang.String); method public static byte[] networkPortionToCalledPartyBCD(java.lang.String); method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String); + method public static java.lang.String normalizeNumber(java.lang.String); method public static byte[] numberToCalledPartyBCD(java.lang.String); + method public static java.lang.String replaceUnicodeDigits(java.lang.String); method public static java.lang.String stringFromStringAndTOA(java.lang.String, int); method public static java.lang.String stripSeparators(java.lang.String); method public static java.lang.String toCallerIDMinMatch(java.lang.String); @@ -23477,10 +28365,50 @@ public final class SmsManager { method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String); + method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent); + method public android.os.Bundle getCarrierConfigValues(); method public static android.telephony.SmsManager getDefault(); method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); + method public void sendMultimediaMessage(android.content.Context, android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent); method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>); method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent); + field public static final java.lang.String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; + field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; + field public static final java.lang.String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars"; + field public static final java.lang.String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars"; + field public static final java.lang.String MMS_CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio"; + field public static final java.lang.String MMS_CONFIG_APPEND_TRANSACTION_ID = "enabledTransID"; + field public static final java.lang.String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber"; + field public static final java.lang.String MMS_CONFIG_GROUP_MMS_ENABLED = "enableGroupMms"; + field public static final java.lang.String MMS_CONFIG_HTTP_PARAMS = "httpParams"; + field public static final java.lang.String MMS_CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout"; + field public static final java.lang.String MMS_CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight"; + field public static final java.lang.String MMS_CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth"; + field public static final java.lang.String MMS_CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize"; + field public static final java.lang.String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE = "maxMessageTextSize"; + field public static final java.lang.String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED = "enableMMSDeliveryReports"; + field public static final java.lang.String MMS_CONFIG_MMS_ENABLED = "enabledMMS"; + field public static final java.lang.String MMS_CONFIG_MMS_READ_REPORT_ENABLED = "enableMMSReadReports"; + field public static final java.lang.String MMS_CONFIG_MULTIPART_SMS_ENABLED = "enableMultipartSMS"; + field public static final java.lang.String MMS_CONFIG_NAI_SUFFIX = "naiSuffix"; + field public static final java.lang.String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC"; + field public static final java.lang.String MMS_CONFIG_RECIPIENT_LIMIT = "recipientLimit"; + field public static final java.lang.String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = "sendMultipartSmsAsSeparateMessages"; + field public static final java.lang.String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports"; + field public static final java.lang.String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = "smsToMmsTextLengthThreshold"; + field public static final java.lang.String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold"; + field public static final java.lang.String MMS_CONFIG_SUBJECT_MAX_LENGTH = "maxSubjectLength"; + field public static final java.lang.String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = "supportMmsContentDisposition"; + field public static final java.lang.String MMS_CONFIG_UA_PROF_TAG_NAME = "uaProfTagName"; + field public static final java.lang.String MMS_CONFIG_UA_PROF_URL = "uaProfUrl"; + field public static final java.lang.String MMS_CONFIG_USER_AGENT = "userAgent"; + field public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; // 0x7 + field public static final int MMS_ERROR_HTTP_FAILURE = 4; // 0x4 + field public static final int MMS_ERROR_INVALID_APN = 2; // 0x2 + field public static final int MMS_ERROR_IO_ERROR = 5; // 0x5 + field public static final int MMS_ERROR_RETRY = 6; // 0x6 + field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3 + field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1 field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3 @@ -23577,8 +28505,15 @@ method public java.lang.String getVoiceMailAlphaTag(); method public java.lang.String getVoiceMailNumber(); method public boolean hasIccCard(); + method public boolean iccCloseLogicalChannel(int); + method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String); + method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String); + method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String); + method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String); method public boolean isNetworkRoaming(); + method public boolean isSmsCapable(); method public void listen(android.telephony.PhoneStateListener, int); + method public java.lang.String sendEnvelopeWithStatus(java.lang.String); field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final int CALL_STATE_IDLE = 0; // 0x0 @@ -24097,6 +29032,7 @@ method public android.content.res.AssetManager getAssets(); method public java.io.File getCacheDir(); method public java.lang.ClassLoader getClassLoader(); + method public java.io.File getCodeCacheDir(); method public android.content.ContentResolver getContentResolver(); method public java.io.File getDatabasePath(java.lang.String); method public java.io.File getDir(java.lang.String, int); @@ -24104,9 +29040,11 @@ method public java.io.File[] getExternalCacheDirs(); method public java.io.File getExternalFilesDir(java.lang.String); method public java.io.File[] getExternalFilesDirs(java.lang.String); + method public java.io.File[] getExternalMediaDirs(); method public java.io.File getFileStreamPath(java.lang.String); method public java.io.File getFilesDir(); method public android.os.Looper getMainLooper(); + method public java.io.File getNoBackupFilesDir(); method public java.io.File getObbDir(); method public java.io.File[] getObbDirs(); method public java.lang.String getPackageCodePath(); @@ -24246,9 +29184,11 @@ method public java.lang.String getInstallerPackageName(java.lang.String); method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method public android.content.Intent getLaunchIntentForPackage(java.lang.String); + method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String); method public java.lang.String getNameForUid(int); method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; + method public android.content.pm.PackageInstaller getPackageInstaller(); method public java.lang.String[] getPackagesForUid(int); method public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int); method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; @@ -24264,6 +29204,9 @@ method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures(); method public java.lang.String[] getSystemSharedLibraryNames(); method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo); + method public android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int); + method public android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle); + method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle); method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo); method public boolean hasSystemFeature(java.lang.String); method public boolean isSafeMode(); @@ -24510,6 +29453,7 @@ public static class InputFilter.LengthFilter implements android.text.InputFilter { ctor public InputFilter.LengthFilter(int); method public java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int); + method public int getMax(); } public abstract interface InputType { @@ -24709,6 +29653,7 @@ ctor public SpannableStringBuilder(java.lang.CharSequence); ctor public SpannableStringBuilder(java.lang.CharSequence, int, int); method public android.text.SpannableStringBuilder append(java.lang.CharSequence); + method public android.text.SpannableStringBuilder append(java.lang.CharSequence, java.lang.Object, int); method public android.text.SpannableStringBuilder append(java.lang.CharSequence, int, int); method public android.text.SpannableStringBuilder append(char); method public char charAt(int); @@ -25633,6 +30578,227 @@ method public void writeToParcel(android.os.Parcel, int); } + public class TtsSpan implements android.text.ParcelableSpan { + ctor public TtsSpan(java.lang.String, android.os.PersistableBundle); + ctor public TtsSpan(android.os.Parcel); + method public int describeContents(); + method public android.os.PersistableBundle getArgs(); + method public int getSpanTypeId(); + method public java.lang.String getType(); + method public void writeToParcel(android.os.Parcel, int); + field public static final java.lang.String ANIMACY_ANIMATE = "android.animate"; + field public static final java.lang.String ANIMACY_INANIMATE = "android.inanimate"; + field public static final java.lang.String ARG_ANIMACY = "android.arg.animacy"; + field public static final java.lang.String ARG_CASE = "android.arg.case"; + field public static final java.lang.String ARG_COUNTRY_CODE = "android.arg.country_code"; + field public static final java.lang.String ARG_CURRENCY = "android.arg.money"; + field public static final java.lang.String ARG_DAY = "android.arg.day"; + field public static final java.lang.String ARG_DENOMINATOR = "android.arg.denominator"; + field public static final java.lang.String ARG_DIGITS = "android.arg.digits"; + field public static final java.lang.String ARG_DOMAIN = "android.arg.domain"; + field public static final java.lang.String ARG_EXTENSION = "android.arg.extension"; + field public static final java.lang.String ARG_FRACTIONAL_PART = "android.arg.fractional_part"; + field public static final java.lang.String ARG_FRAGMENT_ID = "android.arg.fragment_id"; + field public static final java.lang.String ARG_GENDER = "android.arg.gender"; + field public static final java.lang.String ARG_HOURS = "android.arg.hours"; + field public static final java.lang.String ARG_INTEGER_PART = "android.arg.integer_part"; + field public static final java.lang.String ARG_MINUTES = "android.arg.minutes"; + field public static final java.lang.String ARG_MONTH = "android.arg.month"; + field public static final java.lang.String ARG_MULTIPLICITY = "android.arg.multiplicity"; + field public static final java.lang.String ARG_NUMBER = "android.arg.number"; + field public static final java.lang.String ARG_NUMBER_PARTS = "android.arg.number_parts"; + field public static final java.lang.String ARG_NUMERATOR = "android.arg.numerator"; + field public static final java.lang.String ARG_PASSWORD = "android.arg.password"; + field public static final java.lang.String ARG_PATH = "android.arg.path"; + field public static final java.lang.String ARG_PORT = "android.arg.port"; + field public static final java.lang.String ARG_PROTOCOL = "android.arg.protocol"; + field public static final java.lang.String ARG_QUANTITY = "android.arg.quantity"; + field public static final java.lang.String ARG_QUERY_STRING = "android.arg.query_string"; + field public static final java.lang.String ARG_TEXT = "android.arg.text"; + field public static final java.lang.String ARG_UNIT = "android.arg.unit"; + field public static final java.lang.String ARG_USERNAME = "android.arg.username"; + field public static final java.lang.String ARG_VERBATIM = "android.arg.verbatim"; + field public static final java.lang.String ARG_WEEKDAY = "android.arg.weekday"; + field public static final java.lang.String ARG_YEAR = "android.arg.year"; + field public static final java.lang.String CASE_ABLATIVE = "android.ablative"; + field public static final java.lang.String CASE_ACCUSATIVE = "android.accusative"; + field public static final java.lang.String CASE_DATIVE = "android.dative"; + field public static final java.lang.String CASE_GENITIVE = "android.genitive"; + field public static final java.lang.String CASE_INSTRUMENTAL = "android.instrumental"; + field public static final java.lang.String CASE_LOCATIVE = "android.locative"; + field public static final java.lang.String CASE_NOMINATIVE = "android.nominative"; + field public static final java.lang.String CASE_VOCATIVE = "android.vocative"; + field public static final java.lang.String GENDER_FEMALE = "android.female"; + field public static final java.lang.String GENDER_MALE = "android.male"; + field public static final java.lang.String GENDER_NEUTRAL = "android.neutral"; + field public static final int MONTH_APRIL = 3; // 0x3 + field public static final int MONTH_AUGUST = 7; // 0x7 + field public static final int MONTH_DECEMBER = 11; // 0xb + field public static final int MONTH_FEBRUARY = 1; // 0x1 + field public static final int MONTH_JANUARY = 0; // 0x0 + field public static final int MONTH_JULY = 6; // 0x6 + field public static final int MONTH_JUNE = 5; // 0x5 + field public static final int MONTH_MARCH = 2; // 0x2 + field public static final int MONTH_MAY = 4; // 0x4 + field public static final int MONTH_NOVEMBER = 10; // 0xa + field public static final int MONTH_OCTOBER = 9; // 0x9 + field public static final int MONTH_SEPTEMBER = 8; // 0x8 + field public static final java.lang.String MULTIPLICITY_DUAL = "android.dual"; + field public static final java.lang.String MULTIPLICITY_PLURAL = "android.plural"; + field public static final java.lang.String MULTIPLICITY_SINGLE = "android.single"; + field public static final java.lang.String TYPE_CARDINAL = "android.type.cardinal"; + field public static final java.lang.String TYPE_DATE = "android.type.date"; + field public static final java.lang.String TYPE_DECIMAL = "android.type.decimal"; + field public static final java.lang.String TYPE_DIGITS = "android.type.digits"; + field public static final java.lang.String TYPE_ELECTRONIC = "android.type.electronic"; + field public static final java.lang.String TYPE_FRACTION = "android.type.fraction"; + field public static final java.lang.String TYPE_MEASURE = "android.type.measure"; + field public static final java.lang.String TYPE_MONEY = "android.type.money"; + field public static final java.lang.String TYPE_ORDINAL = "android.type.ordinal"; + field public static final java.lang.String TYPE_TELEPHONE = "android.type.telephone"; + field public static final java.lang.String TYPE_TEXT = "android.type.text"; + field public static final java.lang.String TYPE_TIME = "android.type.time"; + field public static final java.lang.String TYPE_VERBATIM = "android.type.verbatim"; + field public static final int WEEKDAY_FRIDAY = 6; // 0x6 + field public static final int WEEKDAY_MONDAY = 2; // 0x2 + field public static final int WEEKDAY_SATURDAY = 7; // 0x7 + field public static final int WEEKDAY_SUNDAY = 1; // 0x1 + field public static final int WEEKDAY_THURSDAY = 5; // 0x5 + field public static final int WEEKDAY_TUESDAY = 3; // 0x3 + field public static final int WEEKDAY_WEDNESDAY = 4; // 0x4 + } + + public static class TtsSpan.Builder { + ctor public TtsSpan.Builder(java.lang.String); + method public android.text.style.TtsSpan build(); + method public C setIntArgument(java.lang.String, int); + method public C setLongArgument(java.lang.String, long); + method public C setStringArgument(java.lang.String, java.lang.String); + } + + public static class TtsSpan.CardinalBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.CardinalBuilder(); + ctor public TtsSpan.CardinalBuilder(long); + ctor public TtsSpan.CardinalBuilder(java.lang.String); + method public android.text.style.TtsSpan.CardinalBuilder setNumber(long); + method public android.text.style.TtsSpan.CardinalBuilder setNumber(java.lang.String); + } + + public static class TtsSpan.DateBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.DateBuilder(); + ctor public TtsSpan.DateBuilder(java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Integer); + method public android.text.style.TtsSpan.DateBuilder setDay(int); + method public android.text.style.TtsSpan.DateBuilder setMonth(int); + method public android.text.style.TtsSpan.DateBuilder setWeekday(int); + method public android.text.style.TtsSpan.DateBuilder setYear(int); + } + + public static class TtsSpan.DecimalBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.DecimalBuilder(); + ctor public TtsSpan.DecimalBuilder(double, int, int); + ctor public TtsSpan.DecimalBuilder(java.lang.String, java.lang.String); + method public android.text.style.TtsSpan.DecimalBuilder setArgumentsFromDouble(double, int, int); + method public android.text.style.TtsSpan.DecimalBuilder setFractionalPart(java.lang.String); + method public android.text.style.TtsSpan.DecimalBuilder setIntegerPart(long); + method public android.text.style.TtsSpan.DecimalBuilder setIntegerPart(java.lang.String); + } + + public static class TtsSpan.DigitsBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.DigitsBuilder(); + ctor public TtsSpan.DigitsBuilder(java.lang.String); + method public android.text.style.TtsSpan.DigitsBuilder setDigits(java.lang.String); + } + + public static class TtsSpan.ElectronicBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.ElectronicBuilder(); + method public android.text.style.TtsSpan.ElectronicBuilder setDomain(java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setEmailArguments(java.lang.String, java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setFragmentId(java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setPassword(java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setPath(java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setPort(int); + method public android.text.style.TtsSpan.ElectronicBuilder setProtocol(java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setQueryString(java.lang.String); + method public android.text.style.TtsSpan.ElectronicBuilder setUsername(java.lang.String); + } + + public static class TtsSpan.FractionBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.FractionBuilder(); + ctor public TtsSpan.FractionBuilder(long, long, long); + method public android.text.style.TtsSpan.FractionBuilder setDenominator(long); + method public android.text.style.TtsSpan.FractionBuilder setDenominator(java.lang.String); + method public android.text.style.TtsSpan.FractionBuilder setIntegerPart(long); + method public android.text.style.TtsSpan.FractionBuilder setIntegerPart(java.lang.String); + method public android.text.style.TtsSpan.FractionBuilder setNumerator(long); + method public android.text.style.TtsSpan.FractionBuilder setNumerator(java.lang.String); + } + + public static class TtsSpan.MeasureBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.MeasureBuilder(); + method public android.text.style.TtsSpan.MeasureBuilder setDenominator(long); + method public android.text.style.TtsSpan.MeasureBuilder setDenominator(java.lang.String); + method public android.text.style.TtsSpan.MeasureBuilder setFractionalPart(java.lang.String); + method public android.text.style.TtsSpan.MeasureBuilder setIntegerPart(long); + method public android.text.style.TtsSpan.MeasureBuilder setIntegerPart(java.lang.String); + method public android.text.style.TtsSpan.MeasureBuilder setNumber(long); + method public android.text.style.TtsSpan.MeasureBuilder setNumber(java.lang.String); + method public android.text.style.TtsSpan.MeasureBuilder setNumerator(long); + method public android.text.style.TtsSpan.MeasureBuilder setNumerator(java.lang.String); + method public android.text.style.TtsSpan.MeasureBuilder setUnit(java.lang.String); + } + + public static class TtsSpan.MoneyBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.MoneyBuilder(); + method public android.text.style.TtsSpan.MoneyBuilder setCurrency(java.lang.String); + method public android.text.style.TtsSpan.MoneyBuilder setFractionalPart(java.lang.String); + method public android.text.style.TtsSpan.MoneyBuilder setIntegerPart(long); + method public android.text.style.TtsSpan.MoneyBuilder setIntegerPart(java.lang.String); + method public android.text.style.TtsSpan.MoneyBuilder setQuantity(java.lang.String); + } + + public static class TtsSpan.OrdinalBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.OrdinalBuilder(); + ctor public TtsSpan.OrdinalBuilder(long); + ctor public TtsSpan.OrdinalBuilder(java.lang.String); + method public android.text.style.TtsSpan.OrdinalBuilder setNumber(long); + method public android.text.style.TtsSpan.OrdinalBuilder setNumber(java.lang.String); + } + + public static class TtsSpan.SemioticClassBuilder extends android.text.style.TtsSpan.Builder { + ctor public TtsSpan.SemioticClassBuilder(java.lang.String); + method public C setAnimacy(java.lang.String); + method public C setCase(java.lang.String); + method public C setGender(java.lang.String); + method public C setMultiplicity(java.lang.String); + } + + public static class TtsSpan.TelephoneBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.TelephoneBuilder(); + ctor public TtsSpan.TelephoneBuilder(java.lang.String); + method public android.text.style.TtsSpan.TelephoneBuilder setCountryCode(java.lang.String); + method public android.text.style.TtsSpan.TelephoneBuilder setExtension(java.lang.String); + method public android.text.style.TtsSpan.TelephoneBuilder setNumberParts(java.lang.String); + } + + public static class TtsSpan.TextBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.TextBuilder(); + ctor public TtsSpan.TextBuilder(java.lang.String); + method public android.text.style.TtsSpan.TextBuilder setText(java.lang.String); + } + + public static class TtsSpan.TimeBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.TimeBuilder(); + ctor public TtsSpan.TimeBuilder(int, int); + method public android.text.style.TtsSpan.TimeBuilder setHours(int); + method public android.text.style.TtsSpan.TimeBuilder setMinutes(int); + } + + public static class TtsSpan.VerbatimBuilder extends android.text.style.TtsSpan.SemioticClassBuilder { + ctor public TtsSpan.VerbatimBuilder(); + ctor public TtsSpan.VerbatimBuilder(java.lang.String); + method public android.text.style.TtsSpan.VerbatimBuilder setVerbatim(java.lang.String); + } + public class TypefaceSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan { ctor public TypefaceSpan(java.lang.String); ctor public TypefaceSpan(android.os.Parcel); @@ -25728,28 +30894,95 @@ package android.transition { + public class ArcMotion extends android.transition.PathMotion { + ctor public ArcMotion(); + ctor public ArcMotion(android.content.Context, android.util.AttributeSet); + method public float getMaximumAngle(); + method public float getMinimumHorizontalAngle(); + method public float getMinimumVerticalAngle(); + method public android.graphics.Path getPath(float, float, float, float); + method public void setMaximumAngle(float); + method public void setMinimumHorizontalAngle(float); + method public void setMinimumVerticalAngle(float); + } + public class AutoTransition extends android.transition.TransitionSet { ctor public AutoTransition(); + ctor public AutoTransition(android.content.Context, android.util.AttributeSet); } public class ChangeBounds extends android.transition.Transition { ctor public ChangeBounds(); + ctor public ChangeBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); - method public void setReparent(boolean); + method public deprecated void setReparent(boolean); method public void setResizeClip(boolean); } + public class ChangeClipBounds extends android.transition.Transition { + ctor public ChangeClipBounds(); + ctor public ChangeClipBounds(android.content.Context, android.util.AttributeSet); + method public void captureEndValues(android.transition.TransitionValues); + method public void captureStartValues(android.transition.TransitionValues); + } + + public class ChangeImageTransform extends android.transition.Transition { + ctor public ChangeImageTransform(); + ctor public ChangeImageTransform(android.content.Context, android.util.AttributeSet); + method public void captureEndValues(android.transition.TransitionValues); + method public void captureStartValues(android.transition.TransitionValues); + } + + public class ChangeTransform extends android.transition.Transition { + ctor public ChangeTransform(); + ctor public ChangeTransform(android.content.Context, android.util.AttributeSet); + method public void captureEndValues(android.transition.TransitionValues); + method public void captureStartValues(android.transition.TransitionValues); + method public boolean getReparent(); + method public boolean getReparentWithOverlay(); + method public void setReparent(boolean); + method public void setReparentWithOverlay(boolean); + } + + public class CircularPropagation extends android.transition.VisibilityPropagation { + ctor public CircularPropagation(); + method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues); + method public void setPropagationSpeed(float); + } + + public class Explode extends android.transition.Visibility { + ctor public Explode(); + ctor public Explode(android.content.Context, android.util.AttributeSet); + } + public class Fade extends android.transition.Visibility { ctor public Fade(); ctor public Fade(int); + ctor public Fade(android.content.Context, android.util.AttributeSet); field public static final int IN = 1; // 0x1 field public static final int OUT = 2; // 0x2 } + public abstract class PathMotion { + ctor public PathMotion(); + ctor public PathMotion(android.content.Context, android.util.AttributeSet); + method public abstract android.graphics.Path getPath(float, float, float, float); + } + + public class PatternPathMotion extends android.transition.PathMotion { + ctor public PatternPathMotion(); + ctor public PatternPathMotion(android.content.Context, android.util.AttributeSet); + ctor public PatternPathMotion(android.graphics.Path); + method public android.graphics.Path getPath(float, float, float, float); + method public android.graphics.Path getPatternPath(); + method public void setPatternPath(android.graphics.Path); + } + public final class Scene { ctor public Scene(android.view.ViewGroup); - ctor public Scene(android.view.ViewGroup, android.view.ViewGroup); + ctor public Scene(android.view.ViewGroup, android.view.View); + ctor public deprecated Scene(android.view.ViewGroup, android.view.ViewGroup); method public void enter(); method public void exit(); method public static android.transition.Scene getSceneForLayout(android.view.ViewGroup, int, android.content.Context); @@ -25758,11 +30991,30 @@ method public void setExitAction(java.lang.Runnable); } + public class SidePropagation extends android.transition.VisibilityPropagation { + ctor public SidePropagation(); + method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues); + method public void setPropagationSpeed(float); + method public void setSide(int); + } + + public class Slide extends android.transition.Visibility { + ctor public Slide(); + ctor public Slide(int); + ctor public Slide(android.content.Context, android.util.AttributeSet); + method public int getSlideEdge(); + method public void setSlideEdge(int); + } + public abstract class Transition implements java.lang.Cloneable { ctor public Transition(); + ctor public Transition(android.content.Context, android.util.AttributeSet); method public android.transition.Transition addListener(android.transition.Transition.TransitionListener); method public android.transition.Transition addTarget(int); + method public android.transition.Transition addTarget(java.lang.String); + method public android.transition.Transition addTarget(java.lang.Class); method public android.transition.Transition addTarget(android.view.View); + method public boolean canRemoveViews(); method public abstract void captureEndValues(android.transition.TransitionValues); method public abstract void captureStartValues(android.transition.TransitionValues); method public android.transition.Transition clone(); @@ -25771,22 +31023,44 @@ method public android.transition.Transition excludeChildren(android.view.View, boolean); method public android.transition.Transition excludeChildren(java.lang.Class, boolean); method public android.transition.Transition excludeTarget(int, boolean); + method public android.transition.Transition excludeTarget(java.lang.String, boolean); method public android.transition.Transition excludeTarget(android.view.View, boolean); method public android.transition.Transition excludeTarget(java.lang.Class, boolean); method public long getDuration(); + method public android.graphics.Rect getEpicenter(); + method public android.transition.Transition.EpicenterCallback getEpicenterCallback(); method public android.animation.TimeInterpolator getInterpolator(); method public java.lang.String getName(); + method public android.transition.PathMotion getPathMotion(); + method public android.transition.TransitionPropagation getPropagation(); method public long getStartDelay(); method public java.util.List<java.lang.Integer> getTargetIds(); + method public java.util.List<java.lang.String> getTargetNames(); + method public java.util.List<java.lang.Class> getTargetTypes(); method public java.util.List<android.view.View> getTargets(); method public java.lang.String[] getTransitionProperties(); method public android.transition.TransitionValues getTransitionValues(android.view.View, boolean); method public android.transition.Transition removeListener(android.transition.Transition.TransitionListener); method public android.transition.Transition removeTarget(int); + method public android.transition.Transition removeTarget(java.lang.String); method public android.transition.Transition removeTarget(android.view.View); + method public android.transition.Transition removeTarget(java.lang.Class); method public android.transition.Transition setDuration(long); + method public void setEpicenterCallback(android.transition.Transition.EpicenterCallback); method public android.transition.Transition setInterpolator(android.animation.TimeInterpolator); + method public void setMatchOrder(int...); + method public void setPathMotion(android.transition.PathMotion); + method public void setPropagation(android.transition.TransitionPropagation); method public android.transition.Transition setStartDelay(long); + field public static final int MATCH_ID = 3; // 0x3 + field public static final int MATCH_INSTANCE = 1; // 0x1 + field public static final int MATCH_ITEM_ID = 4; // 0x4 + field public static final int MATCH_NAME = 2; // 0x2 + } + + public static abstract class Transition.EpicenterCallback { + ctor public Transition.EpicenterCallback(); + method public abstract android.graphics.Rect onGetEpicenter(android.transition.Transition); } public static abstract interface Transition.TransitionListener { @@ -25814,12 +31088,22 @@ method public void transitionTo(android.transition.Scene); } + public abstract class TransitionPropagation { + ctor public TransitionPropagation(); + method public abstract void captureValues(android.transition.TransitionValues); + method public abstract java.lang.String[] getPropagationProperties(); + method public abstract long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues); + } + public class TransitionSet extends android.transition.Transition { ctor public TransitionSet(); + ctor public TransitionSet(android.content.Context, android.util.AttributeSet); method public android.transition.TransitionSet addTransition(android.transition.Transition); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public int getOrdering(); + method public android.transition.Transition getTransitionAt(int); + method public int getTransitionCount(); method public android.transition.TransitionSet removeTransition(android.transition.Transition); method public android.transition.TransitionSet setOrdering(int); field public static final int ORDERING_SEQUENTIAL = 1; // 0x1 @@ -25834,11 +31118,27 @@ public abstract class Visibility extends android.transition.Transition { ctor public Visibility(); + ctor public Visibility(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); + method public int getMode(); method public boolean isVisible(android.transition.TransitionValues); method public android.animation.Animator onAppear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int); + method public android.animation.Animator onAppear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues); method public android.animation.Animator onDisappear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int); + method public android.animation.Animator onDisappear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues); + method public void setMode(int); + field public static final int MODE_IN = 1; // 0x1 + field public static final int MODE_OUT = 2; // 0x2 + } + + public abstract class VisibilityPropagation extends android.transition.TransitionPropagation { + ctor public VisibilityPropagation(); + method public void captureValues(android.transition.TransitionValues); + method public java.lang.String[] getPropagationProperties(); + method public int getViewVisibility(android.transition.TransitionValues); + method public int getViewX(android.transition.TransitionValues); + method public int getViewY(android.transition.TransitionValues); } } @@ -25870,6 +31170,7 @@ method public void ensureCapacity(int); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public V get(java.lang.Object); + method public int indexOfKey(java.lang.Object); method public boolean isEmpty(); method public K keyAt(int); method public java.util.Set<K> keySet(); @@ -25968,6 +31269,7 @@ method public void setTo(android.util.DisplayMetrics); method public void setToDefaults(); field public static final int DENSITY_400 = 400; // 0x190 + field public static final int DENSITY_560 = 560; // 0x230 field public static final int DENSITY_DEFAULT = 160; // 0xa0 field public static final int DENSITY_HIGH = 240; // 0xf0 field public static final int DENSITY_LOW = 120; // 0x78 @@ -26154,6 +31456,7 @@ method public final V put(K, V); method public final synchronized int putCount(); method public final V remove(K); + method public void resize(int); method public final synchronized int size(); method protected int sizeOf(K, V); method public final synchronized java.util.Map<K, V> snapshot(); @@ -26183,6 +31486,46 @@ method public void previousMonth(); } + public final class MutableBoolean { + ctor public MutableBoolean(boolean); + field public boolean value; + } + + public final class MutableByte { + ctor public MutableByte(byte); + field public byte value; + } + + public final class MutableChar { + ctor public MutableChar(char); + field public char value; + } + + public final class MutableDouble { + ctor public MutableDouble(double); + field public double value; + } + + public final class MutableFloat { + ctor public MutableFloat(float); + field public float value; + } + + public final class MutableInt { + ctor public MutableInt(int); + field public int value; + } + + public final class MutableLong { + ctor public MutableLong(long); + field public long value; + } + + public final class MutableShort { + ctor public MutableShort(short); + field public short value; + } + public class NoSuchPropertyException extends java.lang.RuntimeException { ctor public NoSuchPropertyException(java.lang.String); } @@ -26202,9 +31545,9 @@ field public static final java.lang.String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef"; field public static final java.util.regex.Pattern IP_ADDRESS; field public static final java.util.regex.Pattern PHONE; - field public static final java.util.regex.Pattern TOP_LEVEL_DOMAIN; - field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])"; - field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))"; + field public static final deprecated java.util.regex.Pattern TOP_LEVEL_DOMAIN; + field public static final deprecated java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])"; + field public static final deprecated java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))"; field public static final java.util.regex.Pattern WEB_URL; } @@ -26232,6 +31575,55 @@ method public void set(T, V); } + public final class Range { + ctor public Range(T, T); + method public T clamp(T); + method public boolean contains(T); + method public boolean contains(android.util.Range<T>); + method public static android.util.Range<T> create(T, T); + method public android.util.Range<T> extend(android.util.Range<T>); + method public android.util.Range<T> extend(T, T); + method public android.util.Range<T> extend(T); + method public T getLower(); + method public T getUpper(); + method public android.util.Range<T> intersect(android.util.Range<T>); + method public android.util.Range<T> intersect(T, T); + } + + public final class Rational extends java.lang.Number implements java.lang.Comparable { + ctor public Rational(int, int); + method public int compareTo(android.util.Rational); + method public double doubleValue(); + method public float floatValue(); + method public int getDenominator(); + method public int getNumerator(); + method public int intValue(); + method public boolean isFinite(); + method public boolean isInfinite(); + method public boolean isNaN(); + method public boolean isZero(); + method public long longValue(); + method public static android.util.Rational parseRational(java.lang.String) throws java.lang.NumberFormatException; + field public static final android.util.Rational NEGATIVE_INFINITY; + field public static final android.util.Rational NaN; + field public static final android.util.Rational POSITIVE_INFINITY; + field public static final android.util.Rational ZERO; + } + + public final class Size { + ctor public Size(int, int); + method public int getHeight(); + method public int getWidth(); + method public static android.util.Size parseSize(java.lang.String) throws java.lang.NumberFormatException; + } + + public final class SizeF { + ctor public SizeF(float, float); + method public float getHeight(); + method public float getWidth(); + method public static android.util.SizeF parseSizeF(java.lang.String) throws java.lang.NumberFormatException; + } + public class SparseArray implements java.lang.Cloneable { ctor public SparseArray(); ctor public SparseArray(int); @@ -26513,6 +31905,7 @@ } public final class Display { + method public long getAppVsyncOffsetNanos(); method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point); method public int getDisplayId(); method public int getFlags(); @@ -26521,6 +31914,7 @@ method public java.lang.String getName(); method public deprecated int getOrientation(); method public deprecated int getPixelFormat(); + method public long getPresentationDeadlineNanos(); method public void getRealMetrics(android.util.DisplayMetrics); method public void getRealSize(android.graphics.Point); method public void getRectSize(android.graphics.Rect); @@ -26528,6 +31922,7 @@ method public int getRotation(); method public void getSize(android.graphics.Point); method public int getState(); + method public float[] getSupportedRefreshRates(); method public deprecated int getWidth(); method public boolean isValid(); field public static final int DEFAULT_DISPLAY = 0; // 0x0 @@ -26535,7 +31930,8 @@ field public static final int FLAG_PRIVATE = 4; // 0x4 field public static final int FLAG_SECURE = 2; // 0x2 field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1 - field public static final int STATE_DOZING = 3; // 0x3 + field public static final int STATE_DOZE = 3; // 0x3 + field public static final int STATE_DOZE_SUSPEND = 4; // 0x4 field public static final int STATE_OFF = 1; // 0x1 field public static final int STATE_ON = 2; // 0x2 field public static final int STATE_UNKNOWN = 0; // 0x0 @@ -26567,6 +31963,16 @@ method public static android.view.FocusFinder getInstance(); } + public abstract class FrameStats { + ctor public FrameStats(); + method public final long getEndTimeNano(); + method public final int getFrameCount(); + method public final long getFramePresentedTimeNano(int); + method public final long getRefreshPeriodNano(); + method public final long getStartTimeNano(); + field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL + } + public class GestureDetector { ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener, android.os.Handler); ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener); @@ -26648,6 +32054,7 @@ } public class HapticFeedbackConstants { + field public static final int CLOCK_TICK = 4; // 0x4 field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2 field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1 field public static final int KEYBOARD_TAP = 3; // 0x3 @@ -26681,6 +32088,7 @@ method public android.os.Vibrator getVibrator(); method public boolean[] hasKeys(int...); method public boolean isVirtual(); + method public boolean supportsSource(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int KEYBOARD_TYPE_ALPHABETIC = 2; // 0x2 @@ -26705,6 +32113,7 @@ field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4 field public static final int SOURCE_DPAD = 513; // 0x201 field public static final int SOURCE_GAMEPAD = 1025; // 0x401 + field public static final int SOURCE_HDMI = 33554433; // 0x2000001 field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010 field public static final int SOURCE_KEYBOARD = 257; // 0x101 field public static final int SOURCE_MOUSE = 8194; // 0x2002 @@ -26873,6 +32282,8 @@ field public static final deprecated int FLAG_WOKE_HERE = 1; // 0x1 field public static final int KEYCODE_0 = 7; // 0x7 field public static final int KEYCODE_1 = 8; // 0x8 + field public static final int KEYCODE_11 = 227; // 0xe3 + field public static final int KEYCODE_12 = 228; // 0xe4 field public static final int KEYCODE_2 = 9; // 0x9 field public static final int KEYCODE_3 = 10; // 0xa field public static final int KEYCODE_3D_MODE = 206; // 0xce @@ -26981,6 +32392,7 @@ field public static final int KEYCODE_GUIDE = 172; // 0xac field public static final int KEYCODE_H = 36; // 0x24 field public static final int KEYCODE_HEADSETHOOK = 79; // 0x4f + field public static final int KEYCODE_HELP = 259; // 0x103 field public static final int KEYCODE_HENKAN = 214; // 0xd6 field public static final int KEYCODE_HOME = 3; // 0x3 field public static final int KEYCODE_I = 37; // 0x25 @@ -26992,6 +32404,7 @@ field public static final int KEYCODE_KATAKANA_HIRAGANA = 215; // 0xd7 field public static final int KEYCODE_L = 40; // 0x28 field public static final int KEYCODE_LANGUAGE_SWITCH = 204; // 0xcc + field public static final int KEYCODE_LAST_CHANNEL = 229; // 0xe5 field public static final int KEYCODE_LEFT_BRACKET = 71; // 0x47 field public static final int KEYCODE_M = 41; // 0x29 field public static final int KEYCODE_MANNER_MODE = 205; // 0xcd @@ -27007,6 +32420,7 @@ field public static final int KEYCODE_MEDIA_RECORD = 130; // 0x82 field public static final int KEYCODE_MEDIA_REWIND = 89; // 0x59 field public static final int KEYCODE_MEDIA_STOP = 86; // 0x56 + field public static final int KEYCODE_MEDIA_TOP_MENU = 226; // 0xe2 field public static final int KEYCODE_MENU = 82; // 0x52 field public static final int KEYCODE_META_LEFT = 117; // 0x75 field public static final int KEYCODE_META_RIGHT = 118; // 0x76 @@ -27044,6 +32458,7 @@ field public static final int KEYCODE_P = 44; // 0x2c field public static final int KEYCODE_PAGE_DOWN = 93; // 0x5d field public static final int KEYCODE_PAGE_UP = 92; // 0x5c + field public static final int KEYCODE_PAIRING = 225; // 0xe1 field public static final int KEYCODE_PERIOD = 56; // 0x38 field public static final int KEYCODE_PICTSYMBOLS = 94; // 0x5e field public static final int KEYCODE_PLUS = 81; // 0x51 @@ -27078,11 +32493,40 @@ field public static final int KEYCODE_T = 48; // 0x30 field public static final int KEYCODE_TAB = 61; // 0x3d field public static final int KEYCODE_TV = 170; // 0xaa + field public static final int KEYCODE_TV_ANTENNA_CABLE = 242; // 0xf2 + field public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252; // 0xfc + field public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254; // 0xfe + field public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253; // 0xfd + field public static final int KEYCODE_TV_CONTENTS_MENU = 256; // 0x100 + field public static final int KEYCODE_TV_DATA_SERVICE = 230; // 0xe6 field public static final int KEYCODE_TV_INPUT = 178; // 0xb2 + field public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249; // 0xf9 + field public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250; // 0xfa + field public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247; // 0xf7 + field public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248; // 0xf8 + field public static final int KEYCODE_TV_INPUT_HDMI_1 = 243; // 0xf3 + field public static final int KEYCODE_TV_INPUT_HDMI_2 = 244; // 0xf4 + field public static final int KEYCODE_TV_INPUT_HDMI_3 = 245; // 0xf5 + field public static final int KEYCODE_TV_INPUT_HDMI_4 = 246; // 0xf6 + field public static final int KEYCODE_TV_INPUT_VGA_1 = 251; // 0xfb + field public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257; // 0x101 + field public static final int KEYCODE_TV_NETWORK = 241; // 0xf1 + field public static final int KEYCODE_TV_NUMBER_ENTRY = 234; // 0xea field public static final int KEYCODE_TV_POWER = 177; // 0xb1 + field public static final int KEYCODE_TV_RADIO_SERVICE = 232; // 0xe8 + field public static final int KEYCODE_TV_SATELLITE = 237; // 0xed + field public static final int KEYCODE_TV_SATELLITE_BS = 238; // 0xee + field public static final int KEYCODE_TV_SATELLITE_CS = 239; // 0xef + field public static final int KEYCODE_TV_SATELLITE_SERVICE = 240; // 0xf0 + field public static final int KEYCODE_TV_TELETEXT = 233; // 0xe9 + field public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235; // 0xeb + field public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236; // 0xec + field public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258; // 0x102 + field public static final int KEYCODE_TV_ZOOM_MODE = 255; // 0xff field public static final int KEYCODE_U = 49; // 0x31 field public static final int KEYCODE_UNKNOWN = 0; // 0x0 field public static final int KEYCODE_V = 50; // 0x32 + field public static final int KEYCODE_VOICE_ASSIST = 231; // 0xe7 field public static final int KEYCODE_VOLUME_DOWN = 25; // 0x19 field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4 field public static final int KEYCODE_VOLUME_UP = 24; // 0x18 @@ -27339,6 +32783,7 @@ method public final float getY(); method public final float getY(int); method public final float getYPrecision(); + method public final boolean isButtonPressed(int); method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int); method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int); method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int); @@ -27600,6 +33045,7 @@ ctor public SurfaceView(android.content.Context); ctor public SurfaceView(android.content.Context, android.util.AttributeSet); ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int); + ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int, int); method public boolean gatherTransparentRegion(android.graphics.Region); method public android.view.SurfaceHolder getHolder(); method public void setSecure(boolean); @@ -27611,6 +33057,7 @@ ctor public TextureView(android.content.Context); ctor public TextureView(android.content.Context, android.util.AttributeSet); ctor public TextureView(android.content.Context, android.util.AttributeSet, int); + ctor public TextureView(android.content.Context, android.util.AttributeSet, int, int); method public final void draw(android.graphics.Canvas); method public android.graphics.Bitmap getBitmap(); method public android.graphics.Bitmap getBitmap(int, int); @@ -27662,6 +33109,7 @@ ctor public View(android.content.Context); ctor public View(android.content.Context, android.util.AttributeSet); ctor public View(android.content.Context, android.util.AttributeSet, int); + ctor public View(android.content.Context, android.util.AttributeSet, int, int); method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>); method public void addFocusables(java.util.ArrayList<android.view.View>, int); method public void addFocusables(java.util.ArrayList<android.view.View>, int, int); @@ -27693,6 +33141,7 @@ method protected int computeHorizontalScrollOffset(); method protected int computeHorizontalScrollRange(); method public void computeScroll(); + method public android.view.WindowInsets computeSystemWindowInsets(android.view.WindowInsets, android.graphics.Rect); method protected int computeVerticalScrollExtent(); method protected int computeVerticalScrollOffset(); method protected int computeVerticalScrollRange(); @@ -27711,6 +33160,10 @@ method public boolean dispatchKeyEvent(android.view.KeyEvent); method public boolean dispatchKeyEventPreIme(android.view.KeyEvent); method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent); + method public boolean dispatchNestedFling(float, float, boolean); + method public boolean dispatchNestedPreFling(float, float); + method public boolean dispatchNestedPreScroll(int, int, int[], int[]); + method public boolean dispatchNestedScroll(int, int, int, int, int[]); method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>); method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>); @@ -27726,6 +33179,7 @@ method public void dispatchWindowSystemUiVisiblityChanged(int); method public void dispatchWindowVisibilityChanged(int); method public void draw(android.graphics.Canvas); + method public void drawableHotspotChanged(float, float); method protected void drawableStateChanged(); method public android.view.View findFocus(); method public final android.view.View findViewById(int); @@ -27741,12 +33195,15 @@ method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public android.graphics.drawable.Drawable getBackground(); + method public android.content.res.ColorStateList getBackgroundTintList(); + method public android.graphics.PorterDuff.Mode getBackgroundTintMode(); method public int getBaseline(); method public final int getBottom(); method protected float getBottomFadingEdgeStrength(); method protected int getBottomPaddingOffset(); method public float getCameraDistance(); method public android.graphics.Rect getClipBounds(); + method public final boolean getClipToOutline(); method public java.lang.CharSequence getContentDescription(); method public final android.content.Context getContext(); method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo(); @@ -27759,6 +33216,7 @@ method public int getDrawingCacheQuality(); method public void getDrawingRect(android.graphics.Rect); method public long getDrawingTime(); + method public float getElevation(); method public boolean getFilterTouchesWhenObscured(); method public boolean getFitsSystemWindows(); method public java.util.ArrayList<android.view.View> getFocusables(int); @@ -27798,6 +33256,7 @@ method public int getNextFocusRightId(); method public int getNextFocusUpId(); method public android.view.View.OnFocusChangeListener getOnFocusChangeListener(); + method public android.view.ViewOutlineProvider getOutlineProvider(); method public int getOverScrollMode(); method public android.view.ViewOverlay getOverlay(); method public int getPaddingBottom(); @@ -27827,6 +33286,7 @@ method public final int getScrollX(); method public final int getScrollY(); method public int getSolidColor(); + method public android.animation.StateListAnimator getStateListAnimator(); method protected int getSuggestedMinimumHeight(); method protected int getSuggestedMinimumWidth(); method public int getSystemUiVisibility(); @@ -27839,8 +33299,10 @@ method protected int getTopPaddingOffset(); method public android.view.TouchDelegate getTouchDelegate(); method public java.util.ArrayList<android.view.View> getTouchables(); + method public java.lang.String getTransitionName(); method public float getTranslationX(); method public float getTranslationY(); + method public float getTranslationZ(); method public int getVerticalFadingEdgeLength(); method public int getVerticalScrollbarPosition(); method public int getVerticalScrollbarWidth(); @@ -27855,19 +33317,21 @@ method public void getWindowVisibleDisplayFrame(android.graphics.Rect); method public float getX(); method public float getY(); + method public float getZ(); method public boolean hasFocus(); method public boolean hasFocusable(); + method public boolean hasNestedScrollingParent(); method public boolean hasOnClickListeners(); method public boolean hasOverlappingRendering(); method public boolean hasTransientState(); method public boolean hasWindowFocus(); method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup); - method protected void initializeFadingEdge(android.content.res.TypedArray); - method protected void initializeScrollbars(android.content.res.TypedArray); method public void invalidate(android.graphics.Rect); method public void invalidate(int, int, int, int); method public void invalidate(); method public void invalidateDrawable(android.graphics.drawable.Drawable); + method public void invalidateOutline(); + method public boolean isAccessibilityFocused(); method public boolean isActivated(); method public boolean isAttachedToWindow(); method public boolean isClickable(); @@ -27883,6 +33347,7 @@ method public boolean isHorizontalFadingEdgeEnabled(); method public boolean isHorizontalScrollBarEnabled(); method public boolean isHovered(); + method public boolean isImportantForAccessibility(); method public boolean isInEditMode(); method public boolean isInLayout(); method public boolean isInTouchMode(); @@ -27890,6 +33355,7 @@ method public boolean isLayoutDirectionResolved(); method public boolean isLayoutRequested(); method public boolean isLongClickable(); + method public boolean isNestedScrollingEnabled(); method public boolean isOpaque(); method protected boolean isPaddingOffsetRequired(); method public boolean isPaddingRelative(); @@ -27989,6 +33455,7 @@ method public void requestLayout(); method public boolean requestRectangleOnScreen(android.graphics.Rect); method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean); + method public final void requestUnbufferedDispatch(android.view.MotionEvent); method public static int resolveSize(int, int); method public static int resolveSizeAndState(int, int, int); method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>); @@ -28007,15 +33474,19 @@ method public void setBackgroundColor(int); method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setBackgroundResource(int); + method public void setBackgroundTintList(android.content.res.ColorStateList); + method public void setBackgroundTintMode(android.graphics.PorterDuff.Mode); method public final void setBottom(int); method public void setCameraDistance(float); method public void setClickable(boolean); method public void setClipBounds(android.graphics.Rect); + method public void setClipToOutline(boolean); method public void setContentDescription(java.lang.CharSequence); method public void setDrawingCacheBackgroundColor(int); method public void setDrawingCacheEnabled(boolean); method public void setDrawingCacheQuality(int); method public void setDuplicateParentStateEnabled(boolean); + method public void setElevation(float); method public void setEnabled(boolean); method public void setFadingEdgeLength(int); method public void setFilterTouchesWhenObscured(boolean); @@ -28040,6 +33511,7 @@ method protected final void setMeasuredDimension(int, int); method public void setMinimumHeight(int); method public void setMinimumWidth(int); + method public void setNestedScrollingEnabled(boolean); method public void setNextFocusDownId(int); method public void setNextFocusForwardId(int); method public void setNextFocusLeftId(int); @@ -28056,6 +33528,7 @@ method public void setOnLongClickListener(android.view.View.OnLongClickListener); method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener); method public void setOnTouchListener(android.view.View.OnTouchListener); + method public void setOutlineProvider(android.view.ViewOutlineProvider); method public void setOverScrollMode(int); method public void setPadding(int, int, int, int); method public void setPaddingRelative(int, int, int, int); @@ -28080,6 +33553,7 @@ method public void setScrollbarFadingEnabled(boolean); method public void setSelected(boolean); method public void setSoundEffectsEnabled(boolean); + method public void setStateListAnimator(android.animation.StateListAnimator); method public void setSystemUiVisibility(int); method public void setTag(java.lang.Object); method public void setTag(int, java.lang.Object); @@ -28087,8 +33561,10 @@ method public void setTextDirection(int); method public final void setTop(int); method public void setTouchDelegate(android.view.TouchDelegate); + method public final void setTransitionName(java.lang.String); method public void setTranslationX(float); method public void setTranslationY(float); + method public void setTranslationZ(float); method public void setVerticalFadingEdgeEnabled(boolean); method public void setVerticalScrollBarEnabled(boolean); method public void setVerticalScrollbarPosition(int); @@ -28097,10 +33573,13 @@ method public void setWillNotDraw(boolean); method public void setX(float); method public void setY(float); + method public void setZ(float); method public boolean showContextMenu(); method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback); method public void startAnimation(android.view.animation.Animation); method public final boolean startDrag(android.content.ClipData, android.view.View.DragShadowBuilder, java.lang.Object, int); + method public boolean startNestedScroll(int); + method public void stopNestedScroll(); method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); method public void unscheduleDrawable(android.graphics.drawable.Drawable); method protected boolean verifyDrawable(android.graphics.drawable.Drawable); @@ -28189,6 +33668,9 @@ field public static final int SCROLLBAR_POSITION_DEFAULT = 0; // 0x0 field public static final int SCROLLBAR_POSITION_LEFT = 1; // 0x1 field public static final int SCROLLBAR_POSITION_RIGHT = 2; // 0x2 + field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1 + field public static final int SCROLL_AXIS_NONE = 0; // 0x0 + field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2 field protected static final int[] SELECTED_STATE_SET; field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000 @@ -28219,11 +33701,13 @@ field public static final int TEXT_DIRECTION_RTL = 4; // 0x4 field public static final android.util.Property TRANSLATION_X; field public static final android.util.Property TRANSLATION_Y; + field public static final android.util.Property TRANSLATION_Z; field protected static final java.lang.String VIEW_LOG_TAG = "View"; field public static final int VISIBLE = 0; // 0x0 field protected static final int[] WINDOW_FOCUSED_STATE_SET; field public static final android.util.Property X; field public static final android.util.Property Y; + field public static final android.util.Property Z; } public static class View.AccessibilityDelegate { @@ -28317,6 +33801,10 @@ method public abstract boolean onTouch(android.view.View, android.view.MotionEvent); } + public final class ViewAnimationUtils { + method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float); + } + public class ViewConfiguration { ctor public deprecated ViewConfiguration(); method public static android.view.ViewConfiguration get(android.content.Context); @@ -28408,6 +33896,7 @@ ctor public ViewGroup(android.content.Context); ctor public ViewGroup(android.content.Context, android.util.AttributeSet); ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int); + ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int, int); method public boolean addStatesFromChildren(); method public void addView(android.view.View); method public void addView(android.view.View, int); @@ -28450,13 +33939,16 @@ method protected boolean getChildStaticTransformation(android.view.View, android.view.animation.Transformation); method public boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point); method public boolean getClipChildren(); + method public boolean getClipToPadding(); method public int getDescendantFocusability(); method public android.view.View getFocusedChild(); method public android.view.animation.LayoutAnimationController getLayoutAnimation(); method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener(); method public int getLayoutMode(); method public android.animation.LayoutTransition getLayoutTransition(); + method public int getNestedScrollAxes(); method public int getPersistentDrawingCache(); + method public boolean getTouchscreenBlocksFocus(); method public int indexOfChild(android.view.View); method public final void invalidateChild(android.view.View, android.graphics.Rect); method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect); @@ -28465,6 +33957,7 @@ method protected boolean isChildrenDrawingOrderEnabled(); method protected boolean isChildrenDrawnWithCacheEnabled(); method public boolean isMotionEventSplittingEnabled(); + method public boolean isTransitionGroup(); method public final void layout(int, int, int, int); method protected void measureChild(android.view.View, int, int); method protected void measureChildWithMargins(android.view.View, int, int, int, int); @@ -28475,8 +33968,15 @@ method public boolean onInterceptHoverEvent(android.view.MotionEvent); method public boolean onInterceptTouchEvent(android.view.MotionEvent); method protected abstract void onLayout(boolean, int, int, int, int); + method public boolean onNestedFling(android.view.View, float, float, boolean); + method public boolean onNestedPreFling(android.view.View, float, float); + method public void onNestedPreScroll(android.view.View, int, int, int[]); + method public void onNestedScroll(android.view.View, int, int, int, int); + method public void onNestedScrollAccepted(android.view.View, android.view.View, int); method protected boolean onRequestFocusInDescendants(int, android.graphics.Rect); method public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); + method public boolean onStartNestedScroll(android.view.View, android.view.View, int); + method public void onStopNestedScroll(android.view.View); method public void recomputeViewAttributes(android.view.View); method public void removeAllViews(); method public void removeAllViewsInLayout(); @@ -28509,6 +34009,8 @@ method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener); method public void setPersistentDrawingCache(int); method protected void setStaticTransformationsEnabled(boolean); + method public void setTouchscreenBlocksFocus(boolean); + method public void setTransitionGroup(boolean); method public boolean shouldDelayChildPressedState(); method public boolean showContextMenuForChild(android.view.View); method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback); @@ -28576,6 +34078,14 @@ method public abstract void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams); } + public abstract class ViewOutlineProvider { + ctor public ViewOutlineProvider(); + method public abstract void getOutline(android.view.View, android.graphics.Outline); + field public static final android.view.ViewOutlineProvider BACKGROUND; + field public static final android.view.ViewOutlineProvider BOUNDS; + field public static final android.view.ViewOutlineProvider PADDED_BOUNDS; + } + public class ViewOverlay { method public void add(android.graphics.drawable.Drawable); method public void clear(); @@ -28606,6 +34116,13 @@ method public abstract boolean isTextAlignmentResolved(); method public abstract boolean isTextDirectionResolved(); method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int); + method public abstract boolean onNestedFling(android.view.View, float, float, boolean); + method public abstract boolean onNestedPreFling(android.view.View, float, float); + method public abstract void onNestedPreScroll(android.view.View, int, int, int[]); + method public abstract void onNestedScroll(android.view.View, int, int, int, int); + method public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int); + method public abstract boolean onStartNestedScroll(android.view.View, android.view.View, int); + method public abstract void onStopNestedScroll(android.view.View); method public abstract void recomputeViewAttributes(android.view.View); method public abstract void requestChildFocus(android.view.View, android.view.View); method public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean); @@ -28645,6 +34162,8 @@ method public android.view.ViewPropertyAnimator translationXBy(float); method public android.view.ViewPropertyAnimator translationY(float); method public android.view.ViewPropertyAnimator translationYBy(float); + method public android.view.ViewPropertyAnimator translationZ(float); + method public android.view.ViewPropertyAnimator translationZBy(float); method public android.view.ViewPropertyAnimator withEndAction(java.lang.Runnable); method public android.view.ViewPropertyAnimator withLayer(); method public android.view.ViewPropertyAnimator withStartAction(java.lang.Runnable); @@ -28652,6 +34171,8 @@ method public android.view.ViewPropertyAnimator xBy(float); method public android.view.ViewPropertyAnimator y(float); method public android.view.ViewPropertyAnimator yBy(float); + method public android.view.ViewPropertyAnimator z(float); + method public android.view.ViewPropertyAnimator zBy(float); } public final class ViewStub extends android.view.View { @@ -28659,6 +34180,7 @@ ctor public ViewStub(android.content.Context, int); ctor public ViewStub(android.content.Context, android.util.AttributeSet); ctor public ViewStub(android.content.Context, android.util.AttributeSet, int); + ctor public ViewStub(android.content.Context, android.util.AttributeSet, int, int); method public int getInflatedId(); method public android.view.LayoutInflater getLayoutInflater(); method public int getLayoutResource(); @@ -28738,16 +34260,33 @@ method public abstract void closeAllPanels(); method public abstract void closePanel(int); method public android.view.View findViewById(int); + method public boolean getAllowEnterTransitionOverlap(); + method public boolean getAllowReturnTransitionOverlap(); method public final android.view.WindowManager.LayoutParams getAttributes(); method public final android.view.Window.Callback getCallback(); method public final android.view.Window getContainer(); + method public android.transition.Scene getContentScene(); method public final android.content.Context getContext(); method public abstract android.view.View getCurrentFocus(); method public abstract android.view.View getDecorView(); + method public android.transition.Transition getEnterTransition(); + method public android.transition.Transition getExitTransition(); method protected final int getFeatures(); method protected final int getForcedWindowFlags(); method public abstract android.view.LayoutInflater getLayoutInflater(); method protected final int getLocalFeatures(); + method public android.media.session.MediaController getMediaController(); + method public abstract int getNavigationBarColor(); + method public android.transition.Transition getReenterTransition(); + method public android.transition.Transition getReturnTransition(); + method public android.transition.Transition getSharedElementEnterTransition(); + method public android.transition.Transition getSharedElementExitTransition(); + method public android.transition.Transition getSharedElementReenterTransition(); + method public android.transition.Transition getSharedElementReturnTransition(); + method public boolean getSharedElementsUseOverlay(); + method public abstract int getStatusBarColor(); + method public long getTransitionBackgroundFadeDuration(); + method public android.transition.TransitionManager getTransitionManager(); method public abstract int getVolumeControlStream(); method public android.view.WindowManager getWindowManager(); method public final android.content.res.TypedArray getWindowStyle(); @@ -28770,6 +34309,8 @@ method public boolean requestFeature(int); method public abstract void restoreHierarchyState(android.os.Bundle); method public abstract android.os.Bundle saveHierarchyState(); + method public void setAllowEnterTransitionOverlap(boolean); + method public void setAllowReturnTransitionOverlap(boolean); method public void setAttributes(android.view.WindowManager.LayoutParams); method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setBackgroundDrawableResource(int); @@ -28782,6 +34323,8 @@ method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams); method protected void setDefaultWindowFormat(int); method public void setDimAmount(float); + method public void setEnterTransition(android.transition.Transition); + method public void setExitTransition(android.transition.Transition); method public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable); method public abstract void setFeatureDrawableAlpha(int, int); method public abstract void setFeatureDrawableResource(int, int); @@ -28794,9 +34337,21 @@ method public void setLayout(int, int); method public void setLocalFocus(boolean, boolean); method public void setLogo(int); + method public void setMediaController(android.media.session.MediaController); + method public abstract void setNavigationBarColor(int); + method public void setReenterTransition(android.transition.Transition); + method public void setReturnTransition(android.transition.Transition); + method public void setSharedElementEnterTransition(android.transition.Transition); + method public void setSharedElementExitTransition(android.transition.Transition); + method public void setSharedElementReenterTransition(android.transition.Transition); + method public void setSharedElementReturnTransition(android.transition.Transition); + method public void setSharedElementsUseOverlay(boolean); method public void setSoftInputMode(int); + method public abstract void setStatusBarColor(int); method public abstract void setTitle(java.lang.CharSequence); - method public abstract void setTitleColor(int); + method public abstract deprecated void setTitleColor(int); + method public void setTransitionBackgroundFadeDuration(long); + method public void setTransitionManager(android.transition.TransitionManager); method public void setType(int); method public void setUiOptions(int); method public void setUiOptions(int, int); @@ -28817,6 +34372,8 @@ field public static final int FEATURE_ACTION_BAR = 8; // 0x8 field public static final int FEATURE_ACTION_BAR_OVERLAY = 9; // 0x9 field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa + field public static final int FEATURE_ACTIVITY_TRANSITIONS = 13; // 0xd + field public static final int FEATURE_CONTENT_TRANSITIONS = 12; // 0xc field public static final int FEATURE_CONTEXT_MENU = 6; // 0x6 field public static final int FEATURE_CUSTOM_TITLE = 7; // 0x7 field public static final int FEATURE_INDETERMINATE_PROGRESS = 5; // 0x5 @@ -28827,6 +34384,7 @@ field public static final int FEATURE_RIGHT_ICON = 4; // 0x4 field public static final int FEATURE_SWIPE_TO_DISMISS = 11; // 0xb field public static final int ID_ANDROID_CONTENT = 16908290; // 0x1020002 + field public static final java.lang.String NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME = "android:navigation:background"; field public static final int PROGRESS_END = 10000; // 0x2710 field public static final int PROGRESS_INDETERMINATE_OFF = -4; // 0xfffffffc field public static final int PROGRESS_INDETERMINATE_ON = -3; // 0xfffffffd @@ -28835,6 +34393,7 @@ field public static final int PROGRESS_START = 0; // 0x0 field public static final int PROGRESS_VISIBILITY_OFF = -2; // 0xfffffffe field public static final int PROGRESS_VISIBILITY_ON = -1; // 0xffffffff + field public static final java.lang.String STATUS_BAR_BACKGROUND_TRANSITION_NAME = "android:status:background"; } public static abstract interface Window.Callback { @@ -28861,6 +34420,20 @@ method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback); } + public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class WindowContentFrameStats extends android.view.FrameStats implements android.os.Parcelable { + method public int describeContents(); + method public long getFramePostedTimeNano(int); + method public long getFrameReadyTimeNano(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class WindowId implements android.os.Parcelable { method public int describeContents(); method public boolean isFocused(); @@ -28878,15 +34451,23 @@ public final class WindowInsets { ctor public WindowInsets(android.view.WindowInsets); + method public android.view.WindowInsets consumeStableInsets(); method public android.view.WindowInsets consumeSystemWindowInsets(); + method public int getStableInsetBottom(); + method public int getStableInsetLeft(); + method public int getStableInsetRight(); + method public int getStableInsetTop(); method public int getSystemWindowInsetBottom(); method public int getSystemWindowInsetLeft(); method public int getSystemWindowInsetRight(); method public int getSystemWindowInsetTop(); method public boolean hasInsets(); + method public boolean hasStableInsets(); method public boolean hasSystemWindowInsets(); + method public boolean isConsumed(); method public boolean isRound(); method public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int); + method public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect); } public abstract interface WindowManager implements android.view.ViewManager { @@ -28936,6 +34517,7 @@ field public static final int FLAG_DIM_BEHIND = 2; // 0x2 field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000 field public static final deprecated int FLAG_DITHER = 4096; // 0x1000 + field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000 field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800 field public static final int FLAG_FULLSCREEN = 1024; // 0x400 field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000 @@ -29000,7 +34582,6 @@ field public static final int TYPE_CHANGED = 2; // 0x2 field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc - field public static final int TYPE_KEYGUARD = 2004; // 0x7d4 field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9 field public static final int TYPE_PHONE = 2002; // 0x7d2 field public static final int TYPE_PRIORITY_PHONE = 2007; // 0x7d7 @@ -29024,6 +34605,7 @@ field public float horizontalWeight; field public deprecated int memoryType; field public java.lang.String packageName; + field public float preferredRefreshRate; field public int rotationAnimation; field public float screenBrightness; field public int screenOrientation; @@ -29093,6 +34675,7 @@ field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10 field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000 field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000 + field public static final int TYPE_WINDOWS_CHANGED = 4194304; // 0x400000 field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800 field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20 } @@ -29125,7 +34708,8 @@ } public class AccessibilityNodeInfo implements android.os.Parcelable { - method public void addAction(int); + method public void addAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction); + method public deprecated void addAction(int); method public void addChild(android.view.View); method public void addChild(android.view.View, int); method public boolean canOpenPopup(); @@ -29134,7 +34718,8 @@ method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(java.lang.String); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int); - method public int getActions(); + method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList(); + method public deprecated int getActions(); method public void getBoundsInParent(android.graphics.Rect); method public void getBoundsInScreen(android.graphics.Rect); method public android.view.accessibility.AccessibilityNodeInfo getChild(int); @@ -29143,11 +34728,13 @@ method public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo getCollectionInfo(); method public android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo getCollectionItemInfo(); method public java.lang.CharSequence getContentDescription(); + method public java.lang.CharSequence getError(); method public android.os.Bundle getExtras(); method public int getInputType(); method public android.view.accessibility.AccessibilityNodeInfo getLabelFor(); method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy(); method public int getLiveRegion(); + method public int getMaxTextLength(); method public int getMovementGranularities(); method public java.lang.CharSequence getPackageName(); method public android.view.accessibility.AccessibilityNodeInfo getParent(); @@ -29156,6 +34743,7 @@ method public int getTextSelectionEnd(); method public int getTextSelectionStart(); method public java.lang.String getViewIdResourceName(); + method public android.view.accessibility.AccessibilityWindowInfo getWindow(); method public int getWindowId(); method public boolean isAccessibilityFocused(); method public boolean isCheckable(); @@ -29181,6 +34769,10 @@ method public boolean performAction(int, android.os.Bundle); method public void recycle(); method public boolean refresh(); + method public deprecated void removeAction(int); + method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction); + method public boolean removeChild(android.view.View); + method public boolean removeChild(android.view.View, int); method public void setAccessibilityFocused(boolean); method public void setBoundsInParent(android.graphics.Rect); method public void setBoundsInScreen(android.graphics.Rect); @@ -29196,6 +34788,7 @@ method public void setDismissable(boolean); method public void setEditable(boolean); method public void setEnabled(boolean); + method public void setError(java.lang.CharSequence); method public void setFocusable(boolean); method public void setFocused(boolean); method public void setInputType(int); @@ -29205,6 +34798,7 @@ method public void setLabeledBy(android.view.View, int); method public void setLiveRegion(int); method public void setLongClickable(boolean); + method public void setMaxTextLength(int); method public void setMovementGranularities(int); method public void setMultiLine(boolean); method public void setPackageName(java.lang.CharSequence); @@ -29227,6 +34821,7 @@ field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT"; field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT"; field public static final java.lang.String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT"; + field public static final java.lang.String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE"; field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80 field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2 field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8 @@ -29247,6 +34842,7 @@ field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000 field public static final int ACTION_SELECT = 4; // 0x4 field public static final int ACTION_SET_SELECTION = 131072; // 0x20000 + field public static final int ACTION_SET_TEXT = 2097152; // 0x200000 field public static final android.os.Parcelable.Creator CREATOR; field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2 field public static final int FOCUS_INPUT = 1; // 0x1 @@ -29257,11 +34853,44 @@ field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2 } + public static final class AccessibilityNodeInfo.AccessibilityAction { + ctor public AccessibilityNodeInfo.AccessibilityAction(int, java.lang.CharSequence); + method public int getId(); + method public java.lang.CharSequence getLabel(); + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_ACCESSIBILITY_FOCUS; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_FOCUS; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_SELECTION; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLICK; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_COLLAPSE; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_COPY; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CUT; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_DISMISS; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_EXPAND; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_FOCUS; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_LONG_CLICK; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_HTML_ELEMENT; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PASTE; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_BACKWARD; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_FORWARD; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SELECT; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION; + field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT; + } + public static final class AccessibilityNodeInfo.CollectionInfo { method public int getColumnCount(); method public int getRowCount(); + method public int getSelectionMode(); method public boolean isHierarchical(); method public static android.view.accessibility.AccessibilityNodeInfo.CollectionInfo obtain(int, int, boolean); + method public static android.view.accessibility.AccessibilityNodeInfo.CollectionInfo obtain(int, int, boolean, int); + field public static final int SELECTION_MODE_MULTIPLE = 2; // 0x2 + field public static final int SELECTION_MODE_NONE = 0; // 0x0 + field public static final int SELECTION_MODE_SINGLE = 1; // 0x1 } public static final class AccessibilityNodeInfo.CollectionItemInfo { @@ -29270,7 +34899,9 @@ method public int getRowIndex(); method public int getRowSpan(); method public boolean isHeading(); + method public boolean isSelected(); method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean); + method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean); } public static final class AccessibilityNodeInfo.RangeInfo { @@ -29290,6 +34921,7 @@ method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method public boolean performAction(int, int, android.os.Bundle); + field public static final int HOST_VIEW_ID = -1; // 0xffffffff } public class AccessibilityRecord { @@ -29341,6 +34973,29 @@ method public void setToIndex(int); } + public final class AccessibilityWindowInfo implements android.os.Parcelable { + method public int describeContents(); + method public void getBoundsInScreen(android.graphics.Rect); + method public android.view.accessibility.AccessibilityWindowInfo getChild(int); + method public int getChildCount(); + method public int getId(); + method public int getLayer(); + method public android.view.accessibility.AccessibilityWindowInfo getParent(); + method public android.view.accessibility.AccessibilityNodeInfo getRoot(); + method public int getType(); + method public boolean isAccessibilityFocused(); + method public boolean isActive(); + method public boolean isFocused(); + method public static android.view.accessibility.AccessibilityWindowInfo obtain(); + method public static android.view.accessibility.AccessibilityWindowInfo obtain(android.view.accessibility.AccessibilityWindowInfo); + method public void recycle(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int TYPE_APPLICATION = 1; // 0x1 + field public static final int TYPE_INPUT_METHOD = 2; // 0x2 + field public static final int TYPE_SYSTEM = 3; // 0x3 + } + public class CaptioningManager { method public void addCaptioningChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener); method public final float getFontScale(); @@ -29352,13 +35007,22 @@ public static final class CaptioningManager.CaptionStyle { method public android.graphics.Typeface getTypeface(); + method public boolean hasBackgroundColor(); + method public boolean hasEdgeColor(); + method public boolean hasEdgeType(); + method public boolean hasForegroundColor(); + method public boolean hasWindowColor(); + field public static final int EDGE_TYPE_DEPRESSED = 4; // 0x4 field public static final int EDGE_TYPE_DROP_SHADOW = 2; // 0x2 field public static final int EDGE_TYPE_NONE = 0; // 0x0 field public static final int EDGE_TYPE_OUTLINE = 1; // 0x1 + field public static final int EDGE_TYPE_RAISED = 3; // 0x3 + field public static final int EDGE_TYPE_UNSPECIFIED = -1; // 0xffffffff field public final int backgroundColor; field public final int edgeColor; field public final int edgeType; field public final int foregroundColor; + field public final int windowColor; } public static abstract class CaptioningManager.CaptioningChangeListener { @@ -29596,6 +35260,14 @@ method public float getInterpolation(float); } + public class PathInterpolator implements android.view.animation.Interpolator { + ctor public PathInterpolator(android.graphics.Path); + ctor public PathInterpolator(float, float); + ctor public PathInterpolator(float, float, float, float); + ctor public PathInterpolator(android.content.Context, android.util.AttributeSet); + method public float getInterpolation(float); + } + public class RotateAnimation extends android.view.animation.Animation { ctor public RotateAnimation(android.content.Context, android.util.AttributeSet); ctor public RotateAnimation(float, float); @@ -29663,6 +35335,7 @@ method public boolean performPrivateCommand(java.lang.String, android.os.Bundle); method public static final void removeComposingSpans(android.text.Spannable); method public boolean reportFullscreenMode(boolean); + method public boolean requestCursorUpdates(int); method public boolean sendKeyEvent(android.view.KeyEvent); method public boolean setComposingRegion(int, int); method public static void setComposingSpans(android.text.Spannable); @@ -29692,6 +35365,39 @@ field public static final android.os.Parcelable.Creator CREATOR; } + public final class CursorAnchorInfo implements android.os.Parcelable { + ctor public CursorAnchorInfo(android.os.Parcel); + method public int describeContents(); + method public android.graphics.RectF getCharacterBounds(int); + method public int getCharacterBoundsFlags(int); + method public java.lang.CharSequence getComposingText(); + method public int getComposingTextStart(); + method public float getInsertionMarkerBaseline(); + method public float getInsertionMarkerBottom(); + method public int getInsertionMarkerFlags(); + method public float getInsertionMarkerHorizontal(); + method public float getInsertionMarkerTop(); + method public android.graphics.Matrix getMatrix(); + method public int getSelectionEnd(); + method public int getSelectionStart(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int FLAG_HAS_INVISIBLE_REGION = 2; // 0x2 + field public static final int FLAG_HAS_VISIBLE_REGION = 1; // 0x1 + field public static final int FLAG_IS_RTL = 4; // 0x4 + } + + public static final class CursorAnchorInfo.Builder { + ctor public CursorAnchorInfo.Builder(); + method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterBounds(int, float, float, float, float, int); + method public android.view.inputmethod.CursorAnchorInfo build(); + method public void reset(); + method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence); + method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, int); + method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix); + method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int); + } + public class EditorInfo implements android.text.InputType android.os.Parcelable { ctor public EditorInfo(); method public int describeContents(); @@ -29789,10 +35495,13 @@ method public abstract boolean performEditorAction(int); method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle); method public abstract boolean reportFullscreenMode(boolean); + method public abstract boolean requestCursorUpdates(int); method public abstract boolean sendKeyEvent(android.view.KeyEvent); method public abstract boolean setComposingRegion(int, int); method public abstract boolean setComposingText(java.lang.CharSequence, int); method public abstract boolean setSelection(int, int); + field public static final int CURSOR_UPDATE_IMMEDIATE = 1; // 0x1 + field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2 field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1 } @@ -29816,6 +35525,7 @@ method public boolean performEditorAction(int); method public boolean performPrivateCommand(java.lang.String, android.os.Bundle); method public boolean reportFullscreenMode(boolean); + method public boolean requestCursorUpdates(int); method public boolean sendKeyEvent(android.view.KeyEvent); method public boolean setComposingRegion(int, int); method public boolean setComposingText(java.lang.CharSequence, int); @@ -29881,7 +35591,7 @@ method public boolean isActive(android.view.View); method public boolean isActive(); method public boolean isFullscreenMode(); - method public boolean isWatchingCursor(android.view.View); + method public deprecated boolean isWatchingCursor(android.view.View); method public void restartInput(android.view.View); method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle); method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]); @@ -29899,7 +35609,8 @@ method public boolean switchToNextInputMethod(android.os.IBinder, boolean); method public void toggleSoftInput(int, int); method public void toggleSoftInputFromWindow(android.os.IBinder, int, int); - method public void updateCursor(android.view.View, int, int, int, int); + method public deprecated void updateCursor(android.view.View, int, int, int, int); + method public void updateCursorAnchorInfo(android.view.View, android.view.inputmethod.CursorAnchorInfo); method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText); method public void updateSelection(android.view.View, int, int, int, int); method public void viewClicked(android.view.View); @@ -29922,6 +35633,7 @@ method public abstract void finishInput(); method public abstract void toggleSoftInput(int, int); method public abstract void updateCursor(android.graphics.Rect); + method public abstract void updateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo); method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText); method public abstract void updateSelection(int, int, int, int, int, int); method public abstract void viewClicked(boolean); @@ -30045,8 +35757,10 @@ public final class TextInfo implements android.os.Parcelable { ctor public TextInfo(java.lang.String); ctor public TextInfo(java.lang.String, int, int); + ctor public TextInfo(java.lang.CharSequence, int, int, int, int); ctor public TextInfo(android.os.Parcel); method public int describeContents(); + method public java.lang.CharSequence getCharSequence(); method public int getCookie(); method public int getSequence(); method public java.lang.String getText(); @@ -30062,6 +35776,17 @@ package android.webkit { + public abstract class ClientCertRequest { + ctor public ClientCertRequest(); + method public abstract void cancel(); + method public abstract java.lang.String getHost(); + method public abstract java.lang.String[] getKeyTypes(); + method public abstract int getPort(); + method public abstract java.security.Principal[] getPrincipals(); + method public abstract void ignore(); + method public abstract void proceed(java.security.PrivateKey, java.security.cert.X509Certificate[]); + } + public class ConsoleMessage { ctor public ConsoleMessage(java.lang.String, java.lang.String, int, android.webkit.ConsoleMessage.MessageLevel); method public int lineNumber(); @@ -30082,22 +35807,31 @@ public class CookieManager { method public synchronized boolean acceptCookie(); + method public boolean acceptThirdPartyCookies(android.webkit.WebView); method public static boolean allowFileSchemeCookies(); + method public void flush(); method public java.lang.String getCookie(java.lang.String); method public static synchronized android.webkit.CookieManager getInstance(); method public synchronized boolean hasCookies(); - method public void removeAllCookie(); - method public void removeExpiredCookie(); - method public void removeSessionCookie(); + method public deprecated void removeAllCookie(); + method public void removeAllCookies(android.webkit.ValueCallback<java.lang.Boolean>); + method public deprecated void removeExpiredCookie(); + method public deprecated void removeSessionCookie(); + method public void removeSessionCookies(android.webkit.ValueCallback<java.lang.Boolean>); method public synchronized void setAcceptCookie(boolean); method public static void setAcceptFileSchemeCookies(boolean); + method public void setAcceptThirdPartyCookies(android.webkit.WebView, boolean); method public void setCookie(java.lang.String, java.lang.String); + method public void setCookie(java.lang.String, java.lang.String, android.webkit.ValueCallback<java.lang.Boolean>); } - public final class CookieSyncManager extends android.webkit.WebSyncManager { + public final deprecated class CookieSyncManager extends android.webkit.WebSyncManager { method public static synchronized android.webkit.CookieSyncManager createInstance(android.content.Context); method public static synchronized android.webkit.CookieSyncManager getInstance(); - method protected void syncFromRamToFlash(); + method protected deprecated void syncFromRamToFlash(); + field protected static final java.lang.String LOGTAG = "websync"; + field protected android.webkit.WebViewDatabase mDataBase; + field protected android.os.Handler mHandler; } public class DateSorter { @@ -30152,6 +35886,17 @@ method public boolean hasMimeType(java.lang.String); } + public abstract class PermissionRequest { + ctor public PermissionRequest(); + method public abstract void deny(); + method public abstract android.net.Uri getOrigin(); + method public abstract java.lang.String[] getResources(); + method public abstract void grant(java.lang.String[]); + field public static final java.lang.String RESOURCE_AUDIO_CAPTURE = "android.webkit.resource.AUDIO_CAPTURE"; + field public static final java.lang.String RESOURCE_PROTECTED_MEDIA_ID = "android.webkit.resource.PROTECTED_MEDIA_ID"; + field public static final java.lang.String RESOURCE_VIDEO_CAPTURE = "android.webkit.resource.VIDEO_CAPTURE"; + } + public abstract interface PluginStub { method public abstract android.view.View getEmbeddedView(int, android.content.Context); method public abstract android.view.View getFullScreenView(int, android.content.Context); @@ -30211,6 +35956,8 @@ method public boolean onJsConfirm(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult); method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult); method public deprecated boolean onJsTimeout(); + method public void onPermissionRequest(android.webkit.PermissionRequest); + method public void onPermissionRequestCanceled(android.webkit.PermissionRequest); method public void onProgressChanged(android.webkit.WebView, int); method public deprecated void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater); method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap); @@ -30219,12 +35966,27 @@ method public void onRequestFocus(android.webkit.WebView); method public void onShowCustomView(android.view.View, android.webkit.WebChromeClient.CustomViewCallback); method public deprecated void onShowCustomView(android.view.View, int, android.webkit.WebChromeClient.CustomViewCallback); + method public boolean onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams); } public static abstract interface WebChromeClient.CustomViewCallback { method public abstract void onCustomViewHidden(); } + public static abstract class WebChromeClient.FileChooserParams { + ctor public WebChromeClient.FileChooserParams(); + method public abstract android.content.Intent createIntent(); + method public abstract java.lang.String[] getAcceptTypes(); + method public abstract java.lang.String getFilenameHint(); + method public abstract int getMode(); + method public abstract java.lang.CharSequence getTitle(); + method public abstract boolean isCaptureEnabled(); + method public static android.net.Uri[] parseResult(int, android.content.Intent); + field public static final int MODE_OPEN = 0; // 0x0 + field public static final int MODE_OPEN_MULTIPLE = 1; // 0x1 + field public static final int MODE_SAVE = 3; // 0x3 + } + public class WebHistoryItem implements java.lang.Cloneable { method public android.graphics.Bitmap getFavicon(); method public java.lang.String getOriginalUrl(); @@ -30246,14 +36008,28 @@ method public abstract void onReceivedIcon(java.lang.String, android.graphics.Bitmap); } + public abstract interface WebResourceRequest { + method public abstract java.lang.String getMethod(); + method public abstract java.util.Map<java.lang.String, java.lang.String> getRequestHeaders(); + method public abstract android.net.Uri getUrl(); + method public abstract boolean hasGesture(); + method public abstract boolean isForMainFrame(); + } + public class WebResourceResponse { ctor public WebResourceResponse(java.lang.String, java.lang.String, java.io.InputStream); + ctor public WebResourceResponse(java.lang.String, java.lang.String, int, java.lang.String, java.util.Map<java.lang.String, java.lang.String>, java.io.InputStream); method public java.io.InputStream getData(); method public java.lang.String getEncoding(); method public java.lang.String getMimeType(); + method public java.lang.String getReasonPhrase(); + method public java.util.Map<java.lang.String, java.lang.String> getResponseHeaders(); + method public int getStatusCode(); method public void setData(java.io.InputStream); method public void setEncoding(java.lang.String); method public void setMimeType(java.lang.String); + method public void setResponseHeaders(java.util.Map<java.lang.String, java.lang.String>); + method public void setStatusCodeAndReasonPhrase(int, java.lang.String); } public abstract class WebSettings { @@ -30287,6 +36063,7 @@ method public boolean getMediaPlaybackRequiresUserGesture(); method public synchronized int getMinimumFontSize(); method public synchronized int getMinimumLogicalFontSize(); + method public abstract int getMixedContentMode(); method public deprecated synchronized android.webkit.WebSettings.PluginState getPluginState(); method public synchronized java.lang.String getSansSerifFontFamily(); method public boolean getSaveFormData(); @@ -30331,6 +36108,7 @@ method public void setMediaPlaybackRequiresUserGesture(boolean); method public synchronized void setMinimumFontSize(int); method public synchronized void setMinimumLogicalFontSize(int); + method public abstract void setMixedContentMode(int); method public void setNeedInitialFocus(boolean); method public deprecated synchronized void setPluginState(android.webkit.WebSettings.PluginState); method public deprecated synchronized void setRenderPriority(android.webkit.WebSettings.RenderPriority); @@ -30352,6 +36130,9 @@ field public static final int LOAD_DEFAULT = -1; // 0xffffffff field public static final deprecated int LOAD_NORMAL = 0; // 0x0 field public static final int LOAD_NO_CACHE = 2; // 0x2 + field public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0; // 0x0 + field public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2; // 0x2 + field public static final int MIXED_CONTENT_NEVER_ALLOW = 1; // 0x1 } public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum { @@ -30417,7 +36198,7 @@ method public abstract void updateQuota(long); } - abstract class WebSyncManager implements java.lang.Runnable { + abstract deprecated class WebSyncManager implements java.lang.Runnable { ctor protected WebSyncManager(android.content.Context, java.lang.String); method protected void onSyncInit(); method public void resetSync(); @@ -30434,6 +36215,7 @@ ctor public WebView(android.content.Context); ctor public WebView(android.content.Context, android.util.AttributeSet); ctor public WebView(android.content.Context, android.util.AttributeSet, int); + ctor public WebView(android.content.Context, android.util.AttributeSet, int, int); ctor public deprecated WebView(android.content.Context, android.util.AttributeSet, int, boolean); method public void addJavascriptInterface(java.lang.Object, java.lang.String); method public boolean canGoBack(); @@ -30443,15 +36225,18 @@ method public deprecated boolean canZoomOut(); method public deprecated android.graphics.Picture capturePicture(); method public void clearCache(boolean); + method public static void clearClientCertPreferences(java.lang.Runnable); method public void clearFormData(); method public void clearHistory(); method public void clearMatches(); method public void clearSslPreferences(); method public deprecated void clearView(); method public android.webkit.WebBackForwardList copyBackForwardList(); - method public android.print.PrintDocumentAdapter createPrintDocumentAdapter(); + method public deprecated android.print.PrintDocumentAdapter createPrintDocumentAdapter(); + method public android.print.PrintDocumentAdapter createPrintDocumentAdapter(java.lang.String); method public void destroy(); method public void documentHasImages(android.os.Message); + method public static void enableSlowWholeDocumentDraw(); method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>); method public static java.lang.String findAddress(java.lang.String); method public deprecated int findAll(java.lang.String); @@ -30515,6 +36300,7 @@ method public void setWebViewClient(android.webkit.WebViewClient); method public deprecated boolean showFindDialog(java.lang.String, boolean); method public void stopLoading(); + method public void zoomBy(float); method public boolean zoomIn(); method public boolean zoomOut(); field public static final java.lang.String SCHEME_GEO = "geo:0,0?q="; @@ -30558,14 +36344,17 @@ method public void onLoadResource(android.webkit.WebView, java.lang.String); method public void onPageFinished(android.webkit.WebView, java.lang.String); method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); + method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest); method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String); method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String); method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String); method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError); method public void onScaleChanged(android.webkit.WebView, float, float); method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message); - method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent); - method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String); + method public void onUnhandledInputEvent(android.webkit.WebView, android.view.InputEvent); + method public deprecated void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent); + method public deprecated android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String); + method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, android.webkit.WebResourceRequest); method public boolean shouldOverrideKeyEvent(android.webkit.WebView, android.view.KeyEvent); method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String); field public static final int ERROR_AUTHENTICATION = -4; // 0xfffffffc @@ -30608,12 +36397,14 @@ ctor public AbsListView(android.content.Context); ctor public AbsListView(android.content.Context, android.util.AttributeSet); ctor public AbsListView(android.content.Context, android.util.AttributeSet, int); + ctor public AbsListView(android.content.Context, android.util.AttributeSet, int, int); method public void afterTextChanged(android.text.Editable); method public void beforeTextChanged(java.lang.CharSequence, int, int, int); method public boolean canScrollList(int); method public void clearChoices(); method public void clearTextFilter(); method public void deferNotifyDataSetChanged(); + method public void fling(int); method public int getCacheColorHint(); method public int getCheckedItemCount(); method public long[] getCheckedItemIds(); @@ -30659,6 +36450,7 @@ method public void setDrawSelectorOnTop(boolean); method public void setFastScrollAlwaysVisible(boolean); method public void setFastScrollEnabled(boolean); + method public void setFastScrollStyle(int); method public void setFilterText(java.lang.String); method public void setFriction(float); method public void setItemChecked(int, boolean); @@ -30668,6 +36460,7 @@ method public void setRemoteViewsAdapter(android.content.Intent); method public void setScrollIndicators(android.view.View, android.view.View); method public void setScrollingCacheEnabled(boolean); + method public void setSelectionFromTop(int, int); method public void setSelector(int); method public void setSelector(android.graphics.drawable.Drawable); method public void setSmoothScrollbarEnabled(boolean); @@ -30721,18 +36514,26 @@ ctor public AbsSeekBar(android.content.Context); ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet); ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet, int); + ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet, int, int); method public int getKeyProgressIncrement(); + method public boolean getSplitTrack(); method public android.graphics.drawable.Drawable getThumb(); method public int getThumbOffset(); + method public android.content.res.ColorStateList getThumbTintList(); + method public android.graphics.PorterDuff.Mode getThumbTintMode(); method public void setKeyProgressIncrement(int); + method public void setSplitTrack(boolean); method public void setThumb(android.graphics.drawable.Drawable); method public void setThumbOffset(int); + method public void setThumbTintList(android.content.res.ColorStateList); + method public void setThumbTintMode(android.graphics.PorterDuff.Mode); } public abstract class AbsSpinner extends android.widget.AdapterView { ctor public AbsSpinner(android.content.Context); ctor public AbsSpinner(android.content.Context, android.util.AttributeSet); ctor public AbsSpinner(android.content.Context, android.util.AttributeSet, int); + ctor public AbsSpinner(android.content.Context, android.util.AttributeSet, int, int); method public android.widget.SpinnerAdapter getAdapter(); method public android.view.View getSelectedView(); method public void onRestoreInstanceState(android.os.Parcelable); @@ -30747,6 +36548,7 @@ ctor public AbsoluteLayout(android.content.Context); ctor public AbsoluteLayout(android.content.Context, android.util.AttributeSet); ctor public AbsoluteLayout(android.content.Context, android.util.AttributeSet, int); + ctor public AbsoluteLayout(android.content.Context, android.util.AttributeSet, int, int); method protected void onLayout(boolean, int, int, int, int); } @@ -30759,6 +36561,32 @@ field public int y; } + public class ActionMenuView extends android.widget.LinearLayout { + ctor public ActionMenuView(android.content.Context); + ctor public ActionMenuView(android.content.Context, android.util.AttributeSet); + method public void dismissPopupMenus(); + method public android.view.Menu getMenu(); + method public int getPopupTheme(); + method public boolean hideOverflowMenu(); + method public boolean isOverflowMenuShowing(); + method public void onConfigurationChanged(android.content.res.Configuration); + method public void onDetachedFromWindow(); + method public void setOnMenuItemClickListener(android.widget.ActionMenuView.OnMenuItemClickListener); + method public void setPopupTheme(int); + method public boolean showOverflowMenu(); + } + + public static class ActionMenuView.LayoutParams extends android.widget.LinearLayout.LayoutParams { + ctor public ActionMenuView.LayoutParams(android.content.Context, android.util.AttributeSet); + ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams); + ctor public ActionMenuView.LayoutParams(android.widget.ActionMenuView.LayoutParams); + ctor public ActionMenuView.LayoutParams(int, int); + } + + public static abstract interface ActionMenuView.OnMenuItemClickListener { + method public abstract boolean onMenuItemClick(android.view.MenuItem); + } + public abstract interface Adapter { method public abstract int getCount(); method public abstract java.lang.Object getItem(int); @@ -30778,6 +36606,7 @@ ctor public AdapterView(android.content.Context); ctor public AdapterView(android.content.Context, android.util.AttributeSet); ctor public AdapterView(android.content.Context, android.util.AttributeSet, int); + ctor public AdapterView(android.content.Context, android.util.AttributeSet, int, int); method public abstract T getAdapter(); method public int getCount(); method public android.view.View getEmptyView(); @@ -30831,6 +36660,7 @@ ctor public AdapterViewAnimator(android.content.Context); ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet); ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet, int); + ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet, int, int); method public void advance(); method public void deferNotifyDataSetChanged(); method public void fyiWillBeAdvancedByHostKThx(); @@ -30860,6 +36690,8 @@ public class AdapterViewFlipper extends android.widget.AdapterViewAnimator { ctor public AdapterViewFlipper(android.content.Context); ctor public AdapterViewFlipper(android.content.Context, android.util.AttributeSet); + ctor public AdapterViewFlipper(android.content.Context, android.util.AttributeSet, int); + ctor public AdapterViewFlipper(android.content.Context, android.util.AttributeSet, int, int); method public int getFlipInterval(); method public boolean isAutoStart(); method public boolean isFlipping(); @@ -30890,6 +36722,7 @@ ctor public AnalogClock(android.content.Context); ctor public AnalogClock(android.content.Context, android.util.AttributeSet); ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int); + ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int, int); } public class ArrayAdapter extends android.widget.BaseAdapter implements android.widget.Filterable { @@ -30922,6 +36755,7 @@ ctor public AutoCompleteTextView(android.content.Context); ctor public AutoCompleteTextView(android.content.Context, android.util.AttributeSet); ctor public AutoCompleteTextView(android.content.Context, android.util.AttributeSet, int); + ctor public AutoCompleteTextView(android.content.Context, android.util.AttributeSet, int, int); method public void clearListSelection(); method protected java.lang.CharSequence convertSelectionToString(java.lang.Object); method public void dismissDropDown(); @@ -31014,12 +36848,14 @@ ctor public Button(android.content.Context); ctor public Button(android.content.Context, android.util.AttributeSet); ctor public Button(android.content.Context, android.util.AttributeSet, int); + ctor public Button(android.content.Context, android.util.AttributeSet, int, int); } public class CalendarView extends android.widget.FrameLayout { ctor public CalendarView(android.content.Context); ctor public CalendarView(android.content.Context, android.util.AttributeSet); ctor public CalendarView(android.content.Context, android.util.AttributeSet, int); + ctor public CalendarView(android.content.Context, android.util.AttributeSet, int, int); method public long getDate(); method public int getDateTextAppearance(); method public int getFirstDayOfWeek(); @@ -31061,6 +36897,7 @@ ctor public CheckBox(android.content.Context); ctor public CheckBox(android.content.Context, android.util.AttributeSet); ctor public CheckBox(android.content.Context, android.util.AttributeSet, int); + ctor public CheckBox(android.content.Context, android.util.AttributeSet, int, int); } public abstract interface Checkable { @@ -31073,10 +36910,15 @@ ctor public CheckedTextView(android.content.Context); ctor public CheckedTextView(android.content.Context, android.util.AttributeSet); ctor public CheckedTextView(android.content.Context, android.util.AttributeSet, int); + ctor public CheckedTextView(android.content.Context, android.util.AttributeSet, int, int); method public android.graphics.drawable.Drawable getCheckMarkDrawable(); + method public android.content.res.ColorStateList getCheckMarkTintList(); + method public android.graphics.PorterDuff.Mode getCheckMarkTintMode(); method public boolean isChecked(); method public void setCheckMarkDrawable(int); method public void setCheckMarkDrawable(android.graphics.drawable.Drawable); + method public void setCheckMarkTintList(android.content.res.ColorStateList); + method public void setCheckMarkTintMode(android.graphics.PorterDuff.Mode); method public void setChecked(boolean); method public void toggle(); } @@ -31085,6 +36927,7 @@ ctor public Chronometer(android.content.Context); ctor public Chronometer(android.content.Context, android.util.AttributeSet); ctor public Chronometer(android.content.Context, android.util.AttributeSet, int); + ctor public Chronometer(android.content.Context, android.util.AttributeSet, int, int); method public long getBase(); method public java.lang.String getFormat(); method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener(); @@ -31103,9 +36946,14 @@ ctor public CompoundButton(android.content.Context); ctor public CompoundButton(android.content.Context, android.util.AttributeSet); ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int); + ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int, int); + method public android.content.res.ColorStateList getButtonTintList(); + method public android.graphics.PorterDuff.Mode getButtonTintMode(); method public boolean isChecked(); method public void setButtonDrawable(int); method public void setButtonDrawable(android.graphics.drawable.Drawable); + method public void setButtonTintList(android.content.res.ColorStateList); + method public void setButtonTintMode(android.graphics.PorterDuff.Mode); method public void setChecked(boolean); method public void setOnCheckedChangeListener(android.widget.CompoundButton.OnCheckedChangeListener); method public void toggle(); @@ -31174,9 +37022,11 @@ ctor public DatePicker(android.content.Context); ctor public DatePicker(android.content.Context, android.util.AttributeSet); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int); + ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int); method public android.widget.CalendarView getCalendarView(); method public boolean getCalendarViewShown(); method public int getDayOfMonth(); + method public int getFirstDayOfWeek(); method public long getMaxDate(); method public long getMinDate(); method public int getMonth(); @@ -31184,6 +37034,7 @@ method public int getYear(); method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener); method public void setCalendarViewShown(boolean); + method public void setFirstDayOfWeek(int); method public void setMaxDate(long); method public void setMinDate(long); method public void setSpinnersShown(boolean); @@ -31226,10 +37077,14 @@ ctor public EdgeEffect(android.content.Context); method public boolean draw(android.graphics.Canvas); method public void finish(); + method public int getColor(); + method public int getMaxHeight(); method public boolean isFinished(); method public void onAbsorb(int); method public void onPull(float); + method public void onPull(float, float); method public void onRelease(); + method public void setColor(int); method public void setSize(int, int); } @@ -31237,6 +37092,7 @@ ctor public EditText(android.content.Context); ctor public EditText(android.content.Context, android.util.AttributeSet); ctor public EditText(android.content.Context, android.util.AttributeSet, int); + ctor public EditText(android.content.Context, android.util.AttributeSet, int, int); method public void extendSelection(int); method public void selectAll(); method public void setSelection(int, int); @@ -31268,6 +37124,7 @@ ctor public ExpandableListView(android.content.Context); ctor public ExpandableListView(android.content.Context, android.util.AttributeSet); ctor public ExpandableListView(android.content.Context, android.util.AttributeSet, int); + ctor public ExpandableListView(android.content.Context, android.util.AttributeSet, int, int); method public boolean collapseGroup(int); method public boolean expandGroup(int); method public boolean expandGroup(int, boolean); @@ -31357,13 +37214,18 @@ ctor public FrameLayout(android.content.Context); ctor public FrameLayout(android.content.Context, android.util.AttributeSet); ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int); + ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int, int); method public deprecated boolean getConsiderGoneChildrenWhenMeasuring(); method public android.graphics.drawable.Drawable getForeground(); method public int getForegroundGravity(); + method public android.content.res.ColorStateList getForegroundTintList(); + method public android.graphics.PorterDuff.Mode getForegroundTintMode(); method public boolean getMeasureAllChildren(); method protected void onLayout(boolean, int, int, int, int); method public void setForeground(android.graphics.drawable.Drawable); method public void setForegroundGravity(int); + method public void setForegroundTintList(android.content.res.ColorStateList); + method public void setForegroundTintMode(android.graphics.PorterDuff.Mode); method public void setMeasureAllChildren(boolean); } @@ -31381,6 +37243,7 @@ ctor public Gallery(android.content.Context); ctor public Gallery(android.content.Context, android.util.AttributeSet); ctor public Gallery(android.content.Context, android.util.AttributeSet, int); + ctor public Gallery(android.content.Context, android.util.AttributeSet, int, int); method public boolean onDown(android.view.MotionEvent); method public boolean onFling(android.view.MotionEvent, android.view.MotionEvent, float, float); method public void onLongPress(android.view.MotionEvent); @@ -31401,9 +37264,10 @@ } public class GridLayout extends android.view.ViewGroup { - ctor public GridLayout(android.content.Context, android.util.AttributeSet, int); - ctor public GridLayout(android.content.Context, android.util.AttributeSet); ctor public GridLayout(android.content.Context); + ctor public GridLayout(android.content.Context, android.util.AttributeSet); + ctor public GridLayout(android.content.Context, android.util.AttributeSet, int); + ctor public GridLayout(android.content.Context, android.util.AttributeSet, int, int); method public int getAlignmentMode(); method public int getColumnCount(); method public int getOrientation(); @@ -31419,6 +37283,10 @@ method public void setRowCount(int); method public void setRowOrderPreserved(boolean); method public void setUseDefaultMargins(boolean); + method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment, float); + method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment, float); + method public static android.widget.GridLayout.Spec spec(int, int, float); + method public static android.widget.GridLayout.Spec spec(int, float); method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment); method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment); method public static android.widget.GridLayout.Spec spec(int, int); @@ -31461,6 +37329,7 @@ ctor public GridView(android.content.Context); ctor public GridView(android.content.Context, android.util.AttributeSet); ctor public GridView(android.content.Context, android.util.AttributeSet, int); + ctor public GridView(android.content.Context, android.util.AttributeSet, int, int); method public android.widget.ListAdapter getAdapter(); method public int getColumnWidth(); method public int getGravity(); @@ -31518,6 +37387,7 @@ ctor public HorizontalScrollView(android.content.Context); ctor public HorizontalScrollView(android.content.Context, android.util.AttributeSet); ctor public HorizontalScrollView(android.content.Context, android.util.AttributeSet, int); + ctor public HorizontalScrollView(android.content.Context, android.util.AttributeSet, int, int); method public boolean arrowScroll(int); method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect); method public boolean executeKeyEvent(android.view.KeyEvent); @@ -31537,6 +37407,7 @@ ctor public ImageButton(android.content.Context); ctor public ImageButton(android.content.Context, android.util.AttributeSet); ctor public ImageButton(android.content.Context, android.util.AttributeSet, int); + ctor public ImageButton(android.content.Context, android.util.AttributeSet, int, int); } public class ImageSwitcher extends android.widget.ViewSwitcher { @@ -31551,6 +37422,7 @@ ctor public ImageView(android.content.Context); ctor public ImageView(android.content.Context, android.util.AttributeSet); ctor public ImageView(android.content.Context, android.util.AttributeSet, int); + ctor public ImageView(android.content.Context, android.util.AttributeSet, int, int); method public final void clearColorFilter(); method public boolean getAdjustViewBounds(); method public boolean getBaselineAlignBottom(); @@ -31559,6 +37431,8 @@ method public android.graphics.drawable.Drawable getDrawable(); method public int getImageAlpha(); method public android.graphics.Matrix getImageMatrix(); + method public android.content.res.ColorStateList getImageTintList(); + method public android.graphics.PorterDuff.Mode getImageTintMode(); method public int getMaxHeight(); method public int getMaxWidth(); method public android.widget.ImageView.ScaleType getScaleType(); @@ -31579,6 +37453,8 @@ method public void setImageMatrix(android.graphics.Matrix); method public void setImageResource(int); method public void setImageState(int[], boolean); + method public void setImageTintList(android.content.res.ColorStateList); + method public void setImageTintMode(android.graphics.PorterDuff.Mode); method public void setImageURI(android.net.Uri); method public void setMaxHeight(int); method public void setMaxWidth(int); @@ -31602,6 +37478,7 @@ ctor public LinearLayout(android.content.Context); ctor public LinearLayout(android.content.Context, android.util.AttributeSet); ctor public LinearLayout(android.content.Context, android.util.AttributeSet, int); + ctor public LinearLayout(android.content.Context, android.util.AttributeSet, int, int); method public int getBaselineAlignedChildIndex(); method public android.graphics.drawable.Drawable getDividerDrawable(); method public int getDividerPadding(); @@ -31712,6 +37589,7 @@ ctor public ListView(android.content.Context); ctor public ListView(android.content.Context, android.util.AttributeSet); ctor public ListView(android.content.Context, android.util.AttributeSet, int); + ctor public ListView(android.content.Context, android.util.AttributeSet, int, int); method public void addFooterView(android.view.View, java.lang.Object, boolean); method public void addFooterView(android.view.View); method public void addHeaderView(android.view.View, java.lang.Object, boolean); @@ -31741,7 +37619,6 @@ method public void setOverscrollHeader(android.graphics.drawable.Drawable); method public void setSelection(int); method public void setSelectionAfterHeaderView(); - method public void setSelectionFromTop(int, int); method public void smoothScrollByOffset(int); } @@ -31784,6 +37661,7 @@ ctor public MultiAutoCompleteTextView(android.content.Context); ctor public MultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet); ctor public MultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet, int); + ctor public MultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet, int, int); method protected void performFiltering(java.lang.CharSequence, int, int, int); method public void setTokenizer(android.widget.MultiAutoCompleteTextView.Tokenizer); } @@ -31805,6 +37683,7 @@ ctor public NumberPicker(android.content.Context); ctor public NumberPicker(android.content.Context, android.util.AttributeSet); ctor public NumberPicker(android.content.Context, android.util.AttributeSet, int); + ctor public NumberPicker(android.content.Context, android.util.AttributeSet, int, int); method public java.lang.String[] getDisplayedValues(); method public int getMaxValue(); method public int getMinValue(); @@ -31898,6 +37777,7 @@ method public int getAnimationStyle(); method public android.graphics.drawable.Drawable getBackground(); method public android.view.View getContentView(); + method public float getElevation(); method public int getHeight(); method public int getInputMethodMode(); method public int getMaxAvailableHeight(android.view.View); @@ -31915,6 +37795,7 @@ method public void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setClippingEnabled(boolean); method public void setContentView(android.view.View); + method public void setElevation(float); method public void setFocusable(boolean); method public void setHeight(int); method public void setIgnoreCheekPress(); @@ -31950,12 +37831,21 @@ ctor public ProgressBar(android.content.Context); ctor public ProgressBar(android.content.Context, android.util.AttributeSet); ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int); + ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int, int); method public android.graphics.drawable.Drawable getIndeterminateDrawable(); + method public android.content.res.ColorStateList getIndeterminateTintList(); + method public android.graphics.PorterDuff.Mode getIndeterminateTintMode(); method public android.view.animation.Interpolator getInterpolator(); method public synchronized int getMax(); method public synchronized int getProgress(); + method public android.content.res.ColorStateList getProgressBackgroundTintList(); + method public android.graphics.PorterDuff.Mode getProgressBackgroundTintMode(); method public android.graphics.drawable.Drawable getProgressDrawable(); + method public android.content.res.ColorStateList getProgressTintList(); + method public android.graphics.PorterDuff.Mode getProgressTintMode(); method public synchronized int getSecondaryProgress(); + method public android.content.res.ColorStateList getSecondaryProgressTintList(); + method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode(); method public final synchronized void incrementProgressBy(int); method public final synchronized void incrementSecondaryProgressBy(int); method public synchronized boolean isIndeterminate(); @@ -31963,18 +37853,29 @@ method public android.os.Parcelable onSaveInstanceState(); method public synchronized void setIndeterminate(boolean); method public void setIndeterminateDrawable(android.graphics.drawable.Drawable); + method public void setIndeterminateDrawableTiled(android.graphics.drawable.Drawable); + method public void setIndeterminateTintList(android.content.res.ColorStateList); + method public void setIndeterminateTintMode(android.graphics.PorterDuff.Mode); method public void setInterpolator(android.content.Context, int); method public void setInterpolator(android.view.animation.Interpolator); method public synchronized void setMax(int); method public synchronized void setProgress(int); + method public void setProgressBackgroundTintList(android.content.res.ColorStateList); + method public void setProgressBackgroundTintMode(android.graphics.PorterDuff.Mode); method public void setProgressDrawable(android.graphics.drawable.Drawable); + method public void setProgressDrawableTiled(android.graphics.drawable.Drawable); + method public void setProgressTintList(android.content.res.ColorStateList); + method public void setProgressTintMode(android.graphics.PorterDuff.Mode); method public synchronized void setSecondaryProgress(int); + method public void setSecondaryProgressTintList(android.content.res.ColorStateList); + method public void setSecondaryProgressTintMode(android.graphics.PorterDuff.Mode); } public class QuickContactBadge extends android.widget.ImageView implements android.view.View.OnClickListener { ctor public QuickContactBadge(android.content.Context); ctor public QuickContactBadge(android.content.Context, android.util.AttributeSet); ctor public QuickContactBadge(android.content.Context, android.util.AttributeSet, int); + ctor public QuickContactBadge(android.content.Context, android.util.AttributeSet, int, int); method public void assignContactFromEmail(java.lang.String, boolean); method public void assignContactFromEmail(java.lang.String, boolean, android.os.Bundle); method public void assignContactFromPhone(java.lang.String, boolean); @@ -31984,6 +37885,7 @@ method public void setExcludeMimes(java.lang.String[]); method public void setImageToDefault(); method public void setMode(int); + method public void setOverlay(android.graphics.drawable.Drawable); field protected java.lang.String[] mExcludeMimes; } @@ -31991,6 +37893,7 @@ ctor public RadioButton(android.content.Context); ctor public RadioButton(android.content.Context, android.util.AttributeSet); ctor public RadioButton(android.content.Context, android.util.AttributeSet, int); + ctor public RadioButton(android.content.Context, android.util.AttributeSet, int, int); } public class RadioGroup extends android.widget.LinearLayout { @@ -32016,6 +37919,7 @@ public class RatingBar extends android.widget.AbsSeekBar { ctor public RatingBar(android.content.Context, android.util.AttributeSet, int); + ctor public RatingBar(android.content.Context, android.util.AttributeSet, int, int); ctor public RatingBar(android.content.Context, android.util.AttributeSet); ctor public RatingBar(android.content.Context); method public int getNumStars(); @@ -32038,6 +37942,7 @@ ctor public RelativeLayout(android.content.Context); ctor public RelativeLayout(android.content.Context, android.util.AttributeSet); ctor public RelativeLayout(android.content.Context, android.util.AttributeSet, int); + ctor public RelativeLayout(android.content.Context, android.util.AttributeSet, int, int); method public int getGravity(); method protected void onLayout(boolean, int, int, int, int); method public void setGravity(int); @@ -32186,6 +38091,7 @@ ctor public ScrollView(android.content.Context); ctor public ScrollView(android.content.Context, android.util.AttributeSet); ctor public ScrollView(android.content.Context, android.util.AttributeSet, int); + ctor public ScrollView(android.content.Context, android.util.AttributeSet, int, int); method public boolean arrowScroll(int); method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect); method public boolean executeKeyEvent(android.view.KeyEvent); @@ -32230,6 +38136,8 @@ public class SearchView extends android.widget.LinearLayout implements android.view.CollapsibleActionView { ctor public SearchView(android.content.Context); ctor public SearchView(android.content.Context, android.util.AttributeSet); + ctor public SearchView(android.content.Context, android.util.AttributeSet, int); + ctor public SearchView(android.content.Context, android.util.AttributeSet, int, int); method public int getImeOptions(); method public int getInputType(); method public int getMaxWidth(); @@ -32284,6 +38192,7 @@ ctor public SeekBar(android.content.Context); ctor public SeekBar(android.content.Context, android.util.AttributeSet); ctor public SeekBar(android.content.Context, android.util.AttributeSet, int); + ctor public SeekBar(android.content.Context, android.util.AttributeSet, int, int); method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener); } @@ -32385,6 +38294,7 @@ public deprecated class SlidingDrawer extends android.view.ViewGroup { ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet); ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet, int); + ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet, int, int); method public void animateClose(); method public void animateOpen(); method public void animateToggle(); @@ -32419,6 +38329,7 @@ } public final class Space extends android.view.View { + ctor public Space(android.content.Context, android.util.AttributeSet, int, int); ctor public Space(android.content.Context, android.util.AttributeSet, int); ctor public Space(android.content.Context, android.util.AttributeSet); ctor public Space(android.content.Context); @@ -32430,6 +38341,7 @@ ctor public Spinner(android.content.Context, android.util.AttributeSet); ctor public Spinner(android.content.Context, android.util.AttributeSet, int); ctor public Spinner(android.content.Context, android.util.AttributeSet, int, int); + ctor public Spinner(android.content.Context, android.util.AttributeSet, int, int, int); method public int getDropDownHorizontalOffset(); method public int getDropDownVerticalOffset(); method public int getDropDownWidth(); @@ -32457,12 +38369,16 @@ ctor public StackView(android.content.Context); ctor public StackView(android.content.Context, android.util.AttributeSet); ctor public StackView(android.content.Context, android.util.AttributeSet, int); + ctor public StackView(android.content.Context, android.util.AttributeSet, int, int); } public class Switch extends android.widget.CompoundButton { ctor public Switch(android.content.Context); ctor public Switch(android.content.Context, android.util.AttributeSet); ctor public Switch(android.content.Context, android.util.AttributeSet, int); + ctor public Switch(android.content.Context, android.util.AttributeSet, int, int); + method public boolean getShowText(); + method public boolean getSplitTrack(); method public int getSwitchMinWidth(); method public int getSwitchPadding(); method public java.lang.CharSequence getTextOff(); @@ -32471,6 +38387,8 @@ method public int getThumbTextPadding(); method public android.graphics.drawable.Drawable getTrackDrawable(); method public void onMeasure(int, int); + method public void setShowText(boolean); + method public void setSplitTrack(boolean); method public void setSwitchMinWidth(int); method public void setSwitchPadding(int); method public void setSwitchTextAppearance(android.content.Context, int); @@ -32488,6 +38406,8 @@ public class TabHost extends android.widget.FrameLayout implements android.view.ViewTreeObserver.OnTouchModeChangeListener { ctor public TabHost(android.content.Context); ctor public TabHost(android.content.Context, android.util.AttributeSet); + ctor public TabHost(android.content.Context, android.util.AttributeSet, int); + ctor public TabHost(android.content.Context, android.util.AttributeSet, int, int); method public void addTab(android.widget.TabHost.TabSpec); method public void clearAllTabs(); method public int getCurrentTab(); @@ -32527,6 +38447,7 @@ ctor public TabWidget(android.content.Context); ctor public TabWidget(android.content.Context, android.util.AttributeSet); ctor public TabWidget(android.content.Context, android.util.AttributeSet, int); + ctor public TabWidget(android.content.Context, android.util.AttributeSet, int, int); method public void dispatchDraw(android.graphics.Canvas); method public void focusCurrentTab(int); method public android.view.View getChildTabViewAt(int); @@ -32589,6 +38510,7 @@ ctor public TextClock(android.content.Context); ctor public TextClock(android.content.Context, android.util.AttributeSet); ctor public TextClock(android.content.Context, android.util.AttributeSet, int); + ctor public TextClock(android.content.Context, android.util.AttributeSet, int, int); method public java.lang.CharSequence getFormat12Hour(); method public java.lang.CharSequence getFormat24Hour(); method public java.lang.String getTimeZone(); @@ -32611,6 +38533,7 @@ ctor public TextView(android.content.Context); ctor public TextView(android.content.Context, android.util.AttributeSet); ctor public TextView(android.content.Context, android.util.AttributeSet, int); + ctor public TextView(android.content.Context, android.util.AttributeSet, int, int); method public void addTextChangedListener(android.text.TextWatcher); method public final void append(java.lang.CharSequence); method public void append(java.lang.CharSequence, int, int); @@ -32642,6 +38565,7 @@ method public int getExtendedPaddingBottom(); method public int getExtendedPaddingTop(); method public android.text.InputFilter[] getFilters(); + method public java.lang.String getFontFeatureSettings(); method public boolean getFreezesText(); method public int getGravity(); method public int getHighlightColor(); @@ -32655,6 +38579,7 @@ method public int getInputType(); method public final android.text.method.KeyListener getKeyListener(); method public final android.text.Layout getLayout(); + method public float getLetterSpacing(); method public int getLineBounds(int, android.graphics.Rect); method public int getLineCount(); method public int getLineHeight(); @@ -32682,10 +38607,9 @@ method public float getShadowDx(); method public float getShadowDy(); method public float getShadowRadius(); + method public final boolean getShowSoftInputOnFocus(); method public java.lang.CharSequence getText(); - method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int); method public final android.content.res.ColorStateList getTextColors(); - method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray); method public java.util.Locale getTextLocale(); method public float getTextScaleX(); method public float getTextSize(); @@ -32730,12 +38654,14 @@ method public void setCursorVisible(boolean); method public void setCustomSelectionActionModeCallback(android.view.ActionMode.Callback); method public final void setEditableFactory(android.text.Editable.Factory); + method public void setElegantTextHeight(boolean); method public void setEllipsize(android.text.TextUtils.TruncateAt); method public void setEms(int); method public void setError(java.lang.CharSequence); method public void setError(java.lang.CharSequence, android.graphics.drawable.Drawable); method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); + method public void setFontFeatureSettings(java.lang.String); method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); @@ -32752,6 +38678,7 @@ method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public void setInputType(int); method public void setKeyListener(android.text.method.KeyListener); + method public void setLetterSpacing(float); method public void setLineSpacing(float, float); method public void setLines(int); method public final void setLinkTextColor(int); @@ -32774,6 +38701,7 @@ method public void setScroller(android.widget.Scroller); method public void setSelectAllOnFocus(boolean); method public void setShadowLayer(float, float, float, int); + method public final void setShowSoftInputOnFocus(boolean); method public void setSingleLine(); method public void setSingleLine(boolean); method public final void setSpannableFactory(android.text.Spannable.Factory); @@ -32818,6 +38746,7 @@ ctor public TimePicker(android.content.Context); ctor public TimePicker(android.content.Context, android.util.AttributeSet); ctor public TimePicker(android.content.Context, android.util.AttributeSet, int); + ctor public TimePicker(android.content.Context, android.util.AttributeSet, int, int); method public java.lang.Integer getCurrentHour(); method public java.lang.Integer getCurrentMinute(); method public boolean is24HourView(); @@ -32855,6 +38784,7 @@ } public class ToggleButton extends android.widget.CompoundButton { + ctor public ToggleButton(android.content.Context, android.util.AttributeSet, int, int); ctor public ToggleButton(android.content.Context, android.util.AttributeSet, int); ctor public ToggleButton(android.content.Context, android.util.AttributeSet); ctor public ToggleButton(android.content.Context); @@ -32864,10 +38794,74 @@ method public void setTextOn(java.lang.CharSequence); } + public class Toolbar extends android.view.ViewGroup { + ctor public Toolbar(android.content.Context); + ctor public Toolbar(android.content.Context, android.util.AttributeSet); + ctor public Toolbar(android.content.Context, android.util.AttributeSet, int); + ctor public Toolbar(android.content.Context, android.util.AttributeSet, int, int); + method public void collapseActionView(); + method public void dismissPopupMenus(); + method public int getContentInsetEnd(); + method public int getContentInsetLeft(); + method public int getContentInsetRight(); + method public int getContentInsetStart(); + method public android.graphics.drawable.Drawable getLogo(); + method public java.lang.CharSequence getLogoDescription(); + method public android.view.Menu getMenu(); + method public java.lang.CharSequence getNavigationContentDescription(); + method public android.graphics.drawable.Drawable getNavigationIcon(); + method public int getPopupTheme(); + method public java.lang.CharSequence getSubtitle(); + method public java.lang.CharSequence getTitle(); + method public boolean hasExpandedActionView(); + method public boolean hideOverflowMenu(); + method public void inflateMenu(int); + method public boolean isOverflowMenuShowing(); + method protected void onLayout(boolean, int, int, int, int); + method public void setContentInsetsAbsolute(int, int); + method public void setContentInsetsRelative(int, int); + method public void setLogo(int); + method public void setLogo(android.graphics.drawable.Drawable); + method public void setLogoDescription(int); + method public void setLogoDescription(java.lang.CharSequence); + method public void setNavigationContentDescription(int); + method public void setNavigationContentDescription(java.lang.CharSequence); + method public void setNavigationIcon(int); + method public void setNavigationIcon(android.graphics.drawable.Drawable); + method public void setNavigationOnClickListener(android.view.View.OnClickListener); + method public void setOnMenuItemClickListener(android.widget.Toolbar.OnMenuItemClickListener); + method public void setPopupTheme(int); + method public void setSubtitle(int); + method public void setSubtitle(java.lang.CharSequence); + method public void setSubtitleTextAppearance(android.content.Context, int); + method public void setSubtitleTextColor(int); + method public void setTitle(int); + method public void setTitle(java.lang.CharSequence); + method public void setTitleTextAppearance(android.content.Context, int); + method public void setTitleTextColor(int); + method public boolean showOverflowMenu(); + } + + public static class Toolbar.LayoutParams extends android.app.ActionBar.LayoutParams { + ctor public Toolbar.LayoutParams(android.content.Context, android.util.AttributeSet); + ctor public Toolbar.LayoutParams(int, int); + ctor public Toolbar.LayoutParams(int, int, int); + ctor public Toolbar.LayoutParams(int); + ctor public Toolbar.LayoutParams(android.widget.Toolbar.LayoutParams); + ctor public Toolbar.LayoutParams(android.app.ActionBar.LayoutParams); + ctor public Toolbar.LayoutParams(android.view.ViewGroup.MarginLayoutParams); + ctor public Toolbar.LayoutParams(android.view.ViewGroup.LayoutParams); + } + + public static abstract interface Toolbar.OnMenuItemClickListener { + method public abstract boolean onMenuItemClick(android.view.MenuItem); + } + public deprecated class TwoLineListItem extends android.widget.RelativeLayout { ctor public TwoLineListItem(android.content.Context); ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet); ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet, int); + ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet, int, int); method public android.widget.TextView getText1(); method public android.widget.TextView getText2(); } @@ -32876,6 +38870,7 @@ ctor public VideoView(android.content.Context); ctor public VideoView(android.content.Context, android.util.AttributeSet); ctor public VideoView(android.content.Context, android.util.AttributeSet, int); + ctor public VideoView(android.content.Context, android.util.AttributeSet, int, int); method public void addSubtitleSource(java.io.InputStream, android.media.MediaFormat); method public boolean canPause(); method public boolean canSeekBackward(); @@ -32896,6 +38891,7 @@ method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener); method public void setVideoPath(java.lang.String); method public void setVideoURI(android.net.Uri); + method public void setVideoURI(android.net.Uri, java.util.Map<java.lang.String, java.lang.String>); method public void start(); method public void stopPlayback(); method public void suspend(); @@ -32950,6 +38946,7 @@ ctor public ZoomButton(android.content.Context); ctor public ZoomButton(android.content.Context, android.util.AttributeSet); ctor public ZoomButton(android.content.Context, android.util.AttributeSet, int); + ctor public ZoomButton(android.content.Context, android.util.AttributeSet, int, int); method public boolean onLongClick(android.view.View); method public void setZoomSpeed(long); } @@ -36130,8 +42127,8 @@ method public java.lang.annotation.Annotation[] getDeclaredAnnotations(); method public boolean isAccessible(); method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>); - method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean); method public void setAccessible(boolean); + method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean); } public abstract interface AnnotatedElement { @@ -42088,6 +48085,13 @@ method public int getWidth(); } + public class IllformedLocaleException extends java.lang.RuntimeException { + ctor public IllformedLocaleException(); + ctor public IllformedLocaleException(java.lang.String); + ctor public IllformedLocaleException(java.lang.String, int); + method public int getErrorIndex(); + } + public class InputMismatchException extends java.util.NoSuchElementException implements java.io.Serializable { ctor public InputMismatchException(); ctor public InputMismatchException(java.lang.String); @@ -42202,6 +48206,7 @@ ctor public Locale(java.lang.String, java.lang.String); ctor public Locale(java.lang.String, java.lang.String, java.lang.String); method public java.lang.Object clone(); + method public static java.util.Locale forLanguageTag(java.lang.String); method public static java.util.Locale[] getAvailableLocales(); method public java.lang.String getCountry(); method public static java.util.Locale getDefault(); @@ -42211,15 +48216,24 @@ method public java.lang.String getDisplayLanguage(java.util.Locale); method public final java.lang.String getDisplayName(); method public java.lang.String getDisplayName(java.util.Locale); + method public java.lang.String getDisplayScript(); + method public java.lang.String getDisplayScript(java.util.Locale); method public final java.lang.String getDisplayVariant(); method public java.lang.String getDisplayVariant(java.util.Locale); + method public java.lang.String getExtension(char); + method public java.util.Set<java.lang.Character> getExtensionKeys(); method public java.lang.String getISO3Country(); method public java.lang.String getISO3Language(); method public static java.lang.String[] getISOCountries(); method public static java.lang.String[] getISOLanguages(); method public java.lang.String getLanguage(); + method public java.lang.String getScript(); + method public java.util.Set<java.lang.String> getUnicodeLocaleAttributes(); + method public java.util.Set<java.lang.String> getUnicodeLocaleKeys(); + method public java.lang.String getUnicodeLocaleType(java.lang.String); method public java.lang.String getVariant(); method public static synchronized void setDefault(java.util.Locale); + method public java.lang.String toLanguageTag(); method public final java.lang.String toString(); field public static final java.util.Locale CANADA; field public static final java.util.Locale CANADA_FRENCH; @@ -42237,14 +48251,33 @@ field public static final java.util.Locale KOREA; field public static final java.util.Locale KOREAN; field public static final java.util.Locale PRC; + field public static final char PRIVATE_USE_EXTENSION = 120; // 0x0078 'x' field public static final java.util.Locale ROOT; field public static final java.util.Locale SIMPLIFIED_CHINESE; field public static final java.util.Locale TAIWAN; field public static final java.util.Locale TRADITIONAL_CHINESE; field public static final java.util.Locale UK; + field public static final char UNICODE_LOCALE_EXTENSION = 117; // 0x0075 'u' field public static final java.util.Locale US; } + public static final class Locale.Builder { + ctor public Locale.Builder(); + method public java.util.Locale.Builder addUnicodeLocaleAttribute(java.lang.String); + method public java.util.Locale build(); + method public java.util.Locale.Builder clear(); + method public java.util.Locale.Builder clearExtensions(); + method public java.util.Locale.Builder removeUnicodeLocaleAttribute(java.lang.String); + method public java.util.Locale.Builder setExtension(char, java.lang.String); + method public java.util.Locale.Builder setLanguage(java.lang.String); + method public java.util.Locale.Builder setLanguageTag(java.lang.String); + method public java.util.Locale.Builder setLocale(java.util.Locale); + method public java.util.Locale.Builder setRegion(java.lang.String); + method public java.util.Locale.Builder setScript(java.lang.String); + method public java.util.Locale.Builder setUnicodeLocaleKeyword(java.lang.String, java.lang.String); + method public java.util.Locale.Builder setVariant(java.lang.String); + } + public abstract interface Map { method public abstract void clear(); method public abstract boolean containsKey(java.lang.Object); @@ -42931,6 +48964,35 @@ method public V replace(K, V); } + public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable { + ctor public ConcurrentLinkedDeque(); + ctor public ConcurrentLinkedDeque(java.util.Collection<? extends E>); + method public void addFirst(E); + method public void addLast(E); + method public java.util.Iterator<E> descendingIterator(); + method public E element(); + method public E getFirst(); + method public E getLast(); + method public java.util.Iterator<E> iterator(); + method public boolean offer(E); + method public boolean offerFirst(E); + method public boolean offerLast(E); + method public E peek(); + method public E peekFirst(); + method public E peekLast(); + method public E poll(); + method public E pollFirst(); + method public E pollLast(); + method public E pop(); + method public void push(E); + method public E remove(); + method public E removeFirst(); + method public boolean removeFirstOccurrence(java.lang.Object); + method public E removeLast(); + method public boolean removeLastOccurrence(java.lang.Object); + method public int size(); + } + public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable { ctor public ConcurrentLinkedQueue(); ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>); @@ -43171,6 +49233,94 @@ method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService); } + public class ForkJoinPool extends java.util.concurrent.AbstractExecutorService { + ctor public ForkJoinPool(); + ctor public ForkJoinPool(int); + ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean); + method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit); + method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>); + method public void execute(java.util.concurrent.ForkJoinTask<?>); + method public void execute(java.lang.Runnable); + method public int getActiveThreadCount(); + method public boolean getAsyncMode(); + method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory(); + method public int getParallelism(); + method public int getPoolSize(); + method public int getQueuedSubmissionCount(); + method public long getQueuedTaskCount(); + method public int getRunningThreadCount(); + method public long getStealCount(); + method public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler(); + method public boolean hasQueuedSubmissions(); + method public T invoke(java.util.concurrent.ForkJoinTask<T>); + method public boolean isQuiescent(); + method public boolean isShutdown(); + method public boolean isTerminated(); + method public boolean isTerminating(); + method public static void managedBlock(java.util.concurrent.ForkJoinPool.ManagedBlocker) throws java.lang.InterruptedException; + method protected java.util.concurrent.ForkJoinTask<?> pollSubmission(); + method public void shutdown(); + method public java.util.List<java.lang.Runnable> shutdownNow(); + method public java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>); + field public static final java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory; + } + + public static abstract interface ForkJoinPool.ForkJoinWorkerThreadFactory { + method public abstract java.util.concurrent.ForkJoinWorkerThread newThread(java.util.concurrent.ForkJoinPool); + } + + public static abstract interface ForkJoinPool.ManagedBlocker { + method public abstract boolean block() throws java.lang.InterruptedException; + method public abstract boolean isReleasable(); + } + + public abstract class ForkJoinTask implements java.util.concurrent.Future java.io.Serializable { + ctor public ForkJoinTask(); + method public static java.util.concurrent.ForkJoinTask<?> adapt(java.lang.Runnable); + method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T); + method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>); + method public boolean cancel(boolean); + method public void complete(V); + method public void completeExceptionally(java.lang.Throwable); + method protected abstract boolean exec(); + method public final java.util.concurrent.ForkJoinTask<V> fork(); + method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; + method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; + method public final java.lang.Throwable getException(); + method public static java.util.concurrent.ForkJoinPool getPool(); + method public static int getQueuedTaskCount(); + method public abstract V getRawResult(); + method public static int getSurplusQueuedTaskCount(); + method public static void helpQuiesce(); + method public static boolean inForkJoinPool(); + method public final V invoke(); + method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>, java.util.concurrent.ForkJoinTask<?>); + method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>...); + method public static java.util.Collection<T> invokeAll(java.util.Collection<T>); + method public final boolean isCancelled(); + method public final boolean isCompletedAbnormally(); + method public final boolean isCompletedNormally(); + method public final boolean isDone(); + method public final V join(); + method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask(); + method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask(); + method protected static java.util.concurrent.ForkJoinTask<?> pollTask(); + method public final void quietlyInvoke(); + method public final void quietlyJoin(); + method public void reinitialize(); + method protected abstract void setRawResult(V); + method public boolean tryUnfork(); + } + + public class ForkJoinWorkerThread extends java.lang.Thread { + ctor protected ForkJoinWorkerThread(java.util.concurrent.ForkJoinPool); + method public java.util.concurrent.ForkJoinPool getPool(); + method public int getPoolIndex(); + method protected void onStart(); + method protected void onTermination(java.lang.Throwable); + } + public abstract interface Future { method public abstract boolean cancel(boolean); method public abstract V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; @@ -43255,6 +49405,52 @@ method public E take() throws java.lang.InterruptedException; } + public class LinkedTransferQueue extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue { + ctor public LinkedTransferQueue(); + ctor public LinkedTransferQueue(java.util.Collection<? extends E>); + method public int drainTo(java.util.Collection<? super E>); + method public int drainTo(java.util.Collection<? super E>, int); + method public int getWaitingConsumerCount(); + method public boolean hasWaitingConsumer(); + method public java.util.Iterator<E> iterator(); + method public boolean offer(E, long, java.util.concurrent.TimeUnit); + method public boolean offer(E); + method public E peek(); + method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public E poll(); + method public void put(E); + method public int remainingCapacity(); + method public int size(); + method public E take() throws java.lang.InterruptedException; + method public void transfer(E) throws java.lang.InterruptedException; + method public boolean tryTransfer(E); + method public boolean tryTransfer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + } + + public class Phaser { + ctor public Phaser(); + ctor public Phaser(int); + ctor public Phaser(java.util.concurrent.Phaser); + ctor public Phaser(java.util.concurrent.Phaser, int); + method public int arrive(); + method public int arriveAndAwaitAdvance(); + method public int arriveAndDeregister(); + method public int awaitAdvance(int); + method public int awaitAdvanceInterruptibly(int) throws java.lang.InterruptedException; + method public int awaitAdvanceInterruptibly(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException; + method public int bulkRegister(int); + method public void forceTermination(); + method public int getArrivedParties(); + method public java.util.concurrent.Phaser getParent(); + method public final int getPhase(); + method public int getRegisteredParties(); + method public java.util.concurrent.Phaser getRoot(); + method public int getUnarrivedParties(); + method public boolean isTerminated(); + method protected boolean onAdvance(int, int); + method public int register(); + } + public class PriorityBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable { ctor public PriorityBlockingQueue(); ctor public PriorityBlockingQueue(int); @@ -43275,6 +49471,22 @@ method public E take() throws java.lang.InterruptedException; } + public abstract class RecursiveAction extends java.util.concurrent.ForkJoinTask { + ctor public RecursiveAction(); + method protected abstract void compute(); + method protected final boolean exec(); + method public final java.lang.Void getRawResult(); + method protected final void setRawResult(java.lang.Void); + } + + public abstract class RecursiveTask extends java.util.concurrent.ForkJoinTask { + ctor public RecursiveTask(); + method protected abstract V compute(); + method protected final boolean exec(); + method public final V getRawResult(); + method protected final void setRawResult(V); + } + public class RejectedExecutionException extends java.lang.RuntimeException { ctor public RejectedExecutionException(); ctor public RejectedExecutionException(java.lang.String); @@ -43313,12 +49525,14 @@ method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>); method public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy(); method public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy(); + method public boolean getRemoveOnCancelPolicy(); method public java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit); method public java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit); method public java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit); method public java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit); method public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean); method public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean); + method public void setRemoveOnCancelPolicy(boolean); } public class Semaphore implements java.io.Serializable { @@ -43364,6 +49578,15 @@ method public abstract java.lang.Thread newThread(java.lang.Runnable); } + public class ThreadLocalRandom extends java.util.Random { + method public static java.util.concurrent.ThreadLocalRandom current(); + method public double nextDouble(double); + method public double nextDouble(double, double); + method public int nextInt(int, int); + method public long nextLong(long); + method public long nextLong(long, long); + } + public class ThreadPoolExecutor extends java.util.concurrent.AbstractExecutorService { ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>); ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>, java.util.concurrent.ThreadFactory); @@ -43451,6 +49674,14 @@ ctor public TimeoutException(java.lang.String); } + public abstract interface TransferQueue implements java.util.concurrent.BlockingQueue { + method public abstract int getWaitingConsumerCount(); + method public abstract boolean hasWaitingConsumer(); + method public abstract void transfer(E) throws java.lang.InterruptedException; + method public abstract boolean tryTransfer(E); + method public abstract boolean tryTransfer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + } + } package java.util.concurrent.atomic { @@ -43660,6 +49891,7 @@ method public final int getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject); method public final java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject); method public final boolean hasContended(); + method public final boolean hasQueuedPredecessors(); method public final boolean hasQueuedThreads(); method public final boolean hasWaiters(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject); method protected boolean isHeldExclusively(); @@ -43706,6 +49938,7 @@ method public final int getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject); method public final java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject); method public final boolean hasContended(); + method public final boolean hasQueuedPredecessors(); method public final boolean hasQueuedThreads(); method public final boolean hasWaiters(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject); method protected boolean isHeldExclusively(); @@ -44595,7 +50828,47 @@ method public void setMethod(int); method public void setSize(long); method public void setTime(long); + field public static final int CENATT = 36; // 0x24 + field public static final int CENATX = 38; // 0x26 + field public static final int CENCOM = 32; // 0x20 + field public static final int CENCRC = 16; // 0x10 + field public static final int CENDSK = 34; // 0x22 + field public static final int CENEXT = 30; // 0x1e + field public static final int CENFLG = 8; // 0x8 + field public static final int CENHDR = 46; // 0x2e + field public static final int CENHOW = 10; // 0xa + field public static final int CENLEN = 24; // 0x18 + field public static final int CENNAM = 28; // 0x1c + field public static final int CENOFF = 42; // 0x2a + field public static final long CENSIG = 33639248L; // 0x2014b50L + field public static final int CENSIZ = 20; // 0x14 + field public static final int CENTIM = 12; // 0xc + field public static final int CENVEM = 4; // 0x4 + field public static final int CENVER = 6; // 0x6 field public static final int DEFLATED = 8; // 0x8 + field public static final int ENDCOM = 20; // 0x14 + field public static final int ENDHDR = 22; // 0x16 + field public static final int ENDOFF = 16; // 0x10 + field public static final long ENDSIG = 101010256L; // 0x6054b50L + field public static final int ENDSIZ = 12; // 0xc + field public static final int ENDSUB = 8; // 0x8 + field public static final int ENDTOT = 10; // 0xa + field public static final int EXTCRC = 4; // 0x4 + field public static final int EXTHDR = 16; // 0x10 + field public static final int EXTLEN = 12; // 0xc + field public static final long EXTSIG = 134695760L; // 0x8074b50L + field public static final int EXTSIZ = 8; // 0x8 + field public static final int LOCCRC = 14; // 0xe + field public static final int LOCEXT = 28; // 0x1c + field public static final int LOCFLG = 6; // 0x6 + field public static final int LOCHDR = 30; // 0x1e + field public static final int LOCHOW = 8; // 0x8 + field public static final int LOCLEN = 22; // 0x16 + field public static final int LOCNAM = 26; // 0x1a + field public static final long LOCSIG = 67324752L; // 0x4034b50L + field public static final int LOCSIZ = 18; // 0x12 + field public static final int LOCTIM = 10; // 0xa + field public static final int LOCVER = 4; // 0x4 field public static final int STORED = 0; // 0x0 } @@ -44619,6 +50892,46 @@ method public java.io.InputStream getInputStream(java.util.zip.ZipEntry) throws java.io.IOException; method public java.lang.String getName(); method public int size(); + field public static final int CENATT = 36; // 0x24 + field public static final int CENATX = 38; // 0x26 + field public static final int CENCOM = 32; // 0x20 + field public static final int CENCRC = 16; // 0x10 + field public static final int CENDSK = 34; // 0x22 + field public static final int CENEXT = 30; // 0x1e + field public static final int CENFLG = 8; // 0x8 + field public static final int CENHDR = 46; // 0x2e + field public static final int CENHOW = 10; // 0xa + field public static final int CENLEN = 24; // 0x18 + field public static final int CENNAM = 28; // 0x1c + field public static final int CENOFF = 42; // 0x2a + field public static final long CENSIG = 33639248L; // 0x2014b50L + field public static final int CENSIZ = 20; // 0x14 + field public static final int CENTIM = 12; // 0xc + field public static final int CENVEM = 4; // 0x4 + field public static final int CENVER = 6; // 0x6 + field public static final int ENDCOM = 20; // 0x14 + field public static final int ENDHDR = 22; // 0x16 + field public static final int ENDOFF = 16; // 0x10 + field public static final long ENDSIG = 101010256L; // 0x6054b50L + field public static final int ENDSIZ = 12; // 0xc + field public static final int ENDSUB = 8; // 0x8 + field public static final int ENDTOT = 10; // 0xa + field public static final int EXTCRC = 4; // 0x4 + field public static final int EXTHDR = 16; // 0x10 + field public static final int EXTLEN = 12; // 0xc + field public static final long EXTSIG = 134695760L; // 0x8074b50L + field public static final int EXTSIZ = 8; // 0x8 + field public static final int LOCCRC = 14; // 0xe + field public static final int LOCEXT = 28; // 0x1c + field public static final int LOCFLG = 6; // 0x6 + field public static final int LOCHDR = 30; // 0x1e + field public static final int LOCHOW = 8; // 0x8 + field public static final int LOCLEN = 22; // 0x16 + field public static final int LOCNAM = 26; // 0x1a + field public static final long LOCSIG = 67324752L; // 0x4034b50L + field public static final int LOCSIZ = 18; // 0x12 + field public static final int LOCTIM = 10; // 0xa + field public static final int LOCVER = 4; // 0x4 field public static final int OPEN_DELETE = 4; // 0x4 field public static final int OPEN_READ = 1; // 0x1 } @@ -44628,6 +50941,46 @@ method public void closeEntry() throws java.io.IOException; method protected java.util.zip.ZipEntry createZipEntry(java.lang.String); method public java.util.zip.ZipEntry getNextEntry() throws java.io.IOException; + field public static final int CENATT = 36; // 0x24 + field public static final int CENATX = 38; // 0x26 + field public static final int CENCOM = 32; // 0x20 + field public static final int CENCRC = 16; // 0x10 + field public static final int CENDSK = 34; // 0x22 + field public static final int CENEXT = 30; // 0x1e + field public static final int CENFLG = 8; // 0x8 + field public static final int CENHDR = 46; // 0x2e + field public static final int CENHOW = 10; // 0xa + field public static final int CENLEN = 24; // 0x18 + field public static final int CENNAM = 28; // 0x1c + field public static final int CENOFF = 42; // 0x2a + field public static final long CENSIG = 33639248L; // 0x2014b50L + field public static final int CENSIZ = 20; // 0x14 + field public static final int CENTIM = 12; // 0xc + field public static final int CENVEM = 4; // 0x4 + field public static final int CENVER = 6; // 0x6 + field public static final int ENDCOM = 20; // 0x14 + field public static final int ENDHDR = 22; // 0x16 + field public static final int ENDOFF = 16; // 0x10 + field public static final long ENDSIG = 101010256L; // 0x6054b50L + field public static final int ENDSIZ = 12; // 0xc + field public static final int ENDSUB = 8; // 0x8 + field public static final int ENDTOT = 10; // 0xa + field public static final int EXTCRC = 4; // 0x4 + field public static final int EXTHDR = 16; // 0x10 + field public static final int EXTLEN = 12; // 0xc + field public static final long EXTSIG = 134695760L; // 0x8074b50L + field public static final int EXTSIZ = 8; // 0x8 + field public static final int LOCCRC = 14; // 0xe + field public static final int LOCEXT = 28; // 0x1c + field public static final int LOCFLG = 6; // 0x6 + field public static final int LOCHDR = 30; // 0x1e + field public static final int LOCHOW = 8; // 0x8 + field public static final int LOCLEN = 22; // 0x16 + field public static final int LOCNAM = 26; // 0x1a + field public static final long LOCSIG = 67324752L; // 0x4034b50L + field public static final int LOCSIZ = 18; // 0x12 + field public static final int LOCTIM = 10; // 0xa + field public static final int LOCVER = 4; // 0x4 } public class ZipOutputStream extends java.util.zip.DeflaterOutputStream { @@ -44637,7 +50990,47 @@ method public void setComment(java.lang.String); method public void setLevel(int); method public void setMethod(int); + field public static final int CENATT = 36; // 0x24 + field public static final int CENATX = 38; // 0x26 + field public static final int CENCOM = 32; // 0x20 + field public static final int CENCRC = 16; // 0x10 + field public static final int CENDSK = 34; // 0x22 + field public static final int CENEXT = 30; // 0x1e + field public static final int CENFLG = 8; // 0x8 + field public static final int CENHDR = 46; // 0x2e + field public static final int CENHOW = 10; // 0xa + field public static final int CENLEN = 24; // 0x18 + field public static final int CENNAM = 28; // 0x1c + field public static final int CENOFF = 42; // 0x2a + field public static final long CENSIG = 33639248L; // 0x2014b50L + field public static final int CENSIZ = 20; // 0x14 + field public static final int CENTIM = 12; // 0xc + field public static final int CENVEM = 4; // 0x4 + field public static final int CENVER = 6; // 0x6 field public static final int DEFLATED = 8; // 0x8 + field public static final int ENDCOM = 20; // 0x14 + field public static final int ENDHDR = 22; // 0x16 + field public static final int ENDOFF = 16; // 0x10 + field public static final long ENDSIG = 101010256L; // 0x6054b50L + field public static final int ENDSIZ = 12; // 0xc + field public static final int ENDSUB = 8; // 0x8 + field public static final int ENDTOT = 10; // 0xa + field public static final int EXTCRC = 4; // 0x4 + field public static final int EXTHDR = 16; // 0x10 + field public static final int EXTLEN = 12; // 0xc + field public static final long EXTSIG = 134695760L; // 0x8074b50L + field public static final int EXTSIZ = 8; // 0x8 + field public static final int LOCCRC = 14; // 0xe + field public static final int LOCEXT = 28; // 0x1c + field public static final int LOCFLG = 6; // 0x6 + field public static final int LOCHDR = 30; // 0x1e + field public static final int LOCHOW = 8; // 0x8 + field public static final int LOCLEN = 22; // 0x16 + field public static final int LOCNAM = 26; // 0x1a + field public static final long LOCSIG = 67324752L; // 0x4034b50L + field public static final int LOCSIZ = 18; // 0x12 + field public static final int LOCTIM = 10; // 0xa + field public static final int LOCVER = 4; // 0x4 field public static final int STORED = 0; // 0x0 }
diff --git a/api/removed.txt b/api/removed.txt new file mode 100644 index 0000000..8972679 --- /dev/null +++ b/api/removed.txt
@@ -0,0 +1,46 @@ +package android.media { + + public class AudioFormat { + ctor public AudioFormat(); + } + +} + +package android.os { + + public final class PowerManager { + method public void goToSleep(long); + method public deprecated void userActivity(long, boolean); + method public void wakeUp(long); + } + + public class UserManager { + method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int); + method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle); + method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle); + } + +} + +package android.view { + + public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback { + method protected void initializeFadingEdge(android.content.res.TypedArray); + method protected void initializeScrollbars(android.content.res.TypedArray); + } + + public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable { + field public static final int TYPE_KEYGUARD = 2004; // 0x7d4 + } + +} + +package android.widget { + + public class TextView extends android.view.View implements android.view.ViewTreeObserver.OnPreDrawListener { + method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int); + method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray); + } + +} +
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index abab094..cc0d51c 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -26,12 +26,19 @@ import android.app.IActivityManager; import android.app.IInstrumentationWatcher; import android.app.Instrumentation; +import android.app.ProfilerInfo; import android.app.UiAutomationConnection; +import android.app.usage.ConfigurationStats; +import android.app.usage.IUsageStatsManager; +import android.app.usage.UsageStatsManager; import android.content.ComponentName; +import android.content.Context; import android.content.IIntentReceiver; import android.content.Intent; import android.content.pm.IPackageManager; +import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.graphics.Rect; import android.net.Uri; import android.os.Binder; @@ -41,10 +48,15 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.text.TextUtils; import android.util.AndroidException; +import android.util.ArrayMap; import android.view.IWindowManager; +import android.view.View; + import com.android.internal.os.BaseCommand; import dalvik.system.VMRuntime; @@ -56,6 +68,9 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; @@ -72,6 +87,8 @@ private String mReceiverPermission; private String mProfileFile; + private int mSamplingInterval; + private boolean mAutoStop; /** * Command-line entry point. @@ -87,7 +104,7 @@ out.println( "usage: am [subcommand] [options]\n" + "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + - " [--R COUNT] [-S] [--opengl-trace]\n" + + " [--sampling INTERVAL] [-R COUNT] [-S] [--opengl-trace]\n" + " [--user <USER_ID> | current] <INTENT>\n" + " am startservice [--user <USER_ID> | current] <INTENT>\n" + " am stopservice [--user <USER_ID> | current] <INTENT>\n" + @@ -115,17 +132,23 @@ " am to-uri [INTENT]\n" + " am to-intent-uri [INTENT]\n" + " am switch-user <USER_ID>\n" + + " am start-user <USER_ID>\n" + " am stop-user <USER_ID>\n" + " am stack start <DISPLAY_ID> <INTENT>\n" + " am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" + " am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" + " am stack list\n" + " am stack info <STACK_ID>\n" + + " am lock-task <TASK_ID>\n" + + " am lock-task stop\n" + + " am get-config\n" + "\n" + "am start: start an Activity. Options are:\n" + " -D: enable debugging\n" + " -W: wait for launch to complete\n" + " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + + " --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" + + " between samples (use with --start-profiler)\n" + " -P <FILE>: like above, but profiling stops when app goes idle\n" + " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" + " the top activity will be finished.\n" + @@ -211,8 +234,11 @@ "am switch-user: switch to put USER_ID in the foreground, starting\n" + " execution of that user if it is currently stopped.\n" + "\n" + + "am start-user: start USER_ID in background if it is currently stopped,\n" + + " use switch-user if you want to start the user in foreground.\n" + + "\n" + "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + - " code until a later explicit switch to it.\n" + + " code until a later explicit start or switch to it.\n" + "\n" + "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" + "\n" + @@ -225,6 +251,11 @@ "\n" + "am stack info: display the information about activity stack <STACK_ID>.\n" + "\n" + + "am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run\n" + + "\n" + + "am get-config: retrieve the configuration and any recent configurations\n" + + " of the device\n" + + "\n" + "<INTENT> specifications include these flags and arguments:\n" + " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" + @@ -239,8 +270,11 @@ " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" + " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" + " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" + + " [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]\n" + + " (to embed a comma into a string escape it using \"\\,\")\n" + " [-n <COMPONENT>] [-f <FLAGS>]\n" + " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" + + " [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]\n" + " [--debug-log-resolution] [--exclude-stopped-packages]\n" + " [--include-stopped-packages]\n" + " [--activity-brought-to-front] [--activity-clear-top]\n" + @@ -310,10 +344,16 @@ runToUri(true); } else if (op.equals("switch-user")) { runSwitchUser(); + } else if (op.equals("start-user")) { + runStartUserInBackground(); } else if (op.equals("stop-user")) { runStopUser(); } else if (op.equals("stack")) { runStack(); + } else if (op.equals("lock-task")) { + runLockTask(); + } else if (op.equals("get-config")) { + runGetConfig(); } else { showError("Error: unknown command '" + op + "'"); } @@ -341,6 +381,8 @@ mStopOption = false; mRepeat = 0; mProfileFile = null; + mSamplingInterval = 0; + mAutoStop = false; mUserId = defUser; Uri data = null; String type = null; @@ -426,6 +468,15 @@ } intent.putExtra(key, list); hasIntentInfo = true; + } else if (opt.equals("--esa")) { + String key = nextArgRequired(); + String value = nextArgRequired(); + // Split on commas unless they are preceeded by an escape. + // The escape character must be escaped for the string and + // again for the regex, thus four escape characters become one. + String[] strings = value.split("(?<!\\\\),"); + intent.putExtra(key, strings); + hasIntentInfo = true; } else if (opt.equals("--ez")) { String key = nextArgRequired(); String value = nextArgRequired(); @@ -445,6 +496,10 @@ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else if (opt.equals("--grant-write-uri-permission")) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } else if (opt.equals("--grant-persistable-uri-permission")) { + intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); + } else if (opt.equals("--grant-prefix-uri-permission")) { + intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); } else if (opt.equals("--exclude-stopped-packages")) { intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); } else if (opt.equals("--include-stopped-packages")) { @@ -494,10 +549,12 @@ mWaitOption = true; } else if (opt.equals("-P")) { mProfileFile = nextArgRequired(); - mStartFlags |= ActivityManager.START_FLAG_AUTO_STOP_PROFILER; + mAutoStop = true; } else if (opt.equals("--start-profiler")) { mProfileFile = nextArgRequired(); - mStartFlags &= ~ActivityManager.START_FLAG_AUTO_STOP_PROFILER; + mAutoStop = false; + } else if (opt.equals("--sampling")) { + mSamplingInterval = Integer.parseInt(nextArgRequired()); } else if (opt.equals("-R")) { mRepeat = Integer.parseInt(nextArgRequired()); } else if (opt.equals("-S")) { @@ -653,12 +710,13 @@ mAm.forceStopPackage(packageName, mUserId); Thread.sleep(250); } - + System.out.println("Starting: " + intent); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - + ParcelFileDescriptor fd = null; - + ProfilerInfo profilerInfo = null; + if (mProfileFile != null) { try { fd = ParcelFileDescriptor.open( @@ -670,18 +728,21 @@ System.err.println("Error: Unable to open file: " + mProfileFile); return; } + profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop); } IActivityManager.WaitResult result = null; int res; + final long startTime = SystemClock.uptimeMillis(); if (mWaitOption) { result = mAm.startActivityAndWait(null, null, intent, mimeType, - null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId); + null, null, 0, mStartFlags, profilerInfo, null, mUserId); res = result.result; } else { res = mAm.startActivityAsUser(null, null, intent, mimeType, - null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId); + null, null, 0, mStartFlags, profilerInfo, null, mUserId); } + final long endTime = SystemClock.uptimeMillis(); PrintStream out = mWaitOption ? System.out : System.err; boolean launched = false; switch (res) { @@ -734,6 +795,11 @@ "Error: Activity not started, you do not " + "have permission to access it."); break; + case ActivityManager.START_NOT_VOICE_COMPATIBLE: + out.println( + "Error: Activity not started, voice control not allowed for: " + + intent); + break; default: out.println( "Error: Activity not started, unknown error code " + res); @@ -754,6 +820,7 @@ if (result.totalTime >= 0) { System.out.println("TotalTime: " + result.totalTime); } + System.out.println("WaitTime: " + (endTime-startTime)); System.out.println("Complete"); } mRepeat--; @@ -798,7 +865,7 @@ } private void sendBroadcast() throws Exception { - Intent intent = makeIntent(UserHandle.USER_ALL); + Intent intent = makeIntent(UserHandle.USER_CURRENT); IntentReceiver receiver = new IntentReceiver(); System.out.println("Broadcasting: " + intent); mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission, @@ -882,8 +949,7 @@ } } - if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, - abi)) { + if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, abi)) { throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); } @@ -906,7 +972,7 @@ SystemProperties.set("dalvik.vm.extra-opts", props); } } - + private void runProfile() throws Exception { String profileFile = null; boolean start = false; @@ -960,6 +1026,7 @@ } ParcelFileDescriptor fd = null; + ProfilerInfo profilerInfo = null; if (start) { profileFile = nextArgRequired(); @@ -973,6 +1040,7 @@ System.err.println("Error: Unable to open file: " + profileFile); return; } + profilerInfo = new ProfilerInfo(profileFile, fd, 0, false); } try { @@ -986,7 +1054,7 @@ } else if (start) { //removeWallOption(); } - if (!mAm.profileControl(process, userId, start, profileFile, fd, profileType)) { + if (!mAm.profileControl(process, userId, start, profilerInfo, profileType)) { wall = false; throw new AndroidException("PROFILE FAILED on process " + process); } @@ -1071,6 +1139,16 @@ mAm.switchUser(Integer.parseInt(user)); } + private void runStartUserInBackground() throws Exception { + String user = nextArgRequired(); + boolean success = mAm.startUserInBackground(Integer.parseInt(user)); + if (success) { + System.out.println("Success: user started"); + } else { + System.err.println("Error: could not start user"); + } + } + private void runStopUser() throws Exception { String user = nextArgRequired(); int res = mAm.stopUser(Integer.parseInt(user), null); @@ -1429,7 +1507,7 @@ System.out.println("Performing idle maintenance..."); Intent intent = new Intent( - "com.android.server.IdleMaintenanceService.action.FORCE_IDLE_MAINTENANCE"); + "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE"); mAm.broadcastIntent(null, intent, null, null, 0, null, null, null, android.app.AppOpsManager.OP_NONE, true, false, UserHandle.USER_ALL); } @@ -1657,4 +1735,102 @@ } catch (RemoteException e) { } } + + private void runLockTask() throws Exception { + String taskIdStr = nextArgRequired(); + try { + if (taskIdStr.equals("stop")) { + mAm.stopLockTaskMode(); + } else { + int taskId = Integer.valueOf(taskIdStr); + mAm.startLockTaskMode(taskId); + } + System.err.println("Activity manager is " + (mAm.isInLockTaskMode() ? "" : "not ") + + "in lockTaskMode"); + } catch (RemoteException e) { + } + } + + private List<Configuration> getRecentConfigurations(int days) { + IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( + Context.USAGE_STATS_SERVICE)); + final long now = System.currentTimeMillis(); + final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000); + try { + @SuppressWarnings("unchecked") + ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats( + UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell"); + if (configStatsSlice == null) { + return Collections.emptyList(); + } + + final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>(); + final List<ConfigurationStats> configStatsList = configStatsSlice.getList(); + final int configStatsListSize = configStatsList.size(); + for (int i = 0; i < configStatsListSize; i++) { + final ConfigurationStats stats = configStatsList.get(i); + final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration()); + if (indexOfKey < 0) { + recentConfigs.put(stats.getConfiguration(), stats.getActivationCount()); + } else { + recentConfigs.setValueAt(indexOfKey, + recentConfigs.valueAt(indexOfKey) + stats.getActivationCount()); + } + } + + final Comparator<Configuration> comparator = new Comparator<Configuration>() { + @Override + public int compare(Configuration a, Configuration b) { + return recentConfigs.get(b).compareTo(recentConfigs.get(a)); + } + }; + + ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size()); + configs.addAll(recentConfigs.keySet()); + Collections.sort(configs, comparator); + return configs; + + } catch (RemoteException e) { + return Collections.emptyList(); + } + } + + private void runGetConfig() throws Exception { + int days = 14; + String option = nextOption(); + if (option != null) { + if (!option.equals("--days")) { + throw new IllegalArgumentException("unrecognized option " + option); + } + + days = Integer.parseInt(nextArgRequired()); + if (days <= 0) { + throw new IllegalArgumentException("--days must be a positive integer"); + } + } + + try { + Configuration config = mAm.getConfiguration(); + if (config == null) { + System.err.println("Activity manager has no configuration"); + return; + } + + System.out.println("config: " + Configuration.resourceQualifierString(config)); + System.out.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS)); + + final List<Configuration> recentConfigs = getRecentConfigurations(days); + final int recentConfigSize = recentConfigs.size(); + if (recentConfigSize > 0) { + System.out.println("recentConfigs:"); + } + + for (int i = 0; i < recentConfigSize; i++) { + System.out.println(" config: " + Configuration.resourceQualifierString( + recentConfigs.get(i))); + } + + } catch (RemoteException e) { + } + } }
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 74ccbc2..1bb28c3 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp
@@ -133,8 +133,7 @@ // names if the zygote command line decreases in size. uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]); uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]); - end += strlen(argv[argc - 1]); - + end += strlen(argv[argc - 1]) + 1; return (end - start); } @@ -161,17 +160,17 @@ LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0), "Error constructing dalvik cache : %s", strerror(errno)); - int result = mkdir(dalvikCacheDir, 0771); + int result = mkdir(dalvikCacheDir, 0711); LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST), "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno)); // We always perform these steps because the directory might // already exist, with wider permissions and a different owner // than we'd like. - result = chown(dalvikCacheDir, AID_SYSTEM, AID_SYSTEM); + result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT); LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno)); - result = chmod(dalvikCacheDir, 0771); + result = chmod(dalvikCacheDir, 0711); LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache permissions : %s", strerror(errno)); } @@ -220,15 +219,27 @@ // // For zygote starts, all remaining arguments are passed to the zygote. // main function. + // + // Note that we must copy argument string values since we will rewrite the + // entire argument block when we apply the nice name to argv0. - - int i = runtime.addVmArguments(argc, argv); + int i; + for (i = 0; i < argc; i++) { + if (argv[i][0] != '-') { + break; + } + if (argv[i][1] == '-' && argv[i][2] == 0) { + ++i; // Skip --. + break; + } + runtime.addOption(strdup(argv[i])); + } // Parse runtime arguments. Stop at first unrecognized option. bool zygote = false; bool startSystemServer = false; bool application = false; - const char* niceName = NULL; + String8 niceName; String8 className; ++i; // Skip unused "parent dir" argument. @@ -242,7 +253,7 @@ } else if (strcmp(arg, "--application") == 0) { application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { - niceName = arg + 12; + niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) { className.setTo(arg); break; @@ -287,9 +298,9 @@ } } - if (niceName && *niceName) { - runtime.setArgv0(niceName); - set_process_name(niceName); + if (!niceName.isEmpty()) { + runtime.setArgv0(niceName.string()); + set_process_name(niceName.string()); } if (zygote) {
diff --git a/cmds/appops/Android.mk b/cmds/appops/Android.mk new file mode 100644 index 0000000..1e15204 --- /dev/null +++ b/cmds/appops/Android.mk
@@ -0,0 +1,16 @@ +# Copyright 2014 The Android Open Source Project + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_MODULE := appops +include $(BUILD_JAVA_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := appops +LOCAL_SRC_FILES := appops +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE_TAGS := optional +include $(BUILD_PREBUILT) +
diff --git a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2 b/cmds/appops/MODULE_LICENSE_APACHE2 similarity index 100% rename from media/jni/mediaeditor/MODULE_LICENSE_APACHE2 rename to cmds/appops/MODULE_LICENSE_APACHE2
diff --git a/cmds/appops/NOTICE b/cmds/appops/NOTICE new file mode 100644 index 0000000..06a9081 --- /dev/null +++ b/cmds/appops/NOTICE
@@ -0,0 +1,190 @@ + + Copyright (c) 2005-2014, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +
diff --git a/cmds/appops/appops b/cmds/appops/appops new file mode 100755 index 0000000..407e551 --- /dev/null +++ b/cmds/appops/appops
@@ -0,0 +1,5 @@ +# Script to start "appwidget" on the device, which has a very rudimentary shell. +base=/system +export CLASSPATH=$base/framework/appops.jar +exec app_process $base/bin com.android.commands.appops.AppOpsCommand "$@" +
diff --git a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java new file mode 100644 index 0000000..c414f58 --- /dev/null +++ b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
@@ -0,0 +1,137 @@ +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package com.android.commands.appops; + +import android.app.ActivityManager; +import android.app.ActivityThread; +import android.app.AppOpsManager; +import android.content.Context; +import android.content.pm.IPackageManager; +import android.os.ServiceManager; +import android.os.UserHandle; + +import com.android.internal.app.IAppOpsService; +import com.android.internal.os.BaseCommand; + +import java.io.PrintStream; + +/** + * This class is a command line utility for manipulating AppOps permissions. + */ +public class AppOpsCommand extends BaseCommand { + + public static void main(String[] args) { + new AppOpsCommand().run(args); + } + + @Override + public void onShowUsage(PrintStream out) { + out.println("usage: adb shell appops set <PACKAGE> <OP> " + + "<allow|ignore|deny|default> [--user <USER_ID>]\n" + + " <PACKAGE> an Android package name.\n" + + " <OP> an AppOps operation.\n" + + " <USER_ID> the user id under which the package is installed. If --user is not\n" + + " specified, the current user is assumed.\n"); + } + + private static final String COMMAND_SET = "set"; + + @Override + public void onRun() throws Exception { + String command = nextArgRequired(); + switch (command) { + case COMMAND_SET: + runSet(); + break; + + default: + throw new IllegalArgumentException("Unknown command '" + command + "'."); + } + } + + private static final String ARGUMENT_USER = "--user"; + + // Modes + private static final String MODE_ALLOW = "allow"; + private static final String MODE_DENY = "deny"; + private static final String MODE_IGNORE = "ignore"; + private static final String MODE_DEFAULT = "default"; + + private void runSet() throws Exception { + String packageName = null; + String op = null; + String mode = null; + int userId = UserHandle.USER_CURRENT; + for (String argument; (argument = nextArg()) != null;) { + if (ARGUMENT_USER.equals(argument)) { + userId = Integer.parseInt(nextArgRequired()); + } else { + if (packageName == null) { + packageName = argument; + } else if (op == null) { + op = argument; + } else if (mode == null) { + mode = argument; + } else { + throw new IllegalArgumentException("Unsupported argument: " + argument); + } + } + } + + if (packageName == null) { + throw new IllegalArgumentException("Package name not specified."); + } else if (op == null) { + throw new IllegalArgumentException("Operation not specified."); + } else if (mode == null) { + throw new IllegalArgumentException("Mode not specified."); + } + + final int opInt = AppOpsManager.strOpToOp(op); + final int modeInt; + switch (mode) { + case MODE_ALLOW: + modeInt = AppOpsManager.MODE_ALLOWED; + break; + case MODE_DENY: + modeInt = AppOpsManager.MODE_ERRORED; + break; + case MODE_IGNORE: + modeInt = AppOpsManager.MODE_IGNORED; + break; + case MODE_DEFAULT: + modeInt = AppOpsManager.MODE_DEFAULT; + break; + default: + throw new IllegalArgumentException("Mode is invalid."); + } + + // Parsing complete, let's execute the command. + + if (userId == UserHandle.USER_CURRENT) { + userId = ActivityManager.getCurrentUser(); + } + + final IPackageManager pm = ActivityThread.getPackageManager(); + final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( + ServiceManager.getService(Context.APP_OPS_SERVICE)); + final int uid = pm.getPackageUid(packageName, userId); + if (uid < 0) { + throw new Exception("No UID for " + packageName + " for user " + userId); + } + appOpsService.setMode(opInt, uid, packageName, modeInt); + } +}
diff --git a/cmds/appwidget/Android.mk b/cmds/appwidget/Android.mk new file mode 100644 index 0000000..1fb258d --- /dev/null +++ b/cmds/appwidget/Android.mk
@@ -0,0 +1,16 @@ +# Copyright 2014 The Android Open Source Project + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_MODULE := appwidget +include $(BUILD_JAVA_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := appwidget +LOCAL_SRC_FILES := appwidget +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE_TAGS := optional +include $(BUILD_PREBUILT) +
diff --git a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2 b/cmds/appwidget/MODULE_LICENSE_APACHE2 similarity index 100% copy from media/jni/mediaeditor/MODULE_LICENSE_APACHE2 copy to cmds/appwidget/MODULE_LICENSE_APACHE2
diff --git a/cmds/appwidget/NOTICE b/cmds/appwidget/NOTICE new file mode 100644 index 0000000..06a9081 --- /dev/null +++ b/cmds/appwidget/NOTICE
@@ -0,0 +1,190 @@ + + Copyright (c) 2005-2014, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +
diff --git a/cmds/appwidget/appwidget b/cmds/appwidget/appwidget new file mode 100755 index 0000000..6105009 --- /dev/null +++ b/cmds/appwidget/appwidget
@@ -0,0 +1,5 @@ +# Script to start "appwidget" on the device, which has a very rudimentary shell. +base=/system +export CLASSPATH=$base/framework/appwidget.jar +exec app_process $base/bin com.android.commands.appwidget.AppWidget "$@" +
diff --git a/cmds/appwidget/src/com/android/commands/appwidget/AppWidget.java b/cmds/appwidget/src/com/android/commands/appwidget/AppWidget.java new file mode 100644 index 0000000..5ea7352 --- /dev/null +++ b/cmds/appwidget/src/com/android/commands/appwidget/AppWidget.java
@@ -0,0 +1,167 @@ +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package com.android.commands.appwidget; + +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.text.TextUtils; + +import com.android.internal.appwidget.IAppWidgetService; + +/** + * This class is a command line utility for manipulating app widgets. A client + * can grant or revoke the permission for a given package to bind app widgets. + */ +public class AppWidget { + + private static final String USAGE = + "usage: adb shell appwidget [subcommand] [options]\n" + + "\n" + + "usage: adb shell appwidget grantbind --package <PACKAGE> " + + " [--user <USER_ID> | current]\n" + + " <PACKAGE> an Android package name.\n" + + " <USER_ID> The user id under which the package is installed.\n" + + " Example:\n" + + " # Grant the \"foo.bar.baz\" package to bind app widgets for the current user.\n" + + " adb shell grantbind --package foo.bar.baz --user current\n" + + "\n" + + "usage: adb shell appwidget revokebind --package <PACKAGE> " + + "[--user <USER_ID> | current]\n" + + " <PACKAGE> an Android package name.\n" + + " <USER_ID> The user id under which the package is installed.\n" + + " Example:\n" + + " # Revoke the permisison to bind app widgets from the \"foo.bar.baz\" package.\n" + + " adb shell revokebind --package foo.bar.baz --user current\n" + + "\n"; + + private static class Parser { + private static final String ARGUMENT_GRANT_BIND = "grantbind"; + private static final String ARGUMENT_REVOKE_BIND = "revokebind"; + private static final String ARGUMENT_PACKAGE = "--package"; + private static final String ARGUMENT_USER = "--user"; + private static final String ARGUMENT_PREFIX = "--"; + private static final String VALUE_USER_CURRENT = "current"; + + private final Tokenizer mTokenizer; + + public Parser(String[] args) { + mTokenizer = new Tokenizer(args); + } + + public Runnable parseCommand() { + try { + String operation = mTokenizer.nextArg(); + if (ARGUMENT_GRANT_BIND.equals(operation)) { + return parseSetGrantBindAppWidgetPermissionCommand(true); + } else if (ARGUMENT_REVOKE_BIND.equals(operation)) { + return parseSetGrantBindAppWidgetPermissionCommand(false); + } else { + throw new IllegalArgumentException("Unsupported operation: " + operation); + } + } catch (IllegalArgumentException iae) { + System.out.println(USAGE); + System.out.println("[ERROR] " + iae.getMessage()); + return null; + } + } + + private SetBindAppWidgetPermissionCommand parseSetGrantBindAppWidgetPermissionCommand( + boolean granted) { + String packageName = null; + int userId = UserHandle.USER_OWNER; + for (String argument; (argument = mTokenizer.nextArg()) != null;) { + if (ARGUMENT_PACKAGE.equals(argument)) { + packageName = argumentValueRequired(argument); + } else if (ARGUMENT_USER.equals(argument)) { + String user = argumentValueRequired(argument); + if (VALUE_USER_CURRENT.equals(user)) { + userId = UserHandle.USER_CURRENT; + } else { + userId = Integer.parseInt(user); + } + } else { + throw new IllegalArgumentException("Unsupported argument: " + argument); + } + } + if (packageName == null) { + throw new IllegalArgumentException("Package name not specified." + + " Did you specify --package argument?"); + } + return new SetBindAppWidgetPermissionCommand(packageName, granted, userId); + } + + private String argumentValueRequired(String argument) { + String value = mTokenizer.nextArg(); + if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) { + throw new IllegalArgumentException("No value for argument: " + argument); + } + return value; + } + } + + private static class Tokenizer { + private final String[] mArgs; + private int mNextArg; + + public Tokenizer(String[] args) { + mArgs = args; + } + + private String nextArg() { + if (mNextArg < mArgs.length) { + return mArgs[mNextArg++]; + } else { + return null; + } + } + } + + private static class SetBindAppWidgetPermissionCommand implements Runnable { + final String mPackageName; + final boolean mGranted; + final int mUserId; + + public SetBindAppWidgetPermissionCommand(String packageName, boolean granted, + int userId) { + mPackageName = packageName; + mGranted = granted; + mUserId = userId; + } + + @Override + public void run() { + IBinder binder = ServiceManager.getService(Context.APPWIDGET_SERVICE); + IAppWidgetService appWidgetService = IAppWidgetService.Stub.asInterface(binder); + try { + appWidgetService.setBindAppWidgetPermission(mPackageName, mUserId, mGranted); + } catch (RemoteException re) { + re.printStackTrace(); + } + } + } + + public static void main(String[] args) { + Parser parser = new Parser(args); + Runnable command = parser.parseCommand(); + if (command != null) { + command.run(); + } + } +}
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index db3d8bb..d683851 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -23,6 +23,7 @@ import android.os.RemoteException; import android.os.ServiceManager; +import java.util.ArrayList; import java.util.HashSet; public final class Bmgr { @@ -102,6 +103,11 @@ return; } + if ("fullbackup".equals(op)) { + doFullTransportBackup(); + return; + } + System.err.println("Unknown command"); showUsage(); } @@ -165,6 +171,24 @@ } } + private void doFullTransportBackup() { + System.out.println("Performing full transport backup"); + + String pkg; + ArrayList<String> allPkgs = new ArrayList<String>(); + while ((pkg = nextArg()) != null) { + allPkgs.add(pkg); + } + if (allPkgs.size() > 0) { + try { + mBmgr.fullTransportBackup(allPkgs.toArray(new String[allPkgs.size()])); + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(BMGR_NOT_RUNNING_ERR); + } + } + } + private void doTransport() { try { String which = nextArg(); @@ -453,6 +477,7 @@ System.err.println(" bmgr restore PACKAGE"); System.err.println(" bmgr run"); System.err.println(" bmgr wipe TRANSPORT PACKAGE"); + System.err.println(" bmgr fullbackup PACKAGE..."); System.err.println(""); System.err.println("The 'backup' command schedules a backup pass for the named package."); System.err.println("Note that the backup pass will effectively be a no-op if the package"); @@ -468,11 +493,11 @@ System.err.println(""); System.err.println("The 'list transports' command reports the names of the backup transports"); System.err.println("currently available on the device. These names can be passed as arguments"); - System.err.println("to the 'transport' and 'wipe' commands. The currently selected transport"); + System.err.println("to the 'transport' and 'wipe' commands. The currently active transport"); System.err.println("is indicated with a '*' character."); System.err.println(""); System.err.println("The 'list sets' command reports the token and name of each restore set"); - System.err.println("available to the device via the current transport."); + System.err.println("available to the device via the currently active transport."); System.err.println(""); System.err.println("The 'transport' command designates the named transport as the currently"); System.err.println("active one. This setting is persistent across reboots."); @@ -500,5 +525,8 @@ System.err.println("erased from the given transport's storage. The next backup operation"); System.err.println("that the given application performs will rewrite its entire data set."); System.err.println("Transport names to use here are those reported by 'list transports'."); + System.err.println(""); + System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more"); + System.err.println("packages. The data is sent via the currently active transport."); } }
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index dd987e0..c4fe6cf 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk
@@ -19,9 +19,6 @@ libGLESv1_CM \ libgui -LOCAL_C_INCLUDES := \ - $(call include-path-for, corecg graphics) - LOCAL_MODULE:= bootanimation ifdef TARGET_32_BIT_SURFACEFLINGER
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 7f7ae2c..08923119 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp
@@ -36,15 +36,14 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <ui/DisplayInfo.h> -#include <ui/FramebufferNativeWindow.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> -#include <core/SkBitmap.h> -#include <core/SkStream.h> -#include <core/SkImageDecoder.h> +#include <SkBitmap.h> +#include <SkStream.h> +#include <SkImageDecoder.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -52,6 +51,7 @@ #include "BootAnimation.h" +#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip" #define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip" #define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip" #define EXIT_PROP_NAME "service.bootanim.exit" @@ -108,7 +108,7 @@ return NO_INIT; SkBitmap bitmap; SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), - &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode); + &bitmap, kUnknown_SkColorType, SkImageDecoder::kDecodePixels_Mode); asset->close(); delete asset; @@ -127,20 +127,20 @@ glGenTextures(1, &texture->name); glBindTexture(GL_TEXTURE_2D, texture->name); - switch (bitmap.getConfig()) { - case SkBitmap::kA8_Config: + switch (bitmap.colorType()) { + case kAlpha_8_SkColorType: glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, p); break; - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, p); break; - case SkBitmap::kARGB_8888_Config: + case kN32_SkColorType: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, p); break; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); break; @@ -166,7 +166,7 @@ if (codec) { codec->setDitherImage(false); codec->decode(&stream, &bitmap, - SkBitmap::kARGB_8888_Config, + kN32_SkColorType, SkImageDecoder::kDecodePixels_Mode); delete codec; } @@ -190,8 +190,8 @@ if (tw < w) tw <<= 1; if (th < h) th <<= 1; - switch (bitmap.getConfig()) { - case SkBitmap::kARGB_8888_Config: + switch (bitmap.colorType()) { + case kN32_SkColorType: if (tw != w || th != h) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); @@ -203,7 +203,7 @@ } break; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: if (tw != w || th != h) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); @@ -289,6 +289,9 @@ (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) && ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) || + ((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) && + ((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) || + ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) && ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) { mZip = zipFile; @@ -394,6 +397,31 @@ } } +// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of +// characters in str is a hex number in [0, 255], which are converted to +// floating point values in the range [0.0, 1.0] and placed in the +// corresponding elements of color. +// +// If the input string isn't valid, parseColor returns false and color is +// left unchanged. +static bool parseColor(const char str[7], float color[3]) { + float tmpColor[3]; + for (int i = 0; i < 3; i++) { + int val = 0; + for (int j = 0; j < 2; j++) { + val *= 16; + char c = str[2*i + j]; + if (c >= '0' && c <= '9') val += c - '0'; + else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10; + else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10; + else return false; + } + tmpColor[i] = static_cast<float>(val) / 255.0f; + } + memcpy(color, tmpColor, sizeof(tmpColor)); + return true; +} + bool BootAnimation::movie() { ZipEntryRO desc = mZip->findEntryByName("desc.txt"); @@ -424,20 +452,28 @@ const char* l = line.string(); int fps, width, height, count, pause; char path[ANIM_ENTRY_NAME_MAX]; + char color[7] = "000000"; // default to black if unspecified + char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { - //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); + // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps); animation.width = width; animation.height = height; animation.fps = fps; } - else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { - //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); + else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) { + // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s", pathType, count, pause, path, color); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; + if (!parseColor(color, part.backgroundColor)) { + ALOGE("> invalid color '#%s'", color); + part.backgroundColor[0] = 0.0f; + part.backgroundColor[1] = 0.0f; + part.backgroundColor[2] = 0.0f; + } animation.parts.add(part); } @@ -523,6 +559,12 @@ if(exitPending() && !part.playUntilComplete) break; + glClearColor( + part.backgroundColor[0], + part.backgroundColor[1], + part.backgroundColor[2], + 1.0f); + for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime();
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index ba1c507..72cd62b 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h
@@ -71,6 +71,7 @@ String8 path; SortedVector<Frame> frames; bool playUntilComplete; + float backgroundColor[3]; }; int fps; int width;
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java index 73fd660..ffc0f87 100644 --- a/cmds/bu/src/com/android/commands/bu/Backup.java +++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -20,6 +20,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; +import android.system.OsConstants; import android.util.Log; import java.io.IOException; @@ -50,13 +51,11 @@ return; } - int socketFd = Integer.parseInt(nextArg()); - String arg = nextArg(); if (arg.equals("backup")) { - doFullBackup(socketFd); + doFullBackup(OsConstants.STDOUT_FILENO); } else if (arg.equals("restore")) { - doFullRestore(socketFd); + doFullRestore(OsConstants.STDIN_FILENO); } else { Log.e(TAG, "Invalid operation '" + arg + "'"); } @@ -68,7 +67,9 @@ boolean saveObbs = false; boolean saveShared = false; boolean doEverything = false; + boolean doWidgets = false; boolean allIncludesSystem = true; + boolean doCompress = true; String arg; while ((arg = nextArg()) != null) { @@ -89,8 +90,16 @@ allIncludesSystem = true; } else if ("-nosystem".equals(arg)) { allIncludesSystem = false; + } else if ("-widgets".equals(arg)) { + doWidgets = true; + } else if ("-nowidgets".equals(arg)) { + doWidgets = false; } else if ("-all".equals(arg)) { doEverything = true; + } else if ("-compress".equals(arg)) { + doCompress = true; + } else if ("-nocompress".equals(arg)) { + doCompress = false; } else { Log.w(TAG, "Unknown backup flag " + arg); continue; @@ -114,8 +123,8 @@ try { fd = ParcelFileDescriptor.adoptFd(socketFd); String[] packArray = new String[packages.size()]; - mBackupManager.fullBackup(fd, saveApks, saveObbs, saveShared, doEverything, - allIncludesSystem, packages.toArray(packArray)); + mBackupManager.fullBackup(fd, saveApks, saveObbs, saveShared, doWidgets, + doEverything, allIncludesSystem, doCompress, packages.toArray(packArray)); } catch (RemoteException e) { Log.e(TAG, "Unable to invoke backup manager for backup"); } finally {
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java index e66bdf4..948c9a2 100644 --- a/cmds/content/src/com/android/commands/content/Content.java +++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -26,9 +26,17 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.text.TextUtils; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import libcore.io.IoUtils; + /** * This class is a command line utility for manipulating content. A client * can insert, update, and remove records in a content provider. For example, @@ -109,6 +117,12 @@ + " <METHOD> is the name of a provider-defined method\n" + " <ARG> is an optional string argument\n" + " <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n" + + "\n" + + "usage: adb shell content read --uri <URI> [--user <USER_ID>]\n" + + " Example:\n" + + " # cat default ringtone to a file, then pull to host\n" + + " adb shell 'content read --uri content://settings/system/ringtone >" + + " /mnt/sdcard/tmp.ogg' && adb pull /mnt/sdcard/tmp.ogg\n" + "\n"; private static class Parser { @@ -117,6 +131,7 @@ private static final String ARGUMENT_UPDATE = "update"; private static final String ARGUMENT_QUERY = "query"; private static final String ARGUMENT_CALL = "call"; + private static final String ARGUMENT_READ = "read"; private static final String ARGUMENT_WHERE = "--where"; private static final String ARGUMENT_BIND = "--bind"; private static final String ARGUMENT_URI = "--uri"; @@ -154,6 +169,8 @@ return parseQueryCommand(); } else if (ARGUMENT_CALL.equals(operation)) { return parseCallCommand(); + } else if (ARGUMENT_READ.equals(operation)) { + return parseReadCommand(); } else { throw new IllegalArgumentException("Unsupported operation: " + operation); } @@ -273,6 +290,25 @@ return new CallCommand(uri, userId, method, arg, values); } + private ReadCommand parseReadCommand() { + Uri uri = null; + int userId = UserHandle.USER_OWNER; + for (String argument; (argument = mTokenizer.nextArg())!= null;) { + if (ARGUMENT_URI.equals(argument)) { + uri = Uri.parse(argumentValueRequired(argument)); + } else if (ARGUMENT_USER.equals(argument)) { + userId = Integer.parseInt(argumentValueRequired(argument)); + } else { + throw new IllegalArgumentException("Unsupported argument: " + argument); + } + } + if (uri == null) { + throw new IllegalArgumentException("Content provider URI not specified." + + " Did you specify --uri argument?"); + } + return new ReadCommand(uri, userId); + } + public QueryCommand parseQueryCommand() { Uri uri = null; int userId = UserHandle.USER_OWNER; @@ -458,6 +494,31 @@ } } + private static class ReadCommand extends Command { + public ReadCommand(Uri uri, int userId) { + super(uri, userId); + } + + @Override + public void onExecute(IContentProvider provider) throws Exception { + final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null); + copy(new FileInputStream(fd.getFileDescriptor()), System.out); + } + + private static void copy(InputStream is, OutputStream os) throws IOException { + final byte[] buffer = new byte[8 * 1024]; + int read; + try { + while ((read = is.read(buffer)) > -1) { + os.write(buffer, 0, read); + } + } finally { + IoUtils.closeQuietly(is); + IoUtils.closeQuietly(os); + } + } + } + private static class QueryCommand extends DeleteCommand { final String[] mProjection; final String mSortOrder; @@ -498,7 +559,7 @@ columnValue = String.valueOf(cursor.getFloat(columnIndex)); break; case Cursor.FIELD_TYPE_INTEGER: - columnValue = String.valueOf(cursor.getInt(columnIndex)); + columnValue = String.valueOf(cursor.getLong(columnIndex)); break; case Cursor.FIELD_TYPE_STRING: columnValue = cursor.getString(columnIndex);
diff --git a/cmds/dpm/Android.mk b/cmds/dpm/Android.mk new file mode 100644 index 0000000..9f5aee4 --- /dev/null +++ b/cmds/dpm/Android.mk
@@ -0,0 +1,15 @@ +# Copyright 2014 The Android Open Source Project +# +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_MODULE := dpm +include $(BUILD_JAVA_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := dpm +LOCAL_SRC_FILES := dpm +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE_TAGS := optional +include $(BUILD_PREBUILT)
diff --git a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2 b/cmds/dpm/MODULE_LICENSE_APACHE2 similarity index 100% copy from media/jni/mediaeditor/MODULE_LICENSE_APACHE2 copy to cmds/dpm/MODULE_LICENSE_APACHE2
diff --git a/cmds/dpm/NOTICE b/cmds/dpm/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/cmds/dpm/NOTICE
@@ -0,0 +1,190 @@ + + Copyright (c) 2014, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +
diff --git a/cmds/dpm/dpm b/cmds/dpm/dpm new file mode 100755 index 0000000..c2e5cbb --- /dev/null +++ b/cmds/dpm/dpm
@@ -0,0 +1,6 @@ +# Script to start "dpm" on the device +# +base=/system +export CLASSPATH=$base/framework/dpm.jar +exec app_process $base/bin com.android.commands.dpm.Dpm "$@" +
diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java new file mode 100644 index 0000000..3b9a785 --- /dev/null +++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
@@ -0,0 +1,135 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.commands.dpm; + +import android.app.admin.IDevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; + +import com.android.internal.os.BaseCommand; + +import java.io.PrintStream; + +public final class Dpm extends BaseCommand { + + /** + * Command-line entry point. + * + * @param args The command-line arguments + */ + public static void main(String[] args) { + (new Dpm()).run(args); + } + + private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner"; + private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner"; + + private IDevicePolicyManager mDevicePolicyManager; + + @Override + public void onShowUsage(PrintStream out) { + out.println( + "usage: dpm [subcommand] [options]\n" + + "usage: dpm set-device-owner <COMPONENT>\n" + + "usage: dpm set-profile-owner <COMPONENT> <USER_ID>\n" + + "\n" + + "dpm set-device-owner: Sets the given component as active admin, and its\n" + + " package as device owner.\n" + + "\n" + + "dpm set-profile-owner: Sets the given component as active admin and profile" + + " owner for an existing user.\n"); + } + + @Override + public void onRun() throws Exception { + mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); + if (mDevicePolicyManager == null) { + showError("Error: Could not access the Device Policy Manager. Is the system running?"); + return; + } + + String command = nextArgRequired(); + switch (command) { + case COMMAND_SET_DEVICE_OWNER: + runSetDeviceOwner(); + break; + case COMMAND_SET_PROFILE_OWNER: + runSetProfileOwner(); + break; + default: + throw new IllegalArgumentException ("unknown command '" + command + "'"); + } + } + + private void runSetDeviceOwner() throws RemoteException { + ComponentName component = parseComponentName(nextArgRequired()); + mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, UserHandle.USER_OWNER); + + String packageName = component.getPackageName(); + try { + if (!mDevicePolicyManager.setDeviceOwner(packageName, null /*ownerName*/)) { + throw new RuntimeException( + "Can't set package " + packageName + " as device owner."); + } + } catch (Exception e) { + // Need to remove the admin that we just added. + mDevicePolicyManager.removeActiveAdmin(component, UserHandle.USER_OWNER); + throw e; + } + System.out.println("Success: Device owner set to package " + packageName); + System.out.println("Active admin set to component " + component.toShortString()); + } + + private void runSetProfileOwner() throws RemoteException { + ComponentName component = parseComponentName(nextArgRequired()); + int userId = parseInt(nextArgRequired()); + mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, userId); + + try { + if (!mDevicePolicyManager.setProfileOwner(component, "" /*ownerName*/, userId)) { + throw new RuntimeException("Can't set component " + component.toShortString() + + " as profile owner for user " + userId); + } + } catch (Exception e) { + // Need to remove the admin that we just added. + mDevicePolicyManager.removeActiveAdmin(component, userId); + throw e; + } + System.out.println("Success: Active admin and profile owner set to " + + component.toShortString() + " for user " + userId); + } + + private ComponentName parseComponentName(String component) { + ComponentName cn = ComponentName.unflattenFromString(component); + if (cn == null) { + throw new IllegalArgumentException ("Invalid component " + component); + } + return cn; + } + + private int parseInt(String argument) { + try { + return Integer.parseInt(argument); + } catch (NumberFormatException e) { + throw new IllegalArgumentException ("Invalid integer argument '" + argument + "'", e); + } + } +} \ No newline at end of file
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp index ae35f7b..593a197 100644 --- a/cmds/idmap/create.cpp +++ b/cmds/idmap/create.cpp
@@ -105,7 +105,7 @@ uint32_t cached_target_crc, cached_overlay_crc; String8 cached_target_path, cached_overlay_path; - if (!ResTable::getIdmapInfo(buf, N, &cached_target_crc, &cached_overlay_crc, + if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc, &cached_target_path, &cached_overlay_path)) { return true; }
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp index 46c0edc..90cfa2c 100644 --- a/cmds/idmap/idmap.cpp +++ b/cmds/idmap/idmap.cpp
@@ -66,26 +66,32 @@ Display an idmap file: \n\ \n\ $ adb shell idmap --inspect /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\ - SECTION ENTRY VALUE OFFSET COMMENT \n\ - IDMAP HEADER magic 0x706d6469 0x0 \n\ - base crc 0x484aa77f 0x1 \n\ - overlay crc 0x03c66fa5 0x2 \n\ - base path .......... 0x03-0x42 /system/app/target.apk \n\ - overlay path .......... 0x43-0x82 /vendor/overlay/overlay.apk \n\ - DATA HEADER types count 0x00000003 0x83 \n\ - padding 0x00000000 0x84 \n\ - type offset 0x00000004 0x85 absolute offset 0x87, xml \n\ - type offset 0x00000007 0x86 absolute offset 0x8a, string \n\ - DATA BLOCK entry count 0x00000001 0x87 \n\ - entry offset 0x00000000 0x88 \n\ - entry 0x7f020000 0x89 xml/integer \n\ - DATA BLOCK entry count 0x00000002 0x8a \n\ - entry offset 0x00000000 0x8b \n\ - entry 0x7f030000 0x8c string/str \n\ - entry 0x7f030001 0x8d string/str2 \n\ + SECTION ENTRY VALUE COMMENT \n\ + IDMAP HEADER magic 0x706d6469 \n\ + base crc 0xb65a383f \n\ + overlay crc 0x7b9675e8 \n\ + base path .......... /path/to/target.apk \n\ + overlay path .......... /path/to/overlay.apk \n\ + DATA HEADER target pkg 0x0000007f \n\ + types count 0x00000003 \n\ + DATA BLOCK target type 0x00000002 \n\ + overlay type 0x00000002 \n\ + entry count 0x00000001 \n\ + entry offset 0x00000000 \n\ + entry 0x00000000 drawable/drawable \n\ + DATA BLOCK target type 0x00000003 \n\ + overlay type 0x00000003 \n\ + entry count 0x00000001 \n\ + entry offset 0x00000000 \n\ + entry 0x00000000 xml/integer \n\ + DATA BLOCK target type 0x00000004 \n\ + overlay type 0x00000004 \n\ + entry count 0x00000001 \n\ + entry offset 0x00000000 \n\ + entry 0x00000000 raw/lorem_ipsum \n\ \n\ In this example, the overlay package provides three alternative resource values:\n\ - xml/integer, string/str and string/str2.\n\ + drawable/drawable, xml/integer, and raw/lorem_ipsum \n\ \n\ NOTES \n\ This tool and its expected invocation from installd is modelled on dexopt.";
diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp index a59f5d31..b9ac8a5 100644 --- a/cmds/idmap/inspect.cpp +++ b/cmds/idmap/inspect.cpp
@@ -10,92 +10,108 @@ using namespace android; -#define NEXT(b, i, o) do { if (buf.next(&i, &o) < 0) { return -1; } } while (0) - namespace { - static const uint32_t IDMAP_MAGIC = 0x706d6469; + static const uint32_t IDMAP_MAGIC = 0x504D4449; static const size_t PATH_LENGTH = 256; - static const uint32_t IDMAP_HEADER_SIZE = (3 + 2 * (PATH_LENGTH / sizeof(uint32_t))); void printe(const char *fmt, ...); class IdmapBuffer { private: - char *buf_; + const char* buf_; size_t len_; - mutable size_t pos_; + size_t pos_; public: - IdmapBuffer() : buf_((char *)MAP_FAILED), len_(0), pos_(0) {} + IdmapBuffer() : buf_((const char *)MAP_FAILED), len_(0), pos_(0) {} ~IdmapBuffer() { if (buf_ != MAP_FAILED) { - munmap(buf_, len_); + munmap(const_cast<char*>(buf_), len_); } } - int init(const char *idmap_path) - { + status_t init(const char *idmap_path) { struct stat st; int fd; if (stat(idmap_path, &st) < 0) { printe("failed to stat idmap '%s': %s\n", idmap_path, strerror(errno)); - return -1; + return UNKNOWN_ERROR; } len_ = st.st_size; if ((fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY))) < 0) { printe("failed to open idmap '%s': %s\n", idmap_path, strerror(errno)); - return -1; + return UNKNOWN_ERROR; } - if ((buf_ = (char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { + if ((buf_ = (const char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { close(fd); printe("failed to mmap idmap: %s\n", strerror(errno)); - return -1; + return UNKNOWN_ERROR; } close(fd); - return 0; + return NO_ERROR; } - int next(uint32_t *i, uint32_t *offset) const - { + status_t nextUint32(uint32_t* i) { if (!buf_) { printe("failed to read next uint32_t: buffer not initialized\n"); - return -1; + return UNKNOWN_ERROR; } - if (pos_ + 4 > len_) { + + if (pos_ + sizeof(uint32_t) > len_) { printe("failed to read next uint32_t: end of buffer reached at pos=0x%08x\n", pos_); - return -1; + return UNKNOWN_ERROR; } - *offset = pos_ / sizeof(uint32_t); - char a = buf_[pos_++]; - char b = buf_[pos_++]; - char c = buf_[pos_++]; - char d = buf_[pos_++]; - *i = (d << 24) | (c << 16) | (b << 8) | a; - return 0; + + if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x3) != 0) { + printe("failed to read next uint32_t: not aligned on 4-byte boundary\n"); + return UNKNOWN_ERROR; + } + + *i = dtohl(*reinterpret_cast<const uint32_t*>(buf_ + pos_)); + pos_ += sizeof(uint32_t); + return NO_ERROR; } - int nextPath(char *b, uint32_t *offset_start, uint32_t *offset_end) const - { + status_t nextUint16(uint16_t* i) { + if (!buf_) { + printe("failed to read next uint16_t: buffer not initialized\n"); + return UNKNOWN_ERROR; + } + + if (pos_ + sizeof(uint16_t) > len_) { + printe("failed to read next uint16_t: end of buffer reached at pos=0x%08x\n", + pos_); + return UNKNOWN_ERROR; + } + + if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x1) != 0) { + printe("failed to read next uint32_t: not aligned on 2-byte boundary\n"); + return UNKNOWN_ERROR; + } + + *i = dtohs(*reinterpret_cast<const uint16_t*>(buf_ + pos_)); + pos_ += sizeof(uint16_t); + return NO_ERROR; + } + + status_t nextPath(char *b) { if (!buf_) { printe("failed to read next path: buffer not initialized\n"); - return -1; + return UNKNOWN_ERROR; } if (pos_ + PATH_LENGTH > len_) { printe("failed to read next path: end of buffer reached at pos=0x%08x\n", pos_); - return -1; + return UNKNOWN_ERROR; } memcpy(b, buf_ + pos_, PATH_LENGTH); - *offset_start = pos_ / sizeof(uint32_t); pos_ += PATH_LENGTH; - *offset_end = pos_ / sizeof(uint32_t) - 1; - return 0; + return NO_ERROR; } }; - void printe(const char *fmt, ...) - { + void printe(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -104,44 +120,37 @@ va_end(ap); } - void print_header() - { - printf("SECTION ENTRY VALUE OFFSET COMMENT\n"); + void print_header() { + printf("SECTION ENTRY VALUE COMMENT\n"); } - void print(const char *section, const char *subsection, uint32_t value, uint32_t offset, - const char *fmt, ...) - { + void print(const char *section, const char *subsection, uint32_t value, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - printf("%-12s %-12s 0x%08x 0x%-4x ", section, subsection, value, offset); + printf("%-12s %-12s 0x%08x ", section, subsection, value); vprintf(fmt, ap); printf("\n"); va_end(ap); } - void print_path(const char *section, const char *subsection, uint32_t offset_start, - uint32_t offset_end, const char *fmt, ...) - { + void print_path(const char *section, const char *subsection, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - printf("%-12s %-12s .......... 0x%02x-0x%02x ", section, subsection, offset_start, - offset_end); + printf("%-12s %-12s .......... ", section, subsection); vprintf(fmt, ap); printf("\n"); va_end(ap); } - int resource_metadata(const AssetManager& am, uint32_t res_id, - String8 *package, String8 *type, String8 *name) - { + status_t resource_metadata(const AssetManager& am, uint32_t res_id, + String8 *package, String8 *type, String8 *name) { const ResTable& rt = am.getResources(); struct ResTable::resource_name data; if (!rt.getResourceName(res_id, false, &data)) { printe("failed to get resource name id=0x%08x\n", res_id); - return -1; + return UNKNOWN_ERROR; } if (package) { *package = String8(String16(data.package, data.packageLen)); @@ -152,140 +161,150 @@ if (name) { *name = String8(String16(data.name, data.nameLen)); } - return 0; + return NO_ERROR; } - int package_id(const AssetManager& am) - { - return (am.getResources().getBasePackageId(0)) << 24; - } - - int parse_idmap_header(const IdmapBuffer& buf, AssetManager& am) - { - uint32_t i, o, e; + status_t parse_idmap_header(IdmapBuffer& buf, AssetManager& am) { + uint32_t i; char path[PATH_LENGTH]; - NEXT(buf, i, o); + status_t err = buf.nextUint32(&i); + if (err != NO_ERROR) { + return err; + } + if (i != IDMAP_MAGIC) { printe("not an idmap file: actual magic constant 0x%08x does not match expected magic " "constant 0x%08x\n", i, IDMAP_MAGIC); - return -1; + return UNKNOWN_ERROR; } + print_header(); - print("IDMAP HEADER", "magic", i, o, ""); + print("IDMAP HEADER", "magic", i, ""); - NEXT(buf, i, o); - print("", "base crc", i, o, ""); - - NEXT(buf, i, o); - print("", "overlay crc", i, o, ""); - - if (buf.nextPath(path, &o, &e) < 0) { - // printe done from IdmapBuffer::nextPath - return -1; + err = buf.nextUint32(&i); + if (err != NO_ERROR) { + return err; } - print_path("", "base path", o, e, "%s", path); + print("", "version", i, ""); + + err = buf.nextUint32(&i); + if (err != NO_ERROR) { + return err; + } + print("", "base crc", i, ""); + + err = buf.nextUint32(&i); + if (err != NO_ERROR) { + return err; + } + print("", "overlay crc", i, ""); + + err = buf.nextPath(path); + if (err != NO_ERROR) { + // printe done from IdmapBuffer::nextPath + return err; + } + print_path("", "base path", "%s", path); + if (!am.addAssetPath(String8(path), NULL)) { printe("failed to add '%s' as asset path\n", path); - return -1; + return UNKNOWN_ERROR; } - if (buf.nextPath(path, &o, &e) < 0) { + err = buf.nextPath(path); + if (err != NO_ERROR) { // printe done from IdmapBuffer::nextPath - return -1; + return err; } - print_path("", "overlay path", o, e, "%s", path); + print_path("", "overlay path", "%s", path); - return 0; + return NO_ERROR; } - int parse_data_header(const IdmapBuffer& buf, const AssetManager& am, Vector<uint32_t>& types) - { - uint32_t i, o; - const uint32_t numeric_package = package_id(am); + status_t parse_data(IdmapBuffer& buf, const AssetManager& am) { + const uint32_t packageId = am.getResources().getBasePackageId(0); - NEXT(buf, i, o); - print("DATA HEADER", "types count", i, o, ""); - const uint32_t N = i; + uint16_t data16; + status_t err = buf.nextUint16(&data16); + if (err != NO_ERROR) { + return err; + } + print("DATA HEADER", "target pkg", static_cast<uint32_t>(data16), ""); - for (uint32_t j = 0; j < N; ++j) { - NEXT(buf, i, o); - if (i == 0) { - print("", "padding", i, o, ""); - } else { + err = buf.nextUint16(&data16); + if (err != NO_ERROR) { + return err; + } + print("", "types count", static_cast<uint32_t>(data16), ""); + + uint32_t typeCount = static_cast<uint32_t>(data16); + while (typeCount > 0) { + typeCount--; + + err = buf.nextUint16(&data16); + if (err != NO_ERROR) { + return err; + } + const uint32_t targetTypeId = static_cast<uint32_t>(data16); + print("DATA BLOCK", "target type", targetTypeId, ""); + + err = buf.nextUint16(&data16); + if (err != NO_ERROR) { + return err; + } + print("", "overlay type", static_cast<uint32_t>(data16), ""); + + err = buf.nextUint16(&data16); + if (err != NO_ERROR) { + return err; + } + const uint32_t entryCount = static_cast<uint32_t>(data16); + print("", "entry count", entryCount, ""); + + err = buf.nextUint16(&data16); + if (err != NO_ERROR) { + return err; + } + const uint32_t entryOffset = static_cast<uint32_t>(data16); + print("", "entry offset", entryOffset, ""); + + for (uint32_t i = 0; i < entryCount; i++) { + uint32_t data32; + err = buf.nextUint32(&data32); + if (err != NO_ERROR) { + return err; + } + + uint32_t resID = (packageId << 24) | (targetTypeId << 16) | (entryOffset + i); String8 type; - const uint32_t numeric_type = (j + 1) << 16; - const uint32_t res_id = numeric_package | numeric_type; - if (resource_metadata(am, res_id, NULL, &type, NULL) < 0) { - // printe done from resource_metadata - return -1; + String8 name; + err = resource_metadata(am, resID, NULL, &type, &name); + if (err != NO_ERROR) { + return err; } - print("", "type offset", i, o, "absolute offset 0x%02x, %s", - i + IDMAP_HEADER_SIZE, type.string()); - types.add(numeric_type); + print("", "entry", data32, "%s/%s", type.string(), name.string()); } } - return 0; - } - - int parse_data_block(const IdmapBuffer& buf, const AssetManager& am, size_t numeric_type) - { - uint32_t i, o, n, id_offset; - const uint32_t numeric_package = package_id(am); - - NEXT(buf, i, o); - print("DATA BLOCK", "entry count", i, o, ""); - n = i; - - NEXT(buf, i, o); - print("", "entry offset", i, o, ""); - id_offset = i; - - for ( ; n > 0; --n) { - String8 type, name; - - NEXT(buf, i, o); - if (i == 0) { - print("", "padding", i, o, ""); - } else { - uint32_t res_id = numeric_package | numeric_type | id_offset; - if (resource_metadata(am, res_id, NULL, &type, &name) < 0) { - // printe done from resource_metadata - return -1; - } - print("", "entry", i, o, "%s/%s", type.string(), name.string()); - } - ++id_offset; - } - - return 0; + return NO_ERROR; } } -int idmap_inspect(const char *idmap_path) -{ +int idmap_inspect(const char *idmap_path) { IdmapBuffer buf; if (buf.init(idmap_path) < 0) { // printe done from IdmapBuffer::init return EXIT_FAILURE; } AssetManager am; - if (parse_idmap_header(buf, am) < 0) { + if (parse_idmap_header(buf, am) != NO_ERROR) { // printe done from parse_idmap_header return EXIT_FAILURE; } - Vector<uint32_t> types; - if (parse_data_header(buf, am, types) < 0) { + if (parse_data(buf, am) != NO_ERROR) { // printe done from parse_data_header return EXIT_FAILURE; } - const size_t N = types.size(); - for (size_t i = 0; i < N; ++i) { - if (parse_data_block(buf, am, types.itemAt(i)) < 0) { - // printe done from parse_data_block - return EXIT_FAILURE; - } - } return EXIT_SUCCESS; }
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp index c5fc941..1153f38 100644 --- a/cmds/idmap/scan.cpp +++ b/cmds/idmap/scan.cpp
@@ -119,7 +119,8 @@ int parse_manifest(const void *data, size_t size, const char *target_package_name) { - ResXMLTree parser(data, size); + ResXMLTree parser; + parser.setTo(data, size); if (parser.getError() != NO_ERROR) { ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError()); return -1;
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java index 92c6a51..6a8fb05 100644 --- a/cmds/media/src/com/android/commands/media/Media.java +++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -17,12 +17,19 @@ package com.android.commands.media; -import android.app.PendingIntent; +import android.app.ActivityManager; import android.content.Context; -import android.graphics.Bitmap; -import android.media.IAudioService; -import android.media.IRemoteControlDisplay; +import android.content.pm.ParceledListSlice; +import android.media.MediaMetadata; +import android.media.session.ISessionController; +import android.media.session.ISessionControllerCallback; +import android.media.session.ISessionManager; +import android.media.session.MediaController; +import android.media.session.ParcelableVolumeInfo; +import android.media.session.PlaybackState; import android.os.Bundle; +import android.os.HandlerThread; +import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -30,16 +37,17 @@ import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; + import com.android.internal.os.BaseCommand; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; +import java.util.List; public class Media extends BaseCommand { - - private IAudioService mAudioService; + private ISessionManager mSessionService; /** * Command-line entry point. @@ -54,29 +62,35 @@ out.println( "usage: media [subcommand] [options]\n" + " media dispatch KEY\n" + - " media remote-display\n" + + " media list-sessions\n" + + " media monitor <tag>\n" + "\n" + - "media dispatch: dispatch a media key to the current media client.\n" + + "media dispatch: dispatch a media key to the system.\n" + " KEY may be: play, pause, play-pause, mute, headsethook,\n" + - " stop, next, previous, rewind, recordm fast-forword.\n" + - "media remote-display: monitor remote display updates.\n" + " stop, next, previous, rewind, record, fast-forword.\n" + + "media list-sessions: print a list of the current sessions.\n" + + "media monitor: monitor updates to the specified session.\n" + + " Use the tag from list-sessions.\n" ); } public void onRun() throws Exception { - mAudioService = IAudioService.Stub.asInterface(ServiceManager.checkService( - Context.AUDIO_SERVICE)); - if (mAudioService == null) { + mSessionService = ISessionManager.Stub.asInterface(ServiceManager.checkService( + Context.MEDIA_SESSION_SERVICE)); + if (mSessionService == null) { System.err.println(NO_SYSTEM_ERROR_CODE); - throw new AndroidException("Can't connect to audio service; is the system running?"); + throw new AndroidException( + "Can't connect to media session service; is the system running?"); } String op = nextArgRequired(); if (op.equals("dispatch")) { runDispatch(); - } else if (op.equals("remote-display")) { - runRemoteDisplay(); + } else if (op.equals("list-sessions")) { + runListSessions(); + } else if (op.equals("monitor")) { + runMonitor(); } else { showError("Error: unknown command '" + op + "'"); return; @@ -85,11 +99,42 @@ private void sendMediaKey(KeyEvent event) { try { - mAudioService.dispatchMediaKeyEvent(event); + mSessionService.dispatchMediaKeyEvent(event, false); } catch (RemoteException e) { } } + private void runMonitor() throws Exception { + String id = nextArgRequired(); + if (id == null) { + showError("Error: must include a session id"); + return; + } + boolean success = false; + try { + List<IBinder> sessions = mSessionService + .getSessions(null, ActivityManager.getCurrentUser()); + for (IBinder session : sessions) { + ISessionController controller = ISessionController.Stub.asInterface(session); + try { + if (controller != null && id.equals(controller.getTag())) { + ControllerMonitor monitor = new ControllerMonitor(controller); + monitor.run(); + success = true; + break; + } + } catch (RemoteException e) { + // ignore + } + } + } catch (Exception e) { + System.out.println("***Error monitoring session*** " + e.getMessage()); + } + if (!success) { + System.out.println("No session found with id " + id); + } + } + private void runDispatch() throws Exception { String cmd = nextArgRequired(); int keycode; @@ -127,65 +172,80 @@ KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); } - class RemoteDisplayMonitor extends IRemoteControlDisplay.Stub { - RemoteDisplayMonitor() { - } + class ControllerMonitor extends ISessionControllerCallback.Stub { + private final ISessionController mController; - - @Override - public void setCurrentClientId(int clientGeneration, PendingIntent clientMediaIntent, - boolean clearing) { - System.out.println("New client: id=" + clientGeneration - + " intent=" + clientMediaIntent + " clearing=" + clearing); + public ControllerMonitor(ISessionController controller) { + mController = controller; } @Override - public void setEnabled(boolean enabled) { - System.out.println("New enable state= " + (enabled ? "enabled" : "disabled")); + public void onSessionDestroyed() { + System.out.println("onSessionDestroyed. Enter q to quit."); + } @Override - public void setPlaybackState(int generationId, int state, long stateChangeTimeMs, - long currentPosMs, float speed) { - System.out.println("New state: id=" + generationId + " state=" + state - + " time=" + stateChangeTimeMs + " pos=" + currentPosMs + " speed=" + speed); + public void onEvent(String event, Bundle extras) { + System.out.println("onSessionEvent event=" + event + ", extras=" + extras); } @Override - public void setTransportControlInfo(int generationId, int transportControlFlags, - int posCapabilities) { - System.out.println("New control info: id=" + generationId - + " flags=0x" + Integer.toHexString(transportControlFlags) - + " cap=0x" + Integer.toHexString(posCapabilities)); + public void onPlaybackStateChanged(PlaybackState state) { + System.out.println("onPlaybackStateChanged " + state); } @Override - public void setMetadata(int generationId, Bundle metadata) { - System.out.println("New metadata: id=" + generationId - + " data=" + metadata); + public void onMetadataChanged(MediaMetadata metadata) { + String mmString = metadata == null ? null : "title=" + metadata + .getDescription(); + System.out.println("onMetadataChanged " + mmString); } @Override - public void setArtwork(int generationId, Bitmap artwork) { - System.out.println("New artwork: id=" + generationId - + " art=" + artwork); + public void onQueueChanged(ParceledListSlice queue) throws RemoteException { + System.out.println("onQueueChanged, " + + (queue == null ? "null queue" : " size=" + queue.getList().size())); } @Override - public void setAllMetadata(int generationId, Bundle metadata, Bitmap artwork) { - System.out.println("New metadata+artwork: id=" + generationId - + " data=" + metadata + " art=" + artwork); + public void onQueueTitleChanged(CharSequence title) throws RemoteException { + System.out.println("onQueueTitleChange " + title); + } + + @Override + public void onExtrasChanged(Bundle extras) throws RemoteException { + System.out.println("onExtrasChanged " + extras); + } + + @Override + public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException { + System.out.println("onVolumeInfoChanged " + info); } void printUsageMessage() { - System.out.println("Monitoring remote control displays... available commands:"); + try { + System.out.println("V2Monitoring session " + mController.getTag() + + "... available commands: play, pause, next, previous"); + } catch (RemoteException e) { + System.out.println("Error trying to monitor session!"); + } System.out.println("(q)uit: finish monitoring"); } void run() throws RemoteException { printUsageMessage(); - - mAudioService.registerRemoteControlDisplay(this, 0, 0); + HandlerThread cbThread = new HandlerThread("MediaCb") { + @Override + protected void onLooperPrepared() { + try { + mController.registerCallbackListener(ControllerMonitor.this); + } catch (RemoteException e) { + System.out.println("Error registering monitor callback"); + } + } + }; + cbThread.start(); try { InputStreamReader converter = new InputStreamReader(System.in); @@ -198,6 +258,14 @@ addNewline = false; } else if ("q".equals(line) || "quit".equals(line)) { break; + } else if ("play".equals(line)) { + mController.play(); + } else if ("pause".equals(line)) { + mController.pause(); + } else if ("next".equals(line)) { + mController.next(); + } else if ("previous".equals(line)) { + mController.previous(); } else { System.out.println("Invalid command: " + line); } @@ -209,17 +277,38 @@ printUsageMessage(); } } - } catch (IOException e) { e.printStackTrace(); } finally { - mAudioService.unregisterRemoteControlDisplay(this); + cbThread.getLooper().quit(); + try { + mController.unregisterCallbackListener(this); + } catch (Exception e) { + // ignoring + } } } } - private void runRemoteDisplay() throws Exception { - RemoteDisplayMonitor monitor = new RemoteDisplayMonitor(); - monitor.run(); + private void runListSessions() { + System.out.println("Sessions:"); + try { + List<IBinder> sessions = mSessionService + .getSessions(null, ActivityManager.getCurrentUser()); + for (IBinder session : sessions) { + + ISessionController controller = ISessionController.Stub.asInterface(session); + if (controller != null) { + try { + System.out.println(" tag=" + controller.getTag() + + ", package=" + controller.getPackageName()); + } catch (RemoteException e) { + // ignore + } + } + } + } catch (Exception e) { + System.out.println("***Error listing sessions***"); + } } }
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 75b0a82..5e9d8f7 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -18,16 +18,23 @@ import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.IActivityManager; +import android.app.PackageInstallObserver; import android.content.ComponentName; +import android.content.IIntentReceiver; +import android.content.IIntentSender; +import android.content.Intent; +import android.content.IntentSender; import android.content.pm.ApplicationInfo; -import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageDeleteObserver; -import android.content.pm.IPackageInstallObserver; +import android.content.pm.IPackageInstaller; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageInstaller.SessionInfo; +import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; @@ -39,30 +46,43 @@ import android.content.res.Resources; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.os.IUserManager; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.content.PackageHelper; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.SizedInputStream; + +import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.security.InvalidAlgorithmParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.WeakHashMap; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import com.android.internal.content.PackageHelper; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; public final class Pm { + private static final String TAG = "Pm"; + IPackageManager mPm; + IPackageInstaller mInstaller; IUserManager mUm; private WeakHashMap<String, Resources> mResourceCache @@ -76,10 +96,18 @@ "Error: Could not access the Package Manager. Is the system running?"; public static void main(String[] args) { - new Pm().run(args); + try { + new Pm().run(args); + } catch (Exception e) { + Log.e(TAG, "Error", e); + System.err.println("Error: " + e); + if (e instanceof RemoteException) { + System.err.println(PM_NOT_RUNNING_ERR); + } + } } - public void run(String[] args) { + public void run(String[] args) throws IOException, RemoteException { boolean validCommand = false; if (args.length < 1) { showUsage(); @@ -92,6 +120,7 @@ System.err.println(PM_NOT_RUNNING_ERR); return; } + mInstaller = mPm.getPackageInstaller(); mArgs = args; String op = args[0]; @@ -117,6 +146,31 @@ return; } + if ("install-create".equals(op)) { + runInstallCreate(); + return; + } + + if ("install-write".equals(op)) { + runInstallWrite(); + return; + } + + if ("install-commit".equals(op)) { + runInstallCommit(); + return; + } + + if ("install-abandon".equals(op) || "install-destroy".equals(op)) { + runInstallAbandon(); + return; + } + + if ("set-installer".equals(op)) { + runSetInstaller(); + return; + } + if ("uninstall".equals(op)) { runUninstall(); return; @@ -147,13 +201,13 @@ return; } - if ("block".equals(op)) { - runSetBlockedSetting(true); + if ("hide".equals(op)) { + runSetHiddenSetting(true); return; } - if ("unblock".equals(op)) { - runSetBlockedSetting(false); + if ("unhide".equals(op)) { + runSetHiddenSetting(false); return; } @@ -202,6 +256,11 @@ return; } + if ("force-dex-opt".equals(op)) { + runForceDexOpt(); + return; + } + try { if (args.length == 1) { if (args[0].equalsIgnoreCase("-l")) { @@ -698,14 +757,23 @@ ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg); } - class PackageInstallObserver extends IPackageInstallObserver.Stub { + class LocalPackageInstallObserver extends PackageInstallObserver { boolean finished; int result; + String extraPermission; + String extraPackage; - public void packageInstalled(String name, int status) { - synchronized( this) { + @Override + public void onPackageInstalled(String name, int status, String msg, Bundle extras) { + synchronized (this) { finished = true; result = status; + if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) { + extraPermission = extras.getString( + PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION); + extraPackage = extras.getString( + PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); + } notifyAll(); } } @@ -715,7 +783,8 @@ * Converts a failure code into a string by using reflection to find a matching constant * in PackageManager. */ - private String installFailureToString(int result) { + private String installFailureToString(LocalPackageInstallObserver obs) { + final int result = obs.result; Field[] fields = PackageManager.class.getFields(); for (Field f: fields) { if (f.getType() == int.class) { @@ -730,7 +799,16 @@ // get the int value and compare it to result. try { if (result == f.getInt(null)) { - return fieldName; + StringBuilder sb = new StringBuilder(64); + sb.append(fieldName); + if (obs.extraPermission != null) { + sb.append(" perm="); + sb.append(obs.extraPermission); + } + if (obs.extraPackage != null) { + sb.append(" pkg=" + obs.extraPackage); + } + return sb.toString(); } } catch (IllegalAccessException e) { // this shouldn't happen since we only look for public static fields. @@ -787,18 +865,12 @@ } private void runInstall() { - int installFlags = PackageManager.INSTALL_ALL_USERS; + int installFlags = 0; + int userId = UserHandle.USER_ALL; String installerPackageName = null; String opt; - String algo = null; - byte[] iv = null; - byte[] key = null; - - String macAlgo = null; - byte[] macKey = null; - byte[] tag = null; String originatingUriString = null; String referrer = null; String abi = null; @@ -824,42 +896,6 @@ installFlags |= PackageManager.INSTALL_INTERNAL; } else if (opt.equals("-d")) { installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; - } else if (opt.equals("--algo")) { - algo = nextOptionData(); - if (algo == null) { - System.err.println("Error: must supply argument for --algo"); - return; - } - } else if (opt.equals("--iv")) { - iv = hexToBytes(nextOptionData()); - if (iv == null) { - System.err.println("Error: must supply argument for --iv"); - return; - } - } else if (opt.equals("--key")) { - key = hexToBytes(nextOptionData()); - if (key == null) { - System.err.println("Error: must supply argument for --key"); - return; - } - } else if (opt.equals("--macalgo")) { - macAlgo = nextOptionData(); - if (macAlgo == null) { - System.err.println("Error: must supply argument for --macalgo"); - return; - } - } else if (opt.equals("--mackey")) { - macKey = hexToBytes(nextOptionData()); - if (macKey == null) { - System.err.println("Error: must supply argument for --mackey"); - return; - } - } else if (opt.equals("--tag")) { - tag = hexToBytes(nextOptionData()); - if (tag == null) { - System.err.println("Error: must supply argument for --tag"); - return; - } } else if (opt.equals("--originating-uri")) { originatingUriString = nextOptionData(); if (originatingUriString == null) { @@ -873,70 +909,20 @@ return; } } else if (opt.equals("--abi")) { - abi = nextOptionData(); - if (abi == null) { - System.err.println("Error: must supply argument for --abi"); - return; - } + abi = checkAbiArgument(nextOptionData()); + } else if (opt.equals("--user")) { + userId = Integer.parseInt(nextOptionData()); } else { System.err.println("Error: Unknown option: " + opt); return; } } - if (abi != null) { - final String[] supportedAbis = Build.SUPPORTED_ABIS; - boolean matched = false; - for (String supportedAbi : supportedAbis) { - if (supportedAbi.equals(abi)) { - matched = true; - break; - } - } - - if (!matched) { - System.err.println("Error: abi " + abi + " not supported on this device."); - return; - } + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_OWNER; + installFlags |= PackageManager.INSTALL_ALL_USERS; } - final ContainerEncryptionParams encryptionParams; - if (algo != null || iv != null || key != null || macAlgo != null || macKey != null - || tag != null) { - if (algo == null || iv == null || key == null) { - System.err.println("Error: all of --algo, --iv, and --key must be specified"); - return; - } - - if (macAlgo != null || macKey != null || tag != null) { - if (macAlgo == null || macKey == null || tag == null) { - System.err.println("Error: all of --macalgo, --mackey, and --tag must " - + "be specified"); - return; - } - } - - try { - final SecretKey encKey = new SecretKeySpec(key, "RAW"); - - final SecretKey macSecretKey; - if (macKey == null || macKey.length == 0) { - macSecretKey = null; - } else { - macSecretKey = new SecretKeySpec(macKey, "RAW"); - } - - encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv), - encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - return; - } - } else { - encryptionParams = null; - } - - final Uri apkURI; final Uri verificationURI; final Uri originatingURI; final Uri referrerURI; @@ -956,9 +942,7 @@ // Populate apkURI, must be present final String apkFilePath = nextArg(); System.err.println("\tpkg: " + apkFilePath); - if (apkFilePath != null) { - apkURI = Uri.fromFile(new File(apkFilePath)); - } else { + if (apkFilePath == null) { System.err.println("Error: no package specified"); return; } @@ -972,14 +956,13 @@ verificationURI = null; } - PackageInstallObserver obs = new PackageInstallObserver(); + LocalPackageInstallObserver obs = new LocalPackageInstallObserver(); try { VerificationParams verificationParams = new VerificationParams(verificationURI, originatingURI, referrerURI, VerificationParams.NO_UID, null); - mPm.installPackageWithVerificationEncryptionAndAbiOverride(apkURI, obs, - installFlags, installerPackageName, verificationParams, - encryptionParams, abi); + mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, + installerPackageName, verificationParams, abi, userId); synchronized (obs) { while (!obs.finished) { @@ -992,7 +975,7 @@ System.out.println("Success"); } else { System.err.println("Failure [" - + installFailureToString(obs.result) + + installFailureToString(obs) + "]"); } } @@ -1002,39 +985,200 @@ } } - /** - * Convert a string containing hex-encoded bytes to a byte array. - * - * @param input String containing hex-encoded bytes - * @return input as an array of bytes - */ - private byte[] hexToBytes(String input) { - if (input == null) { - return null; + private void runInstallCreate() throws RemoteException { + int userId = UserHandle.USER_ALL; + String installerPackageName = null; + + final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL); + + String opt; + while ((opt = nextOption()) != null) { + if (opt.equals("-l")) { + params.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; + } else if (opt.equals("-r")) { + params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; + } else if (opt.equals("-i")) { + installerPackageName = nextArg(); + if (installerPackageName == null) { + throw new IllegalArgumentException("Missing installer package"); + } + } else if (opt.equals("-t")) { + params.installFlags |= PackageManager.INSTALL_ALLOW_TEST; + } else if (opt.equals("-s")) { + params.installFlags |= PackageManager.INSTALL_EXTERNAL; + } else if (opt.equals("-f")) { + params.installFlags |= PackageManager.INSTALL_INTERNAL; + } else if (opt.equals("-d")) { + params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; + } else if (opt.equals("--originating-uri")) { + params.originatingUri = Uri.parse(nextOptionData()); + } else if (opt.equals("--referrer")) { + params.referrerUri = Uri.parse(nextOptionData()); + } else if (opt.equals("-p")) { + params.mode = SessionParams.MODE_INHERIT_EXISTING; + params.appPackageName = nextOptionData(); + if (params.appPackageName == null) { + throw new IllegalArgumentException("Missing inherit package name"); + } + } else if (opt.equals("-S")) { + params.setSize(Long.parseLong(nextOptionData())); + } else if (opt.equals("--abi")) { + params.abiOverride = checkAbiArgument(nextOptionData()); + } else if (opt.equals("--user")) { + userId = Integer.parseInt(nextOptionData()); + } else { + throw new IllegalArgumentException("Unknown option " + opt); + } } - final int inputLength = input.length(); - if ((inputLength % 2) != 0) { - System.err.print("Invalid length; must be multiple of 2"); - return null; + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_OWNER; + params.installFlags |= PackageManager.INSTALL_ALL_USERS; } - final int byteLength = inputLength / 2; - final byte[] output = new byte[byteLength]; + final int sessionId = mInstaller.createSession(params, installerPackageName, userId); - int inputIndex = 0; - int byteIndex = 0; - while (inputIndex < inputLength) { - output[byteIndex++] = (byte) Integer.parseInt( - input.substring(inputIndex, inputIndex + 2), 16); - inputIndex += 2; + // NOTE: adb depends on parsing this string + System.out.println("Success: created install session [" + sessionId + "]"); + } + + private void runInstallWrite() throws IOException, RemoteException { + long sizeBytes = -1; + + String opt; + while ((opt = nextOption()) != null) { + if (opt.equals("-S")) { + sizeBytes = Long.parseLong(nextOptionData()); + } else { + throw new IllegalArgumentException("Unknown option: " + opt); + } } - return output; + final int sessionId = Integer.parseInt(nextArg()); + final String splitName = nextArg(); + + String path = nextArg(); + if ("-".equals(path)) { + path = null; + } else if (path != null) { + final File file = new File(path); + if (file.isFile()) { + sizeBytes = file.length(); + } + } + + final SessionInfo info = mInstaller.getSessionInfo(sessionId); + + PackageInstaller.Session session = null; + InputStream in = null; + OutputStream out = null; + try { + session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); + + if (path != null) { + in = new FileInputStream(path); + } else { + in = new SizedInputStream(System.in, sizeBytes); + } + out = session.openWrite(splitName, 0, sizeBytes); + + int total = 0; + byte[] buffer = new byte[65536]; + int c; + while ((c = in.read(buffer)) != -1) { + total += c; + out.write(buffer, 0, c); + + if (info.sizeBytes > 0) { + final float fraction = ((float) c / (float) info.sizeBytes); + session.addProgress(fraction); + } + } + session.fsync(out); + + System.out.println("Success: streamed " + total + " bytes"); + } finally { + IoUtils.closeQuietly(out); + IoUtils.closeQuietly(in); + IoUtils.closeQuietly(session); + } + } + + private void runInstallCommit() throws RemoteException { + final int sessionId = Integer.parseInt(nextArg()); + + PackageInstaller.Session session = null; + try { + session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); + + final LocalIntentReceiver receiver = new LocalIntentReceiver(); + session.commit(receiver.getIntentSender()); + + final Intent result = receiver.getResult(); + final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, + PackageInstaller.STATUS_FAILURE); + if (status == PackageInstaller.STATUS_SUCCESS) { + System.out.println("Success"); + } else { + Log.e(TAG, "Failure details: " + result.getExtras()); + System.out.println("Failure [" + + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); + return; + } + } finally { + IoUtils.closeQuietly(session); + } + } + + private void runInstallAbandon() throws RemoteException { + final int sessionId = Integer.parseInt(nextArg()); + + PackageInstaller.Session session = null; + try { + session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); + session.abandon(); + System.out.println("Success"); + } finally { + IoUtils.closeQuietly(session); + } + } + + private void runSetInstaller() throws RemoteException { + final String targetPackage = nextArg(); + final String installerPackageName = nextArg(); + + if (targetPackage == null || installerPackageName == null) { + throw new IllegalArgumentException( + "must provide both target and installer package names"); + } + + mPm.setInstallerPackageName(targetPackage, installerPackageName); + System.out.println("Success"); } public void runCreateUser() { String name; + int userId = -1; + int flags = 0; + String opt; + while ((opt = nextOption()) != null) { + if ("--profileOf".equals(opt)) { + String optionData = nextOptionData(); + if (optionData == null || !isNumber(optionData)) { + System.err.println("Error: no USER_ID specified"); + showUsage(); + return; + } else { + userId = Integer.parseInt(optionData); + } + } else if ("--managed".equals(opt)) { + flags |= UserInfo.FLAG_MANAGED_PROFILE; + } else { + System.err.println("Error: unknown option " + opt); + showUsage(); + return; + } + } String arg = nextArg(); if (arg == null) { System.err.println("Error: no user name specified."); @@ -1042,7 +1186,12 @@ } name = arg; try { - final UserInfo info = mUm.createUser(name, 0); + UserInfo info = null; + if (userId < 0) { + info = mUm.createUser(name, flags); + } else { + info = mUm.createProfileForUser(name, flags, userId); + } if (info != null) { System.out.println("Success: created user id " + info.id); } else { @@ -1082,13 +1231,16 @@ public void runListUsers() { try { + IActivityManager am = ActivityManagerNative.getDefault(); + List<UserInfo> users = mUm.getUsers(false); if (users == null) { System.err.println("Error: couldn't get users"); } else { System.out.println("Users:"); for (int i = 0; i < users.size(); i++) { - System.out.println("\t" + users.get(i).toString()); + String running = am.isUserRunning(users.get(i).id, false) ? " running" : ""; + System.out.println("\t" + users.get(i).toString() + running); } } } catch (RemoteException e) { @@ -1101,26 +1253,32 @@ System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers()); } - class PackageDeleteObserver extends IPackageDeleteObserver.Stub { - boolean finished; - boolean result; - - public void packageDeleted(String packageName, int returnCode) { - synchronized (this) { - finished = true; - result = returnCode == PackageManager.DELETE_SUCCEEDED; - notifyAll(); - } + public void runForceDexOpt() { + final String packageName = nextArg(); + try { + mPm.forceDexOpt(packageName); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); } } - private void runUninstall() { - int unInstallFlags = PackageManager.DELETE_ALL_USERS; + private void runUninstall() throws RemoteException { + int flags = 0; + int userId = UserHandle.USER_ALL; String opt; while ((opt=nextOption()) != null) { if (opt.equals("-k")) { - unInstallFlags |= PackageManager.DELETE_KEEP_DATA; + flags |= PackageManager.DELETE_KEEP_DATA; + } else if (opt.equals("--user")) { + String param = nextArg(); + if (isNumber(param)) { + userId = Integer.parseInt(param); + } else { + showUsage(); + System.err.println("Error: Invalid user: " + param); + return; + } } else { System.err.println("Error: Unknown option: " + opt); return; @@ -1133,34 +1291,48 @@ showUsage(); return; } - boolean result = deletePackage(pkg, unInstallFlags); - if (result) { + + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_OWNER; + flags |= PackageManager.DELETE_ALL_USERS; + } else { + PackageInfo info; + try { + info = mPm.getPackageInfo(pkg, 0, userId); + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(PM_NOT_RUNNING_ERR); + return; + } + if (info == null) { + System.err.println("Failure - not installed for " + userId); + return; + } + final boolean isSystem = + (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + // If we are being asked to delete a system app for just one + // user set flag so it disables rather than reverting to system + // version of the app. + if (isSystem) { + flags |= PackageManager.DELETE_SYSTEM_APP; + } + } + + final LocalIntentReceiver receiver = new LocalIntentReceiver(); + mInstaller.uninstall(pkg, flags, receiver.getIntentSender(), userId); + + final Intent result = receiver.getResult(); + final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, + PackageInstaller.STATUS_FAILURE); + if (status == PackageInstaller.STATUS_SUCCESS) { System.out.println("Success"); } else { - System.out.println("Failure"); + Log.e(TAG, "Failure details: " + result.getExtras()); + System.out.println("Failure [" + + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); } } - private boolean deletePackage(String pkg, int unInstallFlags) { - PackageDeleteObserver obs = new PackageDeleteObserver(); - try { - mPm.deletePackageAsUser(pkg, obs, UserHandle.USER_OWNER, unInstallFlags); - - synchronized (obs) { - while (!obs.finished) { - try { - obs.wait(); - } catch (InterruptedException e) { - } - } - } - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - } - return obs.result; - } - static class ClearDataObserver extends IPackageDataObserver.Stub { boolean finished; boolean result; @@ -1173,7 +1345,6 @@ notifyAll(); } } - } private void runClear() { @@ -1290,7 +1461,7 @@ } } - private void runSetBlockedSetting(boolean state) { + private void runSetHiddenSetting(boolean state) { int userId = 0; String option = nextOption(); if (option != null && option.equals("--user")) { @@ -1311,9 +1482,9 @@ return; } try { - mPm.setApplicationBlockedSettingAsUser(pkg, state, userId); - System.err.println("Package " + pkg + " new blocked state: " - + mPm.getApplicationBlockedSettingAsUser(pkg, userId)); + mPm.setApplicationHiddenSettingAsUser(pkg, state, userId); + System.err.println("Package " + pkg + " new hidden state: " + + mPm.getApplicationHiddenSettingAsUser(pkg, userId)); } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); @@ -1456,6 +1627,12 @@ if (info != null && info.applicationInfo != null) { System.out.print("package:"); System.out.println(info.applicationInfo.sourceDir); + if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) { + for (String splitSourceDir : info.applicationInfo.splitSourceDirs) { + System.out.print("package:"); + System.out.println(splitSourceDir); + } + } } } catch (RemoteException e) { System.err.println(e.toString()); @@ -1481,6 +1658,54 @@ } } + private static String checkAbiArgument(String abi) { + if (TextUtils.isEmpty(abi)) { + throw new IllegalArgumentException("Missing ABI argument"); + } + + if ("-".equals(abi)) { + return abi; + } + + final String[] supportedAbis = Build.SUPPORTED_ABIS; + for (String supportedAbi : supportedAbis) { + if (supportedAbi.equals(abi)) { + return abi; + } + } + + throw new IllegalArgumentException("ABI " + abi + " not supported on this device"); + } + + private static class LocalIntentReceiver { + private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>(); + + private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { + @Override + public int send(int code, Intent intent, String resolvedType, + IIntentReceiver finishedReceiver, String requiredPermission) { + try { + mResult.offer(intent, 5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return 0; + } + }; + + public IntentSender getIntentSender() { + return new IntentSender((IIntentSender) mLocalSender); + } + + public Intent getResult() { + try { + return mResult.take(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + private String nextOption() { if (mNextArg >= mArgs.length) { return null; @@ -1537,24 +1762,27 @@ System.err.println(" pm list users"); System.err.println(" pm path PACKAGE"); System.err.println(" pm dump PACKAGE"); - System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); - System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]"); - System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH"); - System.err.println(" pm uninstall [-k] PACKAGE"); + System.err.println(" pm install [-lrtsfd] [-i PACKAGE] [PATH]"); + System.err.println(" pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]"); + System.err.println(" pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]"); + System.err.println(" pm install-commit SESSION_ID"); + System.err.println(" pm install-abandon SESSION_ID"); + System.err.println(" pm uninstall [-k] [--user USER_ID] PACKAGE"); + System.err.println(" pm set-installer PACKAGE INSTALLER"); System.err.println(" pm clear [--user USER_ID] PACKAGE"); System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT"); - System.err.println(" pm block [--user USER_ID] PACKAGE_OR_COMPONENT"); - System.err.println(" pm unblock [--user USER_ID] PACKAGE_OR_COMPONENT"); + System.err.println(" pm hide [--user USER_ID] PACKAGE_OR_COMPONENT"); + System.err.println(" pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm grant PACKAGE PERMISSION"); System.err.println(" pm revoke PACKAGE PERMISSION"); System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]"); System.err.println(" pm get-install-location"); System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); System.err.println(" pm trim-caches DESIRED_FREE_SPACE"); - System.err.println(" pm create-user USER_NAME"); + System.err.println(" pm create-user [--profileOf USER_ID] [--managed] USER_NAME"); System.err.println(" pm remove-user USER_ID"); System.err.println(" pm get-max-users"); System.err.println(""); @@ -1589,16 +1817,28 @@ System.err.println(""); System.err.println("pm path: print the path to the .apk of the given PACKAGE."); System.err.println(""); - System.err.println("pm dump: print system state associated w ith the given PACKAGE."); + System.err.println("pm dump: print system state associated with the given PACKAGE."); System.err.println(""); - System.err.println("pm install: installs a package to the system. Options:"); - System.err.println(" -l: install the package with FORWARD_LOCK."); - System.err.println(" -r: reinstall an exisiting app, keeping its data."); - System.err.println(" -t: allow test .apks to be installed."); - System.err.println(" -i: specify the installer package name."); - System.err.println(" -s: install package on sdcard."); - System.err.println(" -f: install package on internal flash."); - System.err.println(" -d: allow version code downgrade."); + System.err.println("pm install: install a single legacy package"); + System.err.println("pm install-create: create an install session"); + System.err.println(" -l: forward lock application"); + System.err.println(" -r: replace existing application"); + System.err.println(" -t: allow test packages"); + System.err.println(" -i: specify the installer package name"); + System.err.println(" -s: install application on sdcard"); + System.err.println(" -f: install application on internal flash"); + System.err.println(" -d: allow version code downgrade"); + System.err.println(" -p: partial application install"); + System.err.println(" -S: size in bytes of entire session"); + System.err.println(""); + System.err.println("pm install-write: write a package into existing session; path may"); + System.err.println(" be '-' to read from stdin"); + System.err.println(" -S: size in bytes of package, required for stdin"); + System.err.println(""); + System.err.println("pm install-commit: perform install of fully staged session"); + System.err.println("pm install-abandon: abandon session"); + System.err.println(""); + System.err.println("pm set-installer: set installer package name"); System.err.println(""); System.err.println("pm uninstall: removes a package from the system. Options:"); System.err.println(" -k: keep the data and cache directories around after package removal."); @@ -1632,5 +1872,6 @@ System.err.println(""); System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,"); System.err.println(" deleting all data associated with that user"); + System.err.println(""); } }
diff --git a/cmds/screencap/Android.mk b/cmds/screencap/Android.mk index ca8008b..5c11b75 100644 --- a/cmds/screencap/Android.mk +++ b/cmds/screencap/Android.mk
@@ -16,11 +16,4 @@ LOCAL_MODULE_TAGS := optional -LOCAL_C_INCLUDES += \ - external/skia/include/core \ - external/skia/include/effects \ - external/skia/include/images \ - external/skia/src/ports \ - external/skia/include/utils - include $(BUILD_EXECUTABLE)
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index a57de01..6b2a0e2 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp
@@ -52,13 +52,13 @@ ); } -static SkBitmap::Config flinger2skia(PixelFormat f) +static SkColorType flinger2skia(PixelFormat f) { switch (f) { case PIXEL_FORMAT_RGB_565: - return SkBitmap::kRGB_565_Config; + return kRGB_565_SkColorType; default: - return SkBitmap::kARGB_8888_Config; + return kN32_SkColorType; } } @@ -141,7 +141,7 @@ ScreenshotClient screenshot; sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId); - if (display != NULL && screenshot.update(display) == NO_ERROR) { + if (display != NULL && screenshot.update(display, Rect(), false) == NO_ERROR) { base = screenshot.getPixels(); w = screenshot.getWidth(); h = screenshot.getHeight(); @@ -174,9 +174,10 @@ if (base) { if (png) { + const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f), + kPremul_SkAlphaType); SkBitmap b; - b.setConfig(flinger2skia(f), w, h, s*bytesPerPixel(f)); - b.setPixels((void*)base); + b.installPixels(info, const_cast<void*>(base), s*bytesPerPixel(f)); SkDynamicMemoryWStream stream; SkImageEncoder::EncodeStream(&stream, b, SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
diff --git a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java index dce0a75..e6847a9 100644 --- a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java +++ b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
@@ -20,6 +20,7 @@ import android.app.IActivityManager; import android.app.IActivityManager.ContentProviderHolder; import android.content.IContentProvider; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -33,7 +34,8 @@ enum CommandVerb { UNSPECIFIED, GET, - PUT + PUT, + DELETE } static String[] mArgs; @@ -74,6 +76,8 @@ mVerb = CommandVerb.GET; } else if ("put".equalsIgnoreCase(arg)) { mVerb = CommandVerb.PUT; + } else if ("delete".equalsIgnoreCase(arg)) { + mVerb = CommandVerb.DELETE; } else { // invalid System.err.println("Invalid command: " + arg); @@ -87,7 +91,7 @@ break; // invalid } mTable = arg.toLowerCase(); - } else if (mVerb == CommandVerb.GET) { + } else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) { mKey = arg; if (mNextArg >= mArgs.length) { valid = true; @@ -136,6 +140,10 @@ case PUT: putForUser(provider, mUser, mTable, mKey, mValue); break; + case DELETE: + System.out.println("Deleted " + + deleteForUser(provider, mUser, mTable, mKey) + " rows"); + break; default: System.err.println("Unspecified command"); break; @@ -211,9 +219,31 @@ } } + int deleteForUser(IContentProvider provider, int userHandle, + final String table, final String key) { + Uri targetUri; + if ("system".equals(table)) targetUri = Settings.System.getUriFor(key); + else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key); + else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key); + else { + System.err.println("Invalid table; no delete performed"); + throw new IllegalArgumentException("Invalid table " + table); + } + + int num = 0; + try { + num = provider.delete(null, targetUri, null, null); + } catch (RemoteException e) { + System.err.println("Can't clear key " + key + " in " + table + " for user " + + userHandle); + } + return num; + } + private static void printUsage() { System.err.println("usage: settings [--user NUM] get namespace key"); System.err.println(" settings [--user NUM] put namespace key value"); + System.err.println(" settings [--user NUM] delete namespace key"); System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive"); System.err.println("If '--user NUM' is not given, the operations are performed on the owner user."); }
diff --git a/cmds/svc/src/com/android/commands/svc/DataCommand.java b/cmds/svc/src/com/android/commands/svc/DataCommand.java index 72cb86d..406e33b 100644 --- a/cmds/svc/src/com/android/commands/svc/DataCommand.java +++ b/cmds/svc/src/com/android/commands/svc/DataCommand.java
@@ -36,9 +36,7 @@ return shortHelp() + "\n" + "\n" + "usage: svc data [enable|disable]\n" - + " Turn mobile data on or off.\n\n" - + " svc data prefer\n" - + " Set mobile as the preferred data network\n"; + + " Turn mobile data on or off.\n\n"; } public void run(String[] args) { @@ -51,15 +49,6 @@ } else if ("disable".equals(args[1])) { flag = false; validCommand = true; - } else if ("prefer".equals(args[1])) { - IConnectivityManager connMgr = - IConnectivityManager.Stub.asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); - try { - connMgr.setNetworkPreference(ConnectivityManager.TYPE_MOBILE); - } catch (RemoteException e) { - System.err.println("Failed to set preferred network: " + e); - } - return; } if (validCommand) { ITelephony phoneMgr @@ -78,4 +67,4 @@ } System.err.println(longHelp()); } -} \ No newline at end of file +}
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java index d29e8b2..39f0e35 100644 --- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java +++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
@@ -36,9 +36,7 @@ return shortHelp() + "\n" + "\n" + "usage: svc wifi [enable|disable]\n" - + " Turn Wi-Fi on or off.\n\n" - + " svc wifi prefer\n" - + " Set Wi-Fi as the preferred data network\n"; + + " Turn Wi-Fi on or off.\n\n"; } public void run(String[] args) { @@ -51,15 +49,6 @@ } else if ("disable".equals(args[1])) { flag = false; validCommand = true; - } else if ("prefer".equals(args[1])) { - IConnectivityManager connMgr = - IConnectivityManager.Stub.asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); - try { - connMgr.setNetworkPreference(ConnectivityManager.TYPE_WIFI); - } catch (RemoteException e) { - System.err.println("Failed to set preferred network: " + e); - } - return; } if (validCommand) { IWifiManager wifiMgr @@ -75,4 +64,4 @@ } System.err.println(longHelp()); } -} \ No newline at end of file +}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 1e3d5be..13ceb4a 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -28,9 +28,12 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityWindowInfo; import com.android.internal.os.HandlerCaller; +import java.util.List; + /** * An accessibility service runs in the background and receives callbacks by the system * when {@link AccessibilityEvent}s are fired. Such events denote some state transition @@ -180,28 +183,37 @@ * event generation has settled down.</p> * <h3>Event types</h3> * <ul> - * <li>{@link AccessibilityEvent#TYPE_VIEW_CLICKED} - * <li>{@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} - * <li>{@link AccessibilityEvent#TYPE_VIEW_FOCUSED} - * <li>{@link AccessibilityEvent#TYPE_VIEW_SELECTED} - * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} - * <li>{@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} - * <li>{@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} - * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START} - * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} - * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER} - * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT} - * <li>{@link AccessibilityEvent#TYPE_VIEW_SCROLLED} - * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} - * <li>{@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} + * <li>{@link AccessibilityEvent#TYPE_VIEW_CLICKED}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_FOCUSED}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_SELECTED}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}</li> + * <li>{@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}</li> + * <li>{@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}</li> + * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}</li> + * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_SCROLLED}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}</li> + * <li>{@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}</li> + * <li>{@link AccessibilityEvent#TYPE_ANNOUNCEMENT}</li> + * <li>{@link AccessibilityEvent#TYPE_GESTURE_DETECTION_START}</li> + * <li>{@link AccessibilityEvent#TYPE_GESTURE_DETECTION_END}</li> + * <li>{@link AccessibilityEvent#TYPE_TOUCH_INTERACTION_START}</li> + * <li>{@link AccessibilityEvent#TYPE_TOUCH_INTERACTION_END}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED}</li> + * <li>{@link AccessibilityEvent#TYPE_WINDOWS_CHANGED}</li> + * <li>{@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED}</li> * </ul> * <h3>Feedback types</h3> * <ul> - * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE} - * <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC} - * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE} - * <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL} - * <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC} + * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li> + * <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}</li> + * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li> + * <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL}</li> + * <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC}</li> + * <li>{@link AccessibilityServiceInfo#FEEDBACK_BRAILLE}</li> * </ul> * @see AccessibilityEvent * @see AccessibilityServiceInfo @@ -340,6 +352,11 @@ */ public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; + /** + * Action to open the power long-press dialog. + */ + public static final int GLOBAL_ACTION_POWER_DIALOG = 6; + private static final String LOG_TAG = "AccessibilityService"; /** @@ -443,8 +460,43 @@ } /** + * Gets the windows on the screen. This method returns only the windows + * that a sighted user can interact with, as opposed to all windows. + * For example, if there is a modal dialog shown and the user cannot touch + * anything behind it, then only the modal window will be reported + * (assuming it is the top one). For convenience the returned windows + * are ordered in a descending layer order, which is the windows that + * are higher in the Z-order are reported first. Since the user can always + * interact with the window that has input focus by typing, the focused + * window is always returned (even if covered by a modal window). + * <p> + * <strong>Note:</strong> In order to access the windows your service has + * to declare the capability to retrieve window content by setting the + * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent} + * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}. + * Also the service has to opt-in to retrieve the interactive windows by + * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} + * flag. + * </p> + * + * @return The windows if there are windows and the service is can retrieve + * them, otherwise an empty list. + */ + public List<AccessibilityWindowInfo> getWindows() { + return AccessibilityInteractionClient.getInstance().getWindows(mConnectionId); + } + + /** * Gets the root node in the currently active window if this service - * can retrieve window content. + * can retrieve window content. The active window is the one that the user + * is currently touching or the window with input focus, if the user is not + * touching any window. + * <p> + * <strong>Note:</strong> In order to access the root node your service has + * to declare the capability to retrieve window content by setting the + * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent} + * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}. + * </p> * * @return The root node if this service can retrieve window content. */ @@ -480,6 +532,31 @@ } /** + * Find the view that has the specified focus type. The search is performed + * across all windows. + * <p> + * <strong>Note:</strong> In order to access the windows your service has + * to declare the capability to retrieve window content by setting the + * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent} + * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}. + * Also the service has to opt-in to retrieve the interactive windows by + * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} + * flag.Otherwise, the search will be performed only in the active window. + * </p> + * + * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or + * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. + * @return The node info of the focused view or null. + * + * @see AccessibilityNodeInfo#FOCUS_INPUT + * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY + */ + public AccessibilityNodeInfo findFocus(int focus) { + return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, + AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus); + } + + /** * Gets the an {@link AccessibilityServiceInfo} describing this * {@link AccessibilityService}. This method is useful if one wants * to change some of the dynamically configurable properties at @@ -581,15 +658,12 @@ */ public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub implements HandlerCaller.Callback { - - static final int NO_ID = -1; - - private static final int DO_SET_SET_CONNECTION = 10; - private static final int DO_ON_INTERRUPT = 20; - private static final int DO_ON_ACCESSIBILITY_EVENT = 30; - private static final int DO_ON_GESTURE = 40; - private static final int DO_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE = 50; - private static final int DO_ON_KEY_EVENT = 60; + private static final int DO_SET_SET_CONNECTION = 1; + private static final int DO_ON_INTERRUPT = 2; + private static final int DO_ON_ACCESSIBILITY_EVENT = 3; + private static final int DO_ON_GESTURE = 4; + private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5; + private static final int DO_ON_KEY_EVENT = 6; private final HandlerCaller mCaller; @@ -624,8 +698,8 @@ mCaller.sendMessage(message); } - public void clearAccessibilityNodeInfoCache() { - Message message = mCaller.obtainMessage(DO_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE); + public void clearAccessibilityCache() { + Message message = mCaller.obtainMessage(DO_CLEAR_ACCESSIBILITY_CACHE); mCaller.sendMessage(message); } @@ -635,6 +709,7 @@ mCaller.sendMessage(message); } + @Override public void executeMessage(Message message) { switch (message.what) { case DO_ON_ACCESSIBILITY_EVENT: { @@ -642,12 +717,19 @@ if (event != null) { AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event); mCallback.onAccessibilityEvent(event); - event.recycle(); + // Make sure the event is recycled. + try { + event.recycle(); + } catch (IllegalStateException ise) { + /* ignore - best effort */ + } } } return; + case DO_ON_INTERRUPT: { mCallback.onInterrupt(); } return; + case DO_SET_SET_CONNECTION: { mConnectionId = message.arg1; IAccessibilityServiceConnection connection = @@ -658,18 +740,22 @@ mCallback.onSetConnectionId(mConnectionId); mCallback.onServiceConnected(); } else { - AccessibilityInteractionClient.getInstance().removeConnection(mConnectionId); + AccessibilityInteractionClient.getInstance().removeConnection( + mConnectionId); AccessibilityInteractionClient.getInstance().clearCache(); mCallback.onSetConnectionId(AccessibilityInteractionClient.NO_ID); } } return; + case DO_ON_GESTURE: { final int gestureId = message.arg1; mCallback.onGesture(gestureId); } return; - case DO_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE: { + + case DO_CLEAR_ACCESSIBILITY_CACHE: { AccessibilityInteractionClient.getInstance().clearCache(); } return; + case DO_ON_KEY_EVENT: { KeyEvent event = (KeyEvent) message.obj; try { @@ -685,9 +771,15 @@ } } } finally { - event.recycle(); + // Make sure the event is recycled. + try { + event.recycle(); + } catch (IllegalStateException ise) { + /* ignore - best effort */ + } } } return; + default : Log.w(LOG_TAG, "Unknown message type " + message.what); }
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index bdc4fdde..4edb0c6 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -284,6 +284,27 @@ public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020; /** + * This flag indicates to the system that the accessibility service wants + * to access content of all interactive windows. An interactive window is a + * window that has input focus or can be touched by a sighted user when explore + * by touch is not enabled. If this flag is not set your service will not receive + * {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED} + * events, calling AccessibilityService{@link AccessibilityService#getWindows() + * AccessibilityService.getWindows()} will return an empty list, and {@link + * AccessibilityNodeInfo#getWindow() AccessibilityNodeInfo.getWindow()} will + * return null. + * <p> + * Services that want to set this flag have to declare the capability + * to retrieve window content in their meta-data by setting the attribute + * {@link android.R.attr#canRetrieveWindowContent canRetrieveWindowContent} to + * true, otherwise this flag will be ignored. For how to declare the meta-data + * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. + * </p> + * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent + */ + public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040; + + /** * The event types an {@link AccessibilityService} is interested in. * <p> * <strong>Can be dynamically set at runtime.</strong> @@ -302,6 +323,15 @@ * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED + * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_START + * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_END + * @see android.view.accessibility.AccessibilityEvent#TYPE_ANNOUNCEMENT + * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_START + * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_END + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY + * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED */ public int eventTypes; @@ -354,6 +384,7 @@ * @see #FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY * @see #FLAG_REQUEST_FILTER_KEY_EVENTS * @see #FLAG_REPORT_VIEW_IDS + * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS */ public int flags; @@ -449,7 +480,7 @@ com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType, 0); notificationTimeout = asAttributes.getInt( - com.android.internal.R.styleable.AccessibilityService_notificationTimeout, + com.android.internal.R.styleable.AccessibilityService_notificationTimeout, 0); flags = asAttributes.getInt( com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0); @@ -861,6 +892,8 @@ return "FLAG_REPORT_VIEW_IDS"; case FLAG_REQUEST_FILTER_KEY_EVENTS: return "FLAG_REQUEST_FILTER_KEY_EVENTS"; + case FLAG_RETRIEVE_INTERACTIVE_WINDOWS: + return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS"; default: return null; }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl index c5e3d43a..6ce0219 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -18,6 +18,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityWindowInfo; import android.view.KeyEvent; /** @@ -35,7 +36,7 @@ void onGesture(int gesture); - void clearAccessibilityNodeInfoCache(); + void clearAccessibilityCache(); void onKeyEvent(in KeyEvent event, int sequence); }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index 3df06b5..27a03b6 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -21,6 +21,7 @@ import android.view.MagnificationSpec; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; +import android.view.accessibility.AccessibilityWindowInfo; /** * Interface given to an AccessibilitySerivce to talk to the AccessibilityManagerService. @@ -53,6 +54,14 @@ int action, in Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); + boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId, + int interactionId, IAccessibilityInteractionConnectionCallback callback, + long threadId); + + AccessibilityWindowInfo getWindow(int windowId); + + List<AccessibilityWindowInfo> getWindows(); + AccessibilityServiceInfo getServiceInfo(); boolean performGlobalAction(int action);
diff --git a/core/java/android/accounts/AccountAuthenticatorActivity.java b/core/java/android/accounts/AccountAuthenticatorActivity.java index 6a55ddf..f9284e67 100644 --- a/core/java/android/accounts/AccountAuthenticatorActivity.java +++ b/core/java/android/accounts/AccountAuthenticatorActivity.java
@@ -17,7 +17,6 @@ package android.accounts; import android.app.Activity; -import android.content.Intent; import android.os.Bundle; /**
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 12fcdcf..09b484b 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java
@@ -155,6 +155,8 @@ /** @hide */ public static final int ERROR_CODE_USER_RESTRICTED = 100; + /** @hide */ + public static final int ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE = 101; /** * Bundle key used for the {@link String} account name in results @@ -359,7 +361,29 @@ */ public AuthenticatorDescription[] getAuthenticatorTypes() { try { - return mService.getAuthenticatorTypes(); + return mService.getAuthenticatorTypes(UserHandle.getCallingUserId()); + } catch (RemoteException e) { + // will never happen + throw new RuntimeException(e); + } + } + + /** + * @hide + * Lists the currently registered authenticators for a given user id. + * + * <p>It is safe to call this method from the main thread. + * + * <p>The caller has to be in the same user or have the permission + * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}. + * + * @return An array of {@link AuthenticatorDescription} for every + * authenticator known to the AccountManager service. Empty (never + * null) if no authenticators are known. + */ + public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) { + try { + return mService.getAuthenticatorTypes(userId); } catch (RemoteException e) { // will never happen throw new RuntimeException(e); @@ -389,6 +413,28 @@ /** * @hide + * Lists all accounts of any type registered on the device for a given + * user id. Equivalent to getAccountsByType(null). + * + * <p>It is safe to call this method from the main thread. + * + * <p>This method requires the caller to hold the permission + * {@link android.Manifest.permission#GET_ACCOUNTS}. + * + * @return An array of {@link Account}, one for each account. Empty + * (never null) if no accounts have been added. + */ + public Account[] getAccountsAsUser(int userId) { + try { + return mService.getAccountsAsUser(null, userId); + } catch (RemoteException e) { + // won't ever happen + throw new RuntimeException(e); + } + } + + /** + * @hide * For use by internal activities. Returns the list of accounts that the calling package * is authorized to use, particularly for shared accounts. * @param packageName package name of the calling app. @@ -617,6 +663,72 @@ } /** + * Rename the specified {@link Account}. This is equivalent to removing + * the existing account and adding a new renamed account with the old + * account's user data. + * + * <p>It is safe to call this method from the main thread. + * + * <p>This method requires the caller to hold the permission + * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} + * and have the same UID as the account's authenticator. + * + * @param account The {@link Account} to rename + * @param newName String name to be associated with the account. + * @param callback Callback to invoke when the request completes, null for + * no callback + * @param handler {@link Handler} identifying the callback thread, null for + * the main thread + * @return An {@link AccountManagerFuture} which resolves to the Account + * after the name change. If successful the account's name will be the + * specified new name. + */ + public AccountManagerFuture<Account> renameAccount( + final Account account, + final String newName, + AccountManagerCallback<Account> callback, + Handler handler) { + if (account == null) throw new IllegalArgumentException("account is null."); + if (TextUtils.isEmpty(newName)) { + throw new IllegalArgumentException("newName is empty or null."); + } + return new Future2Task<Account>(handler, callback) { + @Override + public void doWork() throws RemoteException { + mService.renameAccount(mResponse, account, newName); + } + @Override + public Account bundleToResult(Bundle bundle) throws AuthenticatorException { + String name = bundle.getString(KEY_ACCOUNT_NAME); + String type = bundle.getString(KEY_ACCOUNT_TYPE); + return new Account(name, type); + } + }.start(); + } + + /** + * Gets the previous name associated with the account or {@code null}, if + * none. This is intended so that clients of {@link + * #LOGIN_ACCOUNTS_CHANGED_ACTION} broadcasts can determine if an + * authenticator has renamed an account. + * + * <p>It is safe to call this method from the main thread. + * + * @param account The account to query for a previous name. + * @return The account's previous name, null if the account has never been + * renamed. + */ + public String getPreviousName(final Account account) { + if (account == null) throw new IllegalArgumentException("account is null"); + try { + return mService.getPreviousName(account); + } catch (RemoteException e) { + // will never happen + throw new RuntimeException(e); + } + } + + /** * Removes an account from the AccountManager. Does nothing if the account * does not exist. Does not delete the account from the server. * The authenticator may have its own policies preventing account @@ -634,8 +746,7 @@ * @param handler {@link Handler} identifying the callback thread, * null for the main thread * @return An {@link AccountManagerFuture} which resolves to a Boolean, - * true if the account has been successfully removed, - * false if the authenticator forbids deleting this account. + * true if the account has been successfully removed */ public AccountManagerFuture<Boolean> removeAccount(final Account account, AccountManagerCallback<Boolean> callback, Handler handler) { @@ -654,6 +765,28 @@ } /** + * @see #removeAccount(Account, AccountManagerCallback, Handler) + * @hide + */ + public AccountManagerFuture<Boolean> removeAccountAsUser(final Account account, + AccountManagerCallback<Boolean> callback, Handler handler, + final UserHandle userHandle) { + if (account == null) throw new IllegalArgumentException("account is null"); + if (userHandle == null) throw new IllegalArgumentException("userHandle is null"); + return new Future2Task<Boolean>(handler, callback) { + public void doWork() throws RemoteException { + mService.removeAccountAsUser(mResponse, account, userHandle.getIdentifier()); + } + public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { + if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) { + throw new AuthenticatorException("no result in response"); + } + return bundle.getBoolean(KEY_BOOLEAN_RESULT); + } + }.start(); + } + + /** * Removes an auth token from the AccountManager's cache. Does nothing if * the auth token is not currently in the cache. Applications must call this * method when the auth token is found to have expired or otherwise become @@ -1139,7 +1272,8 @@ * <li> {@link AuthenticatorException} if no authenticator was registered for * this account type or the authenticator failed to respond * <li> {@link OperationCanceledException} if the operation was canceled for - * any reason, including the user canceling the creation process + * any reason, including the user canceling the creation process or adding accounts + * (of this type) has been disabled by policy * <li> {@link IOException} if the authenticator experienced an I/O problem * creating a new account, usually because of network trouble * </ul> @@ -1164,6 +1298,30 @@ } /** + * @see #addAccount(String, String, String[], Bundle, Activity, AccountManagerCallback, Handler) + * @hide + */ + public AccountManagerFuture<Bundle> addAccountAsUser(final String accountType, + final String authTokenType, final String[] requiredFeatures, + final Bundle addAccountOptions, final Activity activity, + AccountManagerCallback<Bundle> callback, Handler handler, final UserHandle userHandle) { + if (accountType == null) throw new IllegalArgumentException("accountType is null"); + if (userHandle == null) throw new IllegalArgumentException("userHandle is null"); + final Bundle optionsIn = new Bundle(); + if (addAccountOptions != null) { + optionsIn.putAll(addAccountOptions); + } + optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName()); + + return new AmsTask(activity, handler, callback) { + public void doWork() throws RemoteException { + mService.addAccountAsUser(mResponse, accountType, authTokenType, + requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier()); + } + }.start(); + } + + /** * Adds a shared account from the primary user to a secondary user. Adding the shared account * doesn't take effect immediately. When the target user starts up, any pending shared accounts * are attempted to be copied to the target user from the primary via calls to the @@ -1564,8 +1722,10 @@ } public void onError(int code, String message) { - if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED) { - // the authenticator indicated that this request was canceled, do so now + if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED + || code == ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) { + // the authenticator indicated that this request was canceled or we were + // forbidden to fulfill; cancel now cancel(true /* mayInterruptIfRunning */); return; } @@ -1624,7 +1784,10 @@ } public void onError(int code, String message) { - if (code == ERROR_CODE_CANCELED) { + if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED + || code == ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) { + // the authenticator indicated that this request was canceled or we were + // forbidden to fulfill; cancel now cancel(true /* mayInterruptIfRunning */); return; }
diff --git a/core/java/android/accounts/AccountManagerFuture.java b/core/java/android/accounts/AccountManagerFuture.java index a1ab00c..77670d9 100644 --- a/core/java/android/accounts/AccountManagerFuture.java +++ b/core/java/android/accounts/AccountManagerFuture.java
@@ -15,10 +15,7 @@ */ package android.accounts; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; import java.io.IOException; /** @@ -87,7 +84,8 @@ * will be thrown rather than the call returning normally. * @return the actual result * @throws android.accounts.OperationCanceledException if the request was canceled for any - * reason + * reason (including if it is forbidden + * by policy to modify an account (of that type)) * @throws android.accounts.AuthenticatorException if there was an error communicating with * the authenticator or if the authenticator returned an invalid response * @throws java.io.IOException if the authenticator returned an error response that indicates
diff --git a/core/java/android/accounts/CantAddAccountActivity.java b/core/java/android/accounts/CantAddAccountActivity.java index e1717a6..f7f232e 100644 --- a/core/java/android/accounts/CantAddAccountActivity.java +++ b/core/java/android/accounts/CantAddAccountActivity.java
@@ -27,6 +27,7 @@ * Just shows an error message about the account restrictions for the limited user. */ public class CantAddAccountActivity extends Activity { + public static final String EXTRA_ERROR_CODE = "android.accounts.extra.ERROR_CODE"; @Override public void onCreate(Bundle savedInstanceState) {
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java index bfbae24..242b3ea 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -100,7 +100,7 @@ try { AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType); Context authContext = createPackageContext(desc.packageName, 0); - icon = authContext.getResources().getDrawable(desc.iconId); + icon = authContext.getDrawable(desc.iconId); } catch (PackageManager.NameNotFoundException e) { // Nothing we can do much here, just log if (Log.isLoggable(TAG, Log.WARN)) {
diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java index acc8549..a3222d8 100644 --- a/core/java/android/accounts/ChooseAccountTypeActivity.java +++ b/core/java/android/accounts/ChooseAccountTypeActivity.java
@@ -129,7 +129,7 @@ Drawable icon = null; try { Context authContext = createPackageContext(desc.packageName, 0); - icon = authContext.getResources().getDrawable(desc.iconId); + icon = authContext.getDrawable(desc.iconId); final CharSequence sequence = authContext.getResources().getText(desc.labelId); if (sequence != null) { name = sequence.toString();
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java index 8b01c6a..12b2b9c 100644 --- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java +++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -16,7 +16,6 @@ package android.accounts; import android.app.Activity; -import android.content.pm.RegisteredServicesCache; import android.content.res.Resources; import android.os.Bundle; import android.widget.TextView; @@ -30,7 +29,6 @@ import com.android.internal.R; import java.io.IOException; -import java.net.Authenticator; /** * @hide
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 86e279f..a133788 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl
@@ -29,7 +29,7 @@ interface IAccountManager { String getPassword(in Account account); String getUserData(in Account account, String key); - AuthenticatorDescription[] getAuthenticatorTypes(); + AuthenticatorDescription[] getAuthenticatorTypes(int userId); Account[] getAccounts(String accountType); Account[] getAccountsForPackage(String packageName, int uid); Account[] getAccountsByTypeForPackage(String type, String packageName); @@ -38,6 +38,7 @@ void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features); boolean addAccountExplicitly(in Account account, String password, in Bundle extras); void removeAccount(in IAccountManagerResponse response, in Account account); + void removeAccountAsUser(in IAccountManagerResponse response, in Account account, int userId); void invalidateAuthToken(String accountType, String authToken); String peekAuthToken(in Account account, String authTokenType); void setAuthToken(in Account account, String authTokenType, String authToken); @@ -52,6 +53,9 @@ void addAccount(in IAccountManagerResponse response, String accountType, String authTokenType, in String[] requiredFeatures, boolean expectActivityLaunch, in Bundle options); + void addAccountAsUser(in IAccountManagerResponse response, String accountType, + String authTokenType, in String[] requiredFeatures, boolean expectActivityLaunch, + in Bundle options, int userId); void updateCredentials(in IAccountManagerResponse response, in Account account, String authTokenType, boolean expectActivityLaunch, in Bundle options); void editProperties(in IAccountManagerResponse response, String accountType, @@ -65,4 +69,10 @@ boolean addSharedAccountAsUser(in Account account, int userId); Account[] getSharedAccountsAsUser(int userId); boolean removeSharedAccountAsUser(in Account account, int userId); + + /* Account renaming. */ + void renameAccount(in IAccountManagerResponse response, in Account accountToRename, String newName); + String getPreviousName(in Account account); + boolean renameSharedAccountAsUser(in Account accountToRename, String newName, int userId); + }
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java new file mode 100644 index 0000000..8b44881 --- /dev/null +++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014 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.alsa; + +import android.util.Slog; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +/** + * @hide Retrieves information from an ALSA "cards" file. + */ +public class AlsaCardsParser { + private static final String TAG = "AlsaCardsParser"; + + private static LineTokenizer tokenizer_ = new LineTokenizer(" :[]"); + + public class AlsaCardRecord { + public int mCardNum = -1; + public String mField1 = ""; + public String mCardName = ""; + public String mCardDescription = ""; + + public AlsaCardRecord() {} + + public boolean parse(String line, int lineIndex) { + int tokenIndex = 0; + int delimIndex = 0; + if (lineIndex == 0) { + // line # (skip) + tokenIndex = tokenizer_.nextToken(line, tokenIndex); + delimIndex = tokenizer_.nextDelimiter(line, tokenIndex); + + // mField1 + tokenIndex = tokenizer_.nextToken(line, delimIndex); + delimIndex = tokenizer_.nextDelimiter(line, tokenIndex); + mField1 = line.substring(tokenIndex, delimIndex); + + // mCardName + tokenIndex = tokenizer_.nextToken(line, delimIndex); + // delimIndex = tokenizer_.nextDelimiter(line, tokenIndex); + mCardName = line.substring(tokenIndex); + // done + } else if (lineIndex == 1) { + tokenIndex = tokenizer_.nextToken(line, 0); + if (tokenIndex != -1) { + mCardDescription = line.substring(tokenIndex); + } + } + + return true; + } + + public String textFormat() { + return mCardName + " : " + mCardDescription; + } + } + + private Vector<AlsaCardRecord> cardRecords_ = new Vector<AlsaCardRecord>(); + + public void scan() { + cardRecords_.clear(); + final String cardsFilePath = "/proc/asound/cards"; + File cardsFile = new File(cardsFilePath); + try { + FileReader reader = new FileReader(cardsFile); + BufferedReader bufferedReader = new BufferedReader(reader); + String line = ""; + while ((line = bufferedReader.readLine()) != null) { + AlsaCardRecord cardRecord = new AlsaCardRecord(); + cardRecord.parse(line, 0); + cardRecord.parse(line = bufferedReader.readLine(), 1); + cardRecords_.add(cardRecord); + } + reader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public AlsaCardRecord getCardRecordAt(int index) { + return cardRecords_.get(index); + } + + public int getNumCardRecords() { + return cardRecords_.size(); + } + + public void Log() { + int numCardRecs = getNumCardRecords(); + for (int index = 0; index < numCardRecs; ++index) { + Slog.w(TAG, "usb:" + getCardRecordAt(index).textFormat()); + } + } + + public AlsaCardsParser() {} +}
diff --git a/core/java/android/alsa/AlsaDevicesParser.java b/core/java/android/alsa/AlsaDevicesParser.java new file mode 100644 index 0000000..82cc1ae --- /dev/null +++ b/core/java/android/alsa/AlsaDevicesParser.java
@@ -0,0 +1,275 @@ +/* + * Copyright (C) 2014 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.alsa; + +import android.util.Slog; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +/** + * @hide + * Retrieves information from an ALSA "devices" file. + */ +public class AlsaDevicesParser { + private static final String TAG = "AlsaDevicesParser"; + + private static final int kIndex_CardDeviceField = 5; + private static final int kStartIndex_CardNum = 6; + private static final int kEndIndex_CardNum = 8; // one past + private static final int kStartIndex_DeviceNum = 9; + private static final int kEndIndex_DeviceNum = 11; // one past + private static final int kStartIndex_Type = 14; + + private static LineTokenizer mTokenizer = new LineTokenizer(" :[]-"); + + private boolean mHasCaptureDevices = false; + private boolean mHasPlaybackDevices = false; + private boolean mHasMIDIDevices = false; + + public class AlsaDeviceRecord { + public static final int kDeviceType_Unknown = -1; + public static final int kDeviceType_Audio = 0; + public static final int kDeviceType_Control = 1; + public static final int kDeviceType_MIDI = 2; + + public static final int kDeviceDir_Unknown = -1; + public static final int kDeviceDir_Capture = 0; + public static final int kDeviceDir_Playback = 1; + + int mCardNum = -1; + int mDeviceNum = -1; + int mDeviceType = kDeviceType_Unknown; + int mDeviceDir = kDeviceDir_Unknown; + + public AlsaDeviceRecord() { + } + + public boolean parse(String line) { + // "0123456789012345678901234567890" + // " 2: [ 0-31]: digital audio playback" + // " 3: [ 0-30]: digital audio capture" + // " 35: [ 1] : control" + // " 36: [ 2- 0]: raw midi" + + final int kToken_LineNum = 0; + final int kToken_CardNum = 1; + final int kToken_DeviceNum = 2; + final int kToken_Type0 = 3; // "digital", "control", "raw" + final int kToken_Type1 = 4; // "audio", "midi" + final int kToken_Type2 = 5; // "capture", "playback" + + int tokenOffset = 0; + int delimOffset = 0; + int tokenIndex = kToken_LineNum; + while (true) { + tokenOffset = mTokenizer.nextToken(line, delimOffset); + if (tokenOffset == LineTokenizer.kTokenNotFound) { + break; // bail + } + delimOffset = mTokenizer.nextDelimiter(line, tokenOffset); + if (delimOffset == LineTokenizer.kTokenNotFound) { + delimOffset = line.length(); + } + String token = line.substring(tokenOffset, delimOffset); + + switch (tokenIndex) { + case kToken_LineNum: + // ignore + break; + + case kToken_CardNum: + mCardNum = Integer.parseInt(token); + if (line.charAt(delimOffset) != '-') { + tokenIndex++; // no device # in the token stream + } + break; + + case kToken_DeviceNum: + mDeviceNum = Integer.parseInt(token); + break; + + case kToken_Type0: + if (token.equals("digital")) { + // NOP + } else if (token.equals("control")) { + mDeviceType = kDeviceType_Control; + } else if (token.equals("raw")) { + // NOP + } + break; + + case kToken_Type1: + if (token.equals("audio")) { + mDeviceType = kDeviceType_Audio; + } else if (token.equals("midi")) { + mDeviceType = kDeviceType_MIDI; + mHasMIDIDevices = true; + } + break; + + case kToken_Type2: + if (token.equals("capture")) { + mDeviceDir = kDeviceDir_Capture; + mHasCaptureDevices = true; + } else if (token.equals("playback")) { + mDeviceDir = kDeviceDir_Playback; + mHasPlaybackDevices = true; + } + break; + } // switch (tokenIndex) + + tokenIndex++; + } // while (true) + + return true; + } // parse() + + public String textFormat() { + StringBuilder sb = new StringBuilder(); + sb.append("[" + mCardNum + ":" + mDeviceNum + "]"); + + switch (mDeviceType) { + case kDeviceType_Unknown: + sb.append(" N/A"); + break; + case kDeviceType_Audio: + sb.append(" Audio"); + break; + case kDeviceType_Control: + sb.append(" Control"); + break; + case kDeviceType_MIDI: + sb.append(" MIDI"); + break; + } + + switch (mDeviceDir) { + case kDeviceDir_Unknown: + sb.append(" N/A"); + break; + case kDeviceDir_Capture: + sb.append(" Capture"); + break; + case kDeviceDir_Playback: + sb.append(" Playback"); + break; + } + + return sb.toString(); + } + } + + private Vector<AlsaDeviceRecord> + deviceRecords_ = new Vector<AlsaDeviceRecord>(); + + private boolean isLineDeviceRecord(String line) { + return line.charAt(kIndex_CardDeviceField) == '['; + } + + public AlsaDevicesParser() { + } + + public int getNumDeviceRecords() { + return deviceRecords_.size(); + } + + public AlsaDeviceRecord getDeviceRecordAt(int index) { + return deviceRecords_.get(index); + } + + public void Log() { + int numDevRecs = getNumDeviceRecords(); + for (int index = 0; index < numDevRecs; ++index) { + Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat()); + } + } + + public boolean hasPlaybackDevices() { + return mHasPlaybackDevices; + } + + public boolean hasPlaybackDevices(int card) { + for (int index = 0; index < deviceRecords_.size(); index++) { + AlsaDeviceRecord deviceRecord = deviceRecords_.get(index); + if (deviceRecord.mCardNum == card && + deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio && + deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Playback) { + return true; + } + } + return false; + } + + public boolean hasCaptureDevices() { + return mHasCaptureDevices; + } + + public boolean hasCaptureDevices(int card) { + for (int index = 0; index < deviceRecords_.size(); index++) { + AlsaDeviceRecord deviceRecord = deviceRecords_.get(index); + if (deviceRecord.mCardNum == card && + deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio && + deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Capture) { + return true; + } + } + return false; + } + + public boolean hasMIDIDevices() { + return mHasMIDIDevices; + } + + public boolean hasMIDIDevices(int card) { + for (int index = 0; index < deviceRecords_.size(); index++) { + AlsaDeviceRecord deviceRecord = deviceRecords_.get(index); + if (deviceRecord.mCardNum == card && + deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_MIDI) { + return true; + } + } + return false; + } + + public void scan() { + deviceRecords_.clear(); + + final String devicesFilePath = "/proc/asound/devices"; + File devicesFile = new File(devicesFilePath); + try { + FileReader reader = new FileReader(devicesFile); + BufferedReader bufferedReader = new BufferedReader(reader); + String line = ""; + while ((line = bufferedReader.readLine()) != null) { + if (isLineDeviceRecord(line)) { + AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord(); + deviceRecord.parse(line); + deviceRecords_.add(deviceRecord); + } + } + reader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} // class AlsaDevicesParser +
diff --git a/core/java/android/alsa/LineTokenizer.java b/core/java/android/alsa/LineTokenizer.java new file mode 100644 index 0000000..78c91b5 --- /dev/null +++ b/core/java/android/alsa/LineTokenizer.java
@@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 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.alsa; + +/** + * @hide + * Breaks lines in an ALSA "cards" or "devices" file into tokens. + * TODO(pmclean) Look into replacing this with String.split(). + */ +public class LineTokenizer { + public static final int kTokenNotFound = -1; + + private String mDelimiters = ""; + + public LineTokenizer(String delimiters) { + mDelimiters = delimiters; + } + + int nextToken(String line, int startIndex) { + int len = line.length(); + int offset = startIndex; + for (; offset < len; offset++) { + if (mDelimiters.indexOf(line.charAt(offset)) == -1) { + // past a delimiter + break; + } + } + + return offset < len ? offset : kTokenNotFound; + } + + int nextDelimiter(String line, int startIndex) { + int len = line.length(); + int offset = startIndex; + for (; offset < len; offset++) { + if (mDelimiters.indexOf(line.charAt(offset)) != -1) { + // past a delimiter + break; + } + } + + return offset < len ? offset : kTokenNotFound; + } +}
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index 129e52c..3720c81 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java
@@ -356,6 +356,23 @@ public void setTarget(Object target) { } + // Hide reverse() and canReverse() for now since reverse() only work for simple + // cases, like we don't support sequential, neither startDelay. + // TODO: make reverse() works for all the Animators. + /** + * @hide + */ + public boolean canReverse() { + return false; + } + + /** + * @hide + */ + public void reverse() { + throw new IllegalStateException("Reverse is not supported"); + } + /** * <p>An animation listener receives notifications from an animation. * Notifications indicate animation related events, such as the end or the @@ -417,4 +434,39 @@ */ void onAnimationResume(Animator animation); } + + /** + * <p>Whether or not the Animator is allowed to run asynchronously off of + * the UI thread. This is a hint that informs the Animator that it is + * OK to run the animation off-thread, however the Animator may decide + * that it must run the animation on the UI thread anyway. + * + * <p>Regardless of whether or not the animation runs asynchronously, all + * listener callbacks will be called on the UI thread.</p> + * + * <p>To be able to use this hint the following must be true:</p> + * <ol> + * <li>The animator is immutable while {@link #isStarted()} is true. Requests + * to change duration, delay, etc... may be ignored.</li> + * <li>Lifecycle callback events may be asynchronous. Events such as + * {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or + * {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed + * as they must be posted back to the UI thread, and any actions performed + * by those callbacks (such as starting new animations) will not happen + * in the same frame.</li> + * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...) + * may be asynchronous. It is guaranteed that all state changes that are + * performed on the UI thread in the same frame will be applied as a single + * atomic update, however that frame may be the current frame, + * the next frame, or some future frame. This will also impact the observed + * state of the Animator. For example, {@link #isStarted()} may still return true + * after a call to {@link #end()}. Using the lifecycle callbacks is preferred over + * queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()} + * for this reason.</li> + * </ol> + * @hide + */ + public void setAllowRunningAsynchronously(boolean mayRunAsync) { + // It is up to subclasses to support this, if they can. + } }
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index d753e32..25417ed 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java
@@ -17,13 +17,22 @@ import android.content.Context; import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.content.res.Resources.NotFoundException; +import android.graphics.Path; import android.util.AttributeSet; +import android.util.Log; +import android.util.PathParser; +import android.util.StateSet; import android.util.TypedValue; import android.util.Xml; +import android.view.InflateException; import android.view.animation.AnimationUtils; + +import com.android.internal.R; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -40,7 +49,7 @@ * <em>something</em> file.) */ public class AnimatorInflater { - + private static final String TAG = "AnimatorInflater"; /** * These flags are used when parsing AnimatorSet objects */ @@ -52,9 +61,12 @@ */ private static final int VALUE_TYPE_FLOAT = 0; private static final int VALUE_TYPE_INT = 1; + private static final int VALUE_TYPE_PATH = 2; private static final int VALUE_TYPE_COLOR = 4; private static final int VALUE_TYPE_CUSTOM = 5; + private static final boolean DBG_ANIMATOR_INFLATER = false; + /** * Loads an {@link Animator} object from a resource * @@ -65,21 +77,42 @@ */ public static Animator loadAnimator(Context context, int id) throws NotFoundException { + return loadAnimator(context.getResources(), context.getTheme(), id); + } + + /** + * Loads an {@link Animator} object from a resource + * + * @param resources The resources + * @param theme The theme + * @param id The resource id of the animation to load + * @return The animator object reference by the specified id + * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded + * @hide + */ + public static Animator loadAnimator(Resources resources, Theme theme, int id) + throws NotFoundException { + return loadAnimator(resources, theme, id, 1); + } + + /** @hide */ + public static Animator loadAnimator(Resources resources, Theme theme, int id, + float pathErrorScale) throws NotFoundException { XmlResourceParser parser = null; try { - parser = context.getResources().getAnimation(id); - return createAnimatorFromXml(context, parser); + parser = resources.getAnimation(id); + return createAnimatorFromXml(resources, theme, parser, pathErrorScale); } catch (XmlPullParserException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); + Integer.toHexString(id)); rnf.initCause(ex); throw rnf; } catch (IOException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); + Integer.toHexString(id)); rnf.initCause(ex); throw rnf; } finally { @@ -87,14 +120,393 @@ } } - private static Animator createAnimatorFromXml(Context c, XmlPullParser parser) - throws XmlPullParserException, IOException { - - return createAnimatorFromXml(c, parser, Xml.asAttributeSet(parser), null, 0); + public static StateListAnimator loadStateListAnimator(Context context, int id) + throws NotFoundException { + XmlResourceParser parser = null; + try { + parser = context.getResources().getAnimation(id); + return createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser)); + } catch (XmlPullParserException ex) { + Resources.NotFoundException rnf = + new Resources.NotFoundException( + "Can't load state list animator resource ID #0x" + + Integer.toHexString(id) + ); + rnf.initCause(ex); + throw rnf; + } catch (IOException ex) { + Resources.NotFoundException rnf = + new Resources.NotFoundException( + "Can't load state list animator resource ID #0x" + + Integer.toHexString(id) + ); + rnf.initCause(ex); + throw rnf; + } finally { + if (parser != null) { + parser.close(); + } + } } - private static Animator createAnimatorFromXml(Context c, XmlPullParser parser, - AttributeSet attrs, AnimatorSet parent, int sequenceOrdering) + private static StateListAnimator createStateListAnimatorFromXml(Context context, + XmlPullParser parser, AttributeSet attributeSet) + throws IOException, XmlPullParserException { + int type; + StateListAnimator stateListAnimator = new StateListAnimator(); + + while (true) { + type = parser.next(); + switch (type) { + case XmlPullParser.END_DOCUMENT: + case XmlPullParser.END_TAG: + return stateListAnimator; + + case XmlPullParser.START_TAG: + // parse item + Animator animator = null; + if ("item".equals(parser.getName())) { + int attributeCount = parser.getAttributeCount(); + int[] states = new int[attributeCount]; + int stateIndex = 0; + for (int i = 0; i < attributeCount; i++) { + int attrName = attributeSet.getAttributeNameResource(i); + if (attrName == R.attr.animation) { + animator = loadAnimator(context, + attributeSet.getAttributeResourceValue(i, 0)); + } else { + states[stateIndex++] = + attributeSet.getAttributeBooleanValue(i, false) ? + attrName : -attrName; + } + + } + if (animator == null) { + animator = createAnimatorFromXml(context.getResources(), + context.getTheme(), parser, 1f); + } + + if (animator == null) { + throw new Resources.NotFoundException( + "animation state item must have a valid animation"); + } + stateListAnimator + .addState(StateSet.trimStateSet(states, stateIndex), animator); + + } + break; + } + } + } + + /** + * PathDataEvaluator is used to interpolate between two paths which are + * represented in the same format but different control points' values. + * The path is represented as an array of PathDataNode here, which is + * fundamentally an array of floating point numbers. + */ + private static class PathDataEvaluator implements TypeEvaluator<PathParser.PathDataNode[]> { + private PathParser.PathDataNode[] mNodeArray; + + /** + * Create a PathParser.PathDataNode[] that does not reuse the animated value. + * Care must be taken when using this option because on every evaluation + * a new <code>PathParser.PathDataNode[]</code> will be allocated. + */ + private PathDataEvaluator() {} + + /** + * Create a PathDataEvaluator that reuses <code>nodeArray</code> for every evaluate() call. + * Caution must be taken to ensure that the value returned from + * {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or + * used across threads. The value will be modified on each <code>evaluate()</code> call. + * + * @param nodeArray The array to modify and return from <code>evaluate</code>. + */ + public PathDataEvaluator(PathParser.PathDataNode[] nodeArray) { + mNodeArray = nodeArray; + } + + @Override + public PathParser.PathDataNode[] evaluate(float fraction, + PathParser.PathDataNode[] startPathData, + PathParser.PathDataNode[] endPathData) { + if (!PathParser.canMorph(startPathData, endPathData)) { + throw new IllegalArgumentException("Can't interpolate between" + + " two incompatible pathData"); + } + + if (mNodeArray == null || !PathParser.canMorph(mNodeArray, startPathData)) { + mNodeArray = PathParser.deepCopyNodes(startPathData); + } + + for (int i = 0; i < startPathData.length; i++) { + mNodeArray[i].interpolatePathDataNode(startPathData[i], + endPathData[i], fraction); + } + + return mNodeArray; + } + } + + /** + * @param anim The animator, must not be null + * @param arrayAnimator Incoming typed array for Animator's attributes. + * @param arrayObjectAnimator Incoming typed array for Object Animator's + * attributes. + * @param pixelSize The relative pixel size, used to calculate the + * maximum error for path animations. + */ + private static void parseAnimatorFromTypeArray(ValueAnimator anim, + TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) { + long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300); + + long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0); + + int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType, + VALUE_TYPE_FLOAT); + + TypeEvaluator evaluator = null; + + boolean getFloats = (valueType == VALUE_TYPE_FLOAT); + + TypedValue tvFrom = arrayAnimator.peekValue(R.styleable.Animator_valueFrom); + boolean hasFrom = (tvFrom != null); + int fromType = hasFrom ? tvFrom.type : 0; + TypedValue tvTo = arrayAnimator.peekValue(R.styleable.Animator_valueTo); + boolean hasTo = (tvTo != null); + int toType = hasTo ? tvTo.type : 0; + + // TODO: Further clean up this part of code into 4 types : path, color, + // integer and float. + if (valueType == VALUE_TYPE_PATH) { + evaluator = setupAnimatorForPath(anim, arrayAnimator); + } else { + // Integer and float value types are handled here. + if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && + (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) || + (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) && + (toType <= TypedValue.TYPE_LAST_COLOR_INT))) { + // special case for colors: ignore valueType and get ints + getFloats = false; + evaluator = ArgbEvaluator.getInstance(); + } + setupValues(anim, arrayAnimator, getFloats, hasFrom, fromType, hasTo, toType); + } + + anim.setDuration(duration); + anim.setStartDelay(startDelay); + + if (arrayAnimator.hasValue(R.styleable.Animator_repeatCount)) { + anim.setRepeatCount( + arrayAnimator.getInt(R.styleable.Animator_repeatCount, 0)); + } + if (arrayAnimator.hasValue(R.styleable.Animator_repeatMode)) { + anim.setRepeatMode( + arrayAnimator.getInt(R.styleable.Animator_repeatMode, + ValueAnimator.RESTART)); + } + if (evaluator != null) { + anim.setEvaluator(evaluator); + } + + if (arrayObjectAnimator != null) { + setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize); + } + } + + /** + * Setup the Animator to achieve path morphing. + * + * @param anim The target Animator which will be updated. + * @param arrayAnimator TypedArray for the ValueAnimator. + * @return the PathDataEvaluator. + */ + private static TypeEvaluator setupAnimatorForPath(ValueAnimator anim, + TypedArray arrayAnimator) { + TypeEvaluator evaluator = null; + String fromString = arrayAnimator.getString(R.styleable.Animator_valueFrom); + String toString = arrayAnimator.getString(R.styleable.Animator_valueTo); + PathParser.PathDataNode[] nodesFrom = PathParser.createNodesFromPathData(fromString); + PathParser.PathDataNode[] nodesTo = PathParser.createNodesFromPathData(toString); + + if (nodesFrom != null) { + if (nodesTo != null) { + anim.setObjectValues(nodesFrom, nodesTo); + if (!PathParser.canMorph(nodesFrom, nodesTo)) { + throw new InflateException(arrayAnimator.getPositionDescription() + + " Can't morph from " + fromString + " to " + toString); + } + } else { + anim.setObjectValues((Object)nodesFrom); + } + evaluator = new PathDataEvaluator(PathParser.deepCopyNodes(nodesFrom)); + } else if (nodesTo != null) { + anim.setObjectValues((Object)nodesTo); + evaluator = new PathDataEvaluator(PathParser.deepCopyNodes(nodesTo)); + } + + if (DBG_ANIMATOR_INFLATER && evaluator != null) { + Log.v(TAG, "create a new PathDataEvaluator here"); + } + + return evaluator; + } + + /** + * Setup ObjectAnimator's property or values from pathData. + * + * @param anim The target Animator which will be updated. + * @param arrayObjectAnimator TypedArray for the ObjectAnimator. + * @param getFloats True if the value type is float. + * @param pixelSize The relative pixel size, used to calculate the + * maximum error for path animations. + */ + private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator, + boolean getFloats, float pixelSize) { + ObjectAnimator oa = (ObjectAnimator) anim; + String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData); + + // Note that if there is a pathData defined in the Object Animator, + // valueFrom / valueTo will be ignored. + if (pathData != null) { + String propertyXName = + arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyXName); + String propertyYName = + arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyYName); + + if (propertyXName == null && propertyYName == null) { + throw new InflateException(arrayObjectAnimator.getPositionDescription() + + " propertyXName or propertyYName is needed for PathData"); + } else { + Path path = PathParser.createPathFromPathData(pathData); + float error = 0.5f * pixelSize; // max half a pixel error + PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error); + Keyframes xKeyframes; + Keyframes yKeyframes; + if (getFloats) { + xKeyframes = keyframeSet.createXFloatKeyframes(); + yKeyframes = keyframeSet.createYFloatKeyframes(); + } else { + xKeyframes = keyframeSet.createXIntKeyframes(); + yKeyframes = keyframeSet.createYIntKeyframes(); + } + PropertyValuesHolder x = null; + PropertyValuesHolder y = null; + if (propertyXName != null) { + x = PropertyValuesHolder.ofKeyframes(propertyXName, xKeyframes); + } + if (propertyYName != null) { + y = PropertyValuesHolder.ofKeyframes(propertyYName, yKeyframes); + } + if (x == null) { + oa.setValues(y); + } else if (y == null) { + oa.setValues(x); + } else { + oa.setValues(x, y); + } + } + } else { + String propertyName = + arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyName); + oa.setPropertyName(propertyName); + } + } + + /** + * Setup ValueAnimator's values. + * This will handle all of the integer, float and color types. + * + * @param anim The target Animator which will be updated. + * @param arrayAnimator TypedArray for the ValueAnimator. + * @param getFloats True if the value type is float. + * @param hasFrom True if "valueFrom" exists. + * @param fromType The type of "valueFrom". + * @param hasTo True if "valueTo" exists. + * @param toType The type of "valueTo". + */ + private static void setupValues(ValueAnimator anim, TypedArray arrayAnimator, + boolean getFloats, boolean hasFrom, int fromType, boolean hasTo, int toType) { + int valueFromIndex = R.styleable.Animator_valueFrom; + int valueToIndex = R.styleable.Animator_valueTo; + if (getFloats) { + float valueFrom; + float valueTo; + if (hasFrom) { + if (fromType == TypedValue.TYPE_DIMENSION) { + valueFrom = arrayAnimator.getDimension(valueFromIndex, 0f); + } else { + valueFrom = arrayAnimator.getFloat(valueFromIndex, 0f); + } + if (hasTo) { + if (toType == TypedValue.TYPE_DIMENSION) { + valueTo = arrayAnimator.getDimension(valueToIndex, 0f); + } else { + valueTo = arrayAnimator.getFloat(valueToIndex, 0f); + } + anim.setFloatValues(valueFrom, valueTo); + } else { + anim.setFloatValues(valueFrom); + } + } else { + if (toType == TypedValue.TYPE_DIMENSION) { + valueTo = arrayAnimator.getDimension(valueToIndex, 0f); + } else { + valueTo = arrayAnimator.getFloat(valueToIndex, 0f); + } + anim.setFloatValues(valueTo); + } + } else { + int valueFrom; + int valueTo; + if (hasFrom) { + if (fromType == TypedValue.TYPE_DIMENSION) { + valueFrom = (int) arrayAnimator.getDimension(valueFromIndex, 0f); + } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && + (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) { + valueFrom = arrayAnimator.getColor(valueFromIndex, 0); + } else { + valueFrom = arrayAnimator.getInt(valueFromIndex, 0); + } + if (hasTo) { + if (toType == TypedValue.TYPE_DIMENSION) { + valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f); + } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && + (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { + valueTo = arrayAnimator.getColor(valueToIndex, 0); + } else { + valueTo = arrayAnimator.getInt(valueToIndex, 0); + } + anim.setIntValues(valueFrom, valueTo); + } else { + anim.setIntValues(valueFrom); + } + } else { + if (hasTo) { + if (toType == TypedValue.TYPE_DIMENSION) { + valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f); + } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && + (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { + valueTo = arrayAnimator.getColor(valueToIndex, 0); + } else { + valueTo = arrayAnimator.getInt(valueToIndex, 0); + } + anim.setIntValues(valueTo); + } + } + } + } + + private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser, + float pixelSize) + throws XmlPullParserException, IOException { + return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0, + pixelSize); + } + + private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser, + AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize) throws XmlPullParserException, IOException { Animator anim = null; @@ -104,26 +516,31 @@ int type; int depth = parser.getDepth(); - while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) - && type != XmlPullParser.END_DOCUMENT) { + while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) + && type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) { continue; } - String name = parser.getName(); + String name = parser.getName(); if (name.equals("objectAnimator")) { - anim = loadObjectAnimator(c, attrs); + anim = loadObjectAnimator(res, theme, attrs, pixelSize); } else if (name.equals("animator")) { - anim = loadAnimator(c, attrs, null); + anim = loadAnimator(res, theme, attrs, null, pixelSize); } else if (name.equals("set")) { anim = new AnimatorSet(); - TypedArray a = c.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.AnimatorSet); - int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering, + TypedArray a; + if (theme != null) { + a = theme.obtainStyledAttributes(attrs, R.styleable.AnimatorSet, 0, 0); + } else { + a = res.obtainAttributes(attrs, R.styleable.AnimatorSet); + } + int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER); - createAnimatorFromXml(c, parser, attrs, (AnimatorSet) anim, ordering); + createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering, + pixelSize); a.recycle(); } else { throw new RuntimeException("Unknown animator name: " + parser.getName()); @@ -153,160 +570,63 @@ } - private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs) - throws NotFoundException { - + private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs, + float pathErrorScale) throws NotFoundException { ObjectAnimator anim = new ObjectAnimator(); - loadAnimator(context, attrs, anim); - - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PropertyAnimator); - - String propertyName = a.getString(com.android.internal.R.styleable.PropertyAnimator_propertyName); - - anim.setPropertyName(propertyName); - - a.recycle(); + loadAnimator(res, theme, attrs, anim, pathErrorScale); return anim; } /** - * Creates a new animation whose parameters come from the specified context and - * attributes set. + * Creates a new animation whose parameters come from the specified context + * and attributes set. * - * @param context the application environment - * @param attrs the set of attributes holding the animation parameters + * @param res The resources + * @param attrs The set of attributes holding the animation parameters + * @param anim Null if this is a ValueAnimator, otherwise this is an + * ObjectAnimator */ - private static ValueAnimator loadAnimator(Context context, AttributeSet attrs, ValueAnimator anim) + private static ValueAnimator loadAnimator(Resources res, Theme theme, + AttributeSet attrs, ValueAnimator anim, float pathErrorScale) throws NotFoundException { - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animator); + TypedArray arrayAnimator = null; + TypedArray arrayObjectAnimator = null; - long duration = a.getInt(com.android.internal.R.styleable.Animator_duration, 300); + if (theme != null) { + arrayAnimator = theme.obtainStyledAttributes(attrs, R.styleable.Animator, 0, 0); + } else { + arrayAnimator = res.obtainAttributes(attrs, R.styleable.Animator); + } - long startDelay = a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0); - - int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType, - VALUE_TYPE_FLOAT); + // If anim is not null, then it is an object animator. + if (anim != null) { + if (theme != null) { + arrayObjectAnimator = theme.obtainStyledAttributes(attrs, + R.styleable.PropertyAnimator, 0, 0); + } else { + arrayObjectAnimator = res.obtainAttributes(attrs, R.styleable.PropertyAnimator); + } + } if (anim == null) { anim = new ValueAnimator(); } - TypeEvaluator evaluator = null; - int valueFromIndex = com.android.internal.R.styleable.Animator_valueFrom; - int valueToIndex = com.android.internal.R.styleable.Animator_valueTo; - - boolean getFloats = (valueType == VALUE_TYPE_FLOAT); - - TypedValue tvFrom = a.peekValue(valueFromIndex); - boolean hasFrom = (tvFrom != null); - int fromType = hasFrom ? tvFrom.type : 0; - TypedValue tvTo = a.peekValue(valueToIndex); - boolean hasTo = (tvTo != null); - int toType = hasTo ? tvTo.type : 0; - - if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) || - (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT))) { - // special case for colors: ignore valueType and get ints - getFloats = false; - anim.setEvaluator(new ArgbEvaluator()); - } - - if (getFloats) { - float valueFrom; - float valueTo; - if (hasFrom) { - if (fromType == TypedValue.TYPE_DIMENSION) { - valueFrom = a.getDimension(valueFromIndex, 0f); - } else { - valueFrom = a.getFloat(valueFromIndex, 0f); - } - if (hasTo) { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = a.getDimension(valueToIndex, 0f); - } else { - valueTo = a.getFloat(valueToIndex, 0f); - } - anim.setFloatValues(valueFrom, valueTo); - } else { - anim.setFloatValues(valueFrom); - } - } else { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = a.getDimension(valueToIndex, 0f); - } else { - valueTo = a.getFloat(valueToIndex, 0f); - } - anim.setFloatValues(valueTo); - } - } else { - int valueFrom; - int valueTo; - if (hasFrom) { - if (fromType == TypedValue.TYPE_DIMENSION) { - valueFrom = (int) a.getDimension(valueFromIndex, 0f); - } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueFrom = a.getColor(valueFromIndex, 0); - } else { - valueFrom = a.getInt(valueFromIndex, 0); - } - if (hasTo) { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = (int) a.getDimension(valueToIndex, 0f); - } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueTo = a.getColor(valueToIndex, 0); - } else { - valueTo = a.getInt(valueToIndex, 0); - } - anim.setIntValues(valueFrom, valueTo); - } else { - anim.setIntValues(valueFrom); - } - } else { - if (hasTo) { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = (int) a.getDimension(valueToIndex, 0f); - } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueTo = a.getColor(valueToIndex, 0); - } else { - valueTo = a.getInt(valueToIndex, 0); - } - anim.setIntValues(valueTo); - } - } - } - - anim.setDuration(duration); - anim.setStartDelay(startDelay); - - if (a.hasValue(com.android.internal.R.styleable.Animator_repeatCount)) { - anim.setRepeatCount( - a.getInt(com.android.internal.R.styleable.Animator_repeatCount, 0)); - } - if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) { - anim.setRepeatMode( - a.getInt(com.android.internal.R.styleable.Animator_repeatMode, - ValueAnimator.RESTART)); - } - if (evaluator != null) { - anim.setEvaluator(evaluator); - } + parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale); final int resID = - a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0); + arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0); if (resID > 0) { - anim.setInterpolator(AnimationUtils.loadInterpolator(context, resID)); + anim.setInterpolator(AnimationUtils.loadInterpolator(res, theme, resID)); } - a.recycle(); + + arrayAnimator.recycle(); + if (arrayObjectAnimator != null) { + arrayObjectAnimator.recycle(); + } return anim; }
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 018a2d6..0aa8fdd 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java
@@ -124,7 +124,7 @@ // was set on this AnimatorSet, so it should not be passed down to the children. private TimeInterpolator mInterpolator = null; - + private boolean mReversible = true; /** * Sets up this AnimatorSet to play all of the supplied animations at the same time. * This is equivalent to calling {@link #play(Animator)} with the first animator in the @@ -177,6 +177,7 @@ if (items.length == 1) { play(items[0]); } else { + mReversible = false; for (int i = 0; i < items.length - 1; ++i) { play(items[i]).before(items[i+1]); } @@ -196,6 +197,7 @@ if (items.size() == 1) { play(items.get(0)); } else { + mReversible = false; for (int i = 0; i < items.size() - 1; ++i) { play(items.get(i)).before(items.get(i+1)); } @@ -407,6 +409,9 @@ */ @Override public void setStartDelay(long startDelay) { + if (mStartDelay > 0) { + mReversible = false; + } mStartDelay = startDelay; } @@ -499,6 +504,10 @@ mStarted = true; mPaused = false; + for (Node node : mNodes) { + node.animation.setAllowRunningAsynchronously(false); + } + if (mDuration >= 0) { // If the duration was set on this AnimatorSet, pass it along to all child animations for (Node node : mNodes) { @@ -512,7 +521,7 @@ node.animation.setInterpolator(mInterpolator); } } - // First, sort the nodes (if necessary). This will ensure that sortedNodes + // First, sort the nodes (if necessary). This will ensure that sortedNodes // contains the animation nodes in the correct order. sortNodes(); @@ -626,6 +635,8 @@ anim.mNodeMap = new HashMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(); anim.mSortedNodes = new ArrayList<Node>(); + anim.mReversible = mReversible; + anim.mSetListener = null; // Walk through the old nodes list, cloning each node and adding it to the new nodemap. // One problem is that the old node dependencies point to nodes in the old AnimatorSet. @@ -908,6 +919,35 @@ } /** + * @hide + */ + @Override + public boolean canReverse() { + if (!mReversible) { + return false; + } + // Loop to make sure all the Nodes can reverse. + for (Node node : mNodes) { + if (!node.animation.canReverse() || node.animation.getStartDelay() > 0) { + return false; + } + } + return true; + } + + /** + * @hide + */ + @Override + public void reverse() { + if (canReverse()) { + for (Node node : mNodes) { + node.animation.reverse(); + } + } + } + + /** * Dependency holds information about the node that some other node is * dependent upon and the nature of that dependency. * @@ -1124,6 +1164,7 @@ * {@link AnimatorSet#play(Animator)} method ends. */ public Builder before(Animator anim) { + mReversible = false; Node node = mNodeMap.get(anim); if (node == null) { node = new Node(anim); @@ -1144,6 +1185,7 @@ * {@link AnimatorSet#play(Animator)} method to play. */ public Builder after(Animator anim) { + mReversible = false; Node node = mNodeMap.get(anim); if (node == null) { node = new Node(anim);
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java index 717a3d9..ed07195 100644 --- a/core/java/android/animation/ArgbEvaluator.java +++ b/core/java/android/animation/ArgbEvaluator.java
@@ -21,6 +21,19 @@ * values that represent ARGB colors. */ public class ArgbEvaluator implements TypeEvaluator { + private static final ArgbEvaluator sInstance = new ArgbEvaluator(); + + /** + * Returns an instance of <code>ArgbEvaluator</code> that may be used in + * {@link ValueAnimator#setEvaluator(TypeEvaluator)}. The same instance may + * be used in multiple <code>Animator</code>s because it holds no state. + * @return An instance of <code>ArgbEvalutor</code>. + * + * @hide + */ + public static ArgbEvaluator getInstance() { + return sInstance; + } /** * This function returns the calculated in-between value for a color
diff --git a/core/java/android/animation/BidirectionalTypeConverter.java b/core/java/android/animation/BidirectionalTypeConverter.java new file mode 100644 index 0000000..960650e --- /dev/null +++ b/core/java/android/animation/BidirectionalTypeConverter.java
@@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014 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.animation; + +/** + * Abstract base class used convert type T to another type V and back again. This + * is necessary when the value types of in animation are different from the property + * type. BidirectionalTypeConverter is needed when only the final value for the + * animation is supplied to animators. + * @see PropertyValuesHolder#setConverter(TypeConverter) + */ +public abstract class BidirectionalTypeConverter<T, V> extends TypeConverter<T, V> { + private BidirectionalTypeConverter mInvertedConverter; + + public BidirectionalTypeConverter(Class<T> fromClass, Class<V> toClass) { + super(fromClass, toClass); + } + + /** + * Does a conversion from the target type back to the source type. The subclass + * must implement this when a TypeConverter is used in animations and current + * values will need to be read for an animation. + * @param value The Object to convert. + * @return A value of type T, converted from <code>value</code>. + */ + public abstract T convertBack(V value); + + /** + * Returns the inverse of this converter, where the from and to classes are reversed. + * The inverted converter uses this convert to call {@link #convertBack(Object)} for + * {@link #convert(Object)} calls and {@link #convert(Object)} for + * {@link #convertBack(Object)} calls. + * @return The inverse of this converter, where the from and to classes are reversed. + */ + public BidirectionalTypeConverter<V, T> invert() { + if (mInvertedConverter == null) { + mInvertedConverter = new InvertedConverter(this); + } + return mInvertedConverter; + } + + private static class InvertedConverter<From, To> extends BidirectionalTypeConverter<From, To> { + private BidirectionalTypeConverter<To, From> mConverter; + + public InvertedConverter(BidirectionalTypeConverter<To, From> converter) { + super(converter.getTargetType(), converter.getSourceType()); + mConverter = converter; + } + + @Override + public From convertBack(To value) { + return mConverter.convert(value); + } + + @Override + public To convert(From value) { + return mConverter.convertBack(value); + } + } +}
diff --git a/core/java/android/animation/FloatArrayEvaluator.java b/core/java/android/animation/FloatArrayEvaluator.java new file mode 100644 index 0000000..9ae1197 --- /dev/null +++ b/core/java/android/animation/FloatArrayEvaluator.java
@@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 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.animation; + +/** + * This evaluator can be used to perform type interpolation between <code>float[]</code> values. + * Each index into the array is treated as a separate value to interpolate. For example, + * evaluating <code>{100, 200}</code> and <code>{300, 400}</code> will interpolate the value at + * the first index between 100 and 300 and the value at the second index value between 200 and 400. + */ +public class FloatArrayEvaluator implements TypeEvaluator<float[]> { + + private float[] mArray; + + /** + * Create a FloatArrayEvaluator that does not reuse the animated value. Care must be taken + * when using this option because on every evaluation a new <code>float[]</code> will be + * allocated. + * + * @see #FloatArrayEvaluator(float[]) + */ + public FloatArrayEvaluator() { + } + + /** + * Create a FloatArrayEvaluator that reuses <code>reuseArray</code> for every evaluate() call. + * Caution must be taken to ensure that the value returned from + * {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or + * used across threads. The value will be modified on each <code>evaluate()</code> call. + * + * @param reuseArray The array to modify and return from <code>evaluate</code>. + */ + public FloatArrayEvaluator(float[] reuseArray) { + mArray = reuseArray; + } + + /** + * Interpolates the value at each index by the fraction. If + * {@link #FloatArrayEvaluator(float[])} was used to construct this object, + * <code>reuseArray</code> will be returned, otherwise a new <code>float[]</code> + * will be returned. + * + * @param fraction The fraction from the starting to the ending values + * @param startValue The start value. + * @param endValue The end value. + * @return A <code>float[]</code> where each element is an interpolation between + * the same index in startValue and endValue. + */ + @Override + public float[] evaluate(float fraction, float[] startValue, float[] endValue) { + float[] array = mArray; + if (array == null) { + array = new float[startValue.length]; + } + + for (int i = 0; i < array.length; i++) { + float start = startValue[i]; + float end = endValue[i]; + array[i] = start + (fraction * (end - start)); + } + return array; + } +}
diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java index 377b5a05..12e5862 100644 --- a/core/java/android/animation/FloatKeyframeSet.java +++ b/core/java/android/animation/FloatKeyframeSet.java
@@ -30,7 +30,7 @@ * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the * Object equivalents of these primitive types.</p> */ -class FloatKeyframeSet extends KeyframeSet { +class FloatKeyframeSet extends KeyframeSet implements Keyframes.FloatKeyframes { private float firstValue; private float lastValue; private float deltaValue; @@ -57,6 +57,12 @@ return newSet; } + @Override + public void invalidateCache() { + firstTime = true; + } + + @Override public float getFloatValue(float fraction) { if (mNumKeyframes == 2) { if (firstTime) { @@ -130,5 +136,9 @@ return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).floatValue(); } + @Override + public Class getType() { + return Float.class; + } }
diff --git a/core/java/android/animation/IntArrayEvaluator.java b/core/java/android/animation/IntArrayEvaluator.java new file mode 100644 index 0000000..d7f10f3 --- /dev/null +++ b/core/java/android/animation/IntArrayEvaluator.java
@@ -0,0 +1,75 @@ +/* + * Copyright (C) 2013 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.animation; + +/** + * This evaluator can be used to perform type interpolation between <code>int[]</code> values. + * Each index into the array is treated as a separate value to interpolate. For example, + * evaluating <code>{100, 200}</code> and <code>{300, 400}</code> will interpolate the value at + * the first index between 100 and 300 and the value at the second index value between 200 and 400. + */ +public class IntArrayEvaluator implements TypeEvaluator<int[]> { + + private int[] mArray; + + /** + * Create an IntArrayEvaluator that does not reuse the animated value. Care must be taken + * when using this option because on every evaluation a new <code>int[]</code> will be + * allocated. + * + * @see #IntArrayEvaluator(int[]) + */ + public IntArrayEvaluator() { + } + + /** + * Create an IntArrayEvaluator that reuses <code>reuseArray</code> for every evaluate() call. + * Caution must be taken to ensure that the value returned from + * {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or + * used across threads. The value will be modified on each <code>evaluate()</code> call. + * + * @param reuseArray The array to modify and return from <code>evaluate</code>. + */ + public IntArrayEvaluator(int[] reuseArray) { + mArray = reuseArray; + } + + /** + * Interpolates the value at each index by the fraction. If {@link #IntArrayEvaluator(int[])} + * was used to construct this object, <code>reuseArray</code> will be returned, otherwise + * a new <code>int[]</code> will be returned. + * + * @param fraction The fraction from the starting to the ending values + * @param startValue The start value. + * @param endValue The end value. + * @return An <code>int[]</code> where each element is an interpolation between + * the same index in startValue and endValue. + */ + @Override + public int[] evaluate(float fraction, int[] startValue, int[] endValue) { + int[] array = mArray; + if (array == null) { + array = new int[startValue.length]; + } + for (int i = 0; i < array.length; i++) { + int start = startValue[i]; + int end = endValue[i]; + array[i] = (int) (start + (fraction * (end - start))); + } + return array; + } +}
diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java index 7b7c876..7a5b0ec 100644 --- a/core/java/android/animation/IntKeyframeSet.java +++ b/core/java/android/animation/IntKeyframeSet.java
@@ -30,7 +30,7 @@ * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the * Object equivalents of these primitive types.</p> */ -class IntKeyframeSet extends KeyframeSet { +class IntKeyframeSet extends KeyframeSet implements Keyframes.IntKeyframes { private int firstValue; private int lastValue; private int deltaValue; @@ -57,6 +57,12 @@ return newSet; } + @Override + public void invalidateCache() { + firstTime = true; + } + + @Override public int getIntValue(float fraction) { if (mNumKeyframes == 2) { if (firstTime) { @@ -129,5 +135,9 @@ return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).intValue(); } + @Override + public Class getType() { + return Integer.class; + } }
diff --git a/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java index dc8538f..5483c49 100644 --- a/core/java/android/animation/Keyframe.java +++ b/core/java/android/animation/Keyframe.java
@@ -35,6 +35,20 @@ */ public abstract class Keyframe implements Cloneable { /** + * Flag to indicate whether this keyframe has a valid value. This flag is used when an + * animation first starts, to populate placeholder keyframes with real values derived + * from the target object. + */ + boolean mHasValue; + + /** + * Flag to indicate whether the value in the keyframe was read from the target object or not. + * If so, its value will be recalculated if target changes. + */ + boolean mValueWasSetOnStart; + + + /** * The time at which mValue will hold true. */ float mFraction; @@ -51,12 +65,7 @@ */ private TimeInterpolator mInterpolator = null; - /** - * Flag to indicate whether this keyframe has a valid value. This flag is used when an - * animation first starts, to populate placeholder keyframes with real values derived - * from the target object. - */ - boolean mHasValue = false; + /** * Constructs a Keyframe object with the given time and value. The time defines the @@ -166,6 +175,20 @@ } /** + * If the Keyframe's value was acquired from the target object, this flag should be set so that, + * if target changes, value will be reset. + * + * @return boolean Whether this Keyframe's value was retieved from the target object or not. + */ + boolean valueWasSetOnStart() { + return mValueWasSetOnStart; + } + + void setValueWasSetOnStart(boolean valueWasSetOnStart) { + mValueWasSetOnStart = valueWasSetOnStart; + } + + /** * Gets the value for this Keyframe. * * @return The value for this Keyframe. @@ -261,7 +284,8 @@ @Override public ObjectKeyframe clone() { - ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mHasValue ? mValue : null); + ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), hasValue() ? mValue : null); + kfClone.mValueWasSetOnStart = mValueWasSetOnStart; kfClone.setInterpolator(getInterpolator()); return kfClone; } @@ -310,6 +334,7 @@ new IntKeyframe(getFraction(), mValue) : new IntKeyframe(getFraction()); kfClone.setInterpolator(getInterpolator()); + kfClone.mValueWasSetOnStart = mValueWasSetOnStart; return kfClone; } } @@ -356,6 +381,7 @@ new FloatKeyframe(getFraction(), mValue) : new FloatKeyframe(getFraction()); kfClone.setInterpolator(getInterpolator()); + kfClone.mValueWasSetOnStart = mValueWasSetOnStart; return kfClone; } }
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index 4026f7f..8d15db2 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java
@@ -21,6 +21,7 @@ import android.animation.Keyframe.IntKeyframe; import android.animation.Keyframe.FloatKeyframe; import android.animation.Keyframe.ObjectKeyframe; +import android.graphics.Path; import android.util.Log; /** @@ -28,7 +29,7 @@ * values between those keyframes for a given animation. The class internal to the animation * package because it is an implementation detail of how Keyframes are stored and used. */ -class KeyframeSet { +class KeyframeSet implements Keyframes { int mNumKeyframes; @@ -48,6 +49,18 @@ mInterpolator = mLastKeyframe.getInterpolator(); } + /** + * If subclass has variables that it calculates based on the Keyframes, it should reset them + * when this method is called because Keyframe contents might have changed. + */ + @Override + public void invalidateCache() { + } + + public ArrayList<Keyframe> getKeyframes() { + return mKeyframes; + } + public static KeyframeSet ofInt(int... values) { int numKeyframes = values.length; IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)]; @@ -137,6 +150,14 @@ return new KeyframeSet(keyframes); } + public static PathKeyframes ofPath(Path path) { + return new PathKeyframes(path); + } + + public static PathKeyframes ofPath(Path path, float error) { + return new PathKeyframes(path, error); + } + /** * Sets the TypeEvaluator to be used when calculating animated values. This object * is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet, @@ -150,6 +171,11 @@ } @Override + public Class getType() { + return mFirstKeyframe.getType(); + } + + @Override public KeyframeSet clone() { ArrayList<Keyframe> keyframes = mKeyframes; int numKeyframes = mKeyframes.size();
diff --git a/core/java/android/animation/Keyframes.java b/core/java/android/animation/Keyframes.java new file mode 100644 index 0000000..6611c6c --- /dev/null +++ b/core/java/android/animation/Keyframes.java
@@ -0,0 +1,94 @@ +/* + * Copyright (C) 2014 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.animation; + +import java.util.ArrayList; + +/** + * This interface abstracts a collection of Keyframe objects and is called by + * ValueAnimator to calculate values between those keyframes for a given animation. + */ +interface Keyframes extends Cloneable { + + /** + * Sets the TypeEvaluator to be used when calculating animated values. This object + * is required only for Keyframes that are not either IntKeyframes or FloatKeyframes, + * both of which assume their own evaluator to speed up calculations with those primitive + * types. + * + * @param evaluator The TypeEvaluator to be used to calculate animated values. + */ + void setEvaluator(TypeEvaluator evaluator); + + /** + * @return The value type contained by the contained Keyframes. + */ + Class getType(); + + /** + * Gets the animated value, given the elapsed fraction of the animation (interpolated by the + * animation's interpolator) and the evaluator used to calculate in-between values. This + * function maps the input fraction to the appropriate keyframe interval and a fraction + * between them and returns the interpolated value. Note that the input fraction may fall + * outside the [0-1] bounds, if the animation's interpolator made that happen (e.g., a + * spring interpolation that might send the fraction past 1.0). We handle this situation by + * just using the two keyframes at the appropriate end when the value is outside those bounds. + * + * @param fraction The elapsed fraction of the animation + * @return The animated value. + */ + Object getValue(float fraction); + + /** + * If subclass has variables that it calculates based on the Keyframes, it should reset them + * when this method is called because Keyframe contents might have changed. + */ + void invalidateCache(); + + /** + * @return A list of all Keyframes contained by this. This may return null if this is + * not made up of Keyframes. + */ + ArrayList<Keyframe> getKeyframes(); + + Keyframes clone(); + + /** + * A specialization of Keyframes that has integer primitive value calculation. + */ + public interface IntKeyframes extends Keyframes { + + /** + * Works like {@link #getValue(float)}, but returning a primitive. + * @param fraction The elapsed fraction of the animation + * @return The animated value. + */ + int getIntValue(float fraction); + } + + /** + * A specialization of Keyframes that has float primitive value calculation. + */ + public interface FloatKeyframes extends Keyframes { + + /** + * Works like {@link #getValue(float)}, but returning a primitive. + * @param fraction The elapsed fraction of the animation + * @return The animated value. + */ + float getFloatValue(float fraction); + } +}
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index 188408d..57906824 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java
@@ -899,11 +899,15 @@ PropertyValuesHolder[] oldValues = valueAnim.getValues(); for (int i = 0; i < oldValues.length; ++i) { PropertyValuesHolder pvh = oldValues[i]; - KeyframeSet keyframeSet = pvh.mKeyframeSet; - if (keyframeSet.mFirstKeyframe == null || - keyframeSet.mLastKeyframe == null || - !keyframeSet.mFirstKeyframe.getValue().equals( - keyframeSet.mLastKeyframe.getValue())) { + if (pvh.mKeyframes instanceof KeyframeSet) { + KeyframeSet keyframeSet = (KeyframeSet) pvh.mKeyframes; + if (keyframeSet.mFirstKeyframe == null || + keyframeSet.mLastKeyframe == null || + !keyframeSet.mFirstKeyframe.getValue().equals( + keyframeSet.mLastKeyframe.getValue())) { + valuesDiffer = true; + } + } else if (!pvh.mKeyframes.getValue(0).equals(pvh.mKeyframes.getValue(1))) { valuesDiffer = true; } }
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index 9c88ccf..500634c 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java
@@ -16,9 +16,14 @@ package android.animation; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.graphics.Path; +import android.graphics.PointF; import android.util.Log; import android.util.Property; +import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -39,10 +44,15 @@ * */ public final class ObjectAnimator extends ValueAnimator { + private static final String LOG_TAG = "ObjectAnimator"; + private static final boolean DBG = false; - // The target object on which the property exists, set in the constructor - private Object mTarget; + /** + * A weak reference to the target object on which the property exists, set + * in the constructor. We'll cancel the animation if this goes away. + */ + private WeakReference<Object> mTarget; private String mPropertyName; @@ -76,7 +86,7 @@ * * @param propertyName The name of the property being animated. Should not be null. */ - public void setPropertyName(String propertyName) { + public void setPropertyName(@NonNull String propertyName) { // mValues could be null if this is being constructed piecemeal. Just record the // propertyName to be used later when setValues() is called if so. if (mValues != null) { @@ -98,7 +108,7 @@ * * @param property The property being animated. Should not be null. */ - public void setProperty(Property property) { + public void setProperty(@NonNull Property property) { // mValues could be null if this is being constructed piecemeal. Just record the // propertyName to be used later when setValues() is called if so. if (mValues != null) { @@ -132,6 +142,7 @@ * object (if there was just one) or a comma-separated list of all of the * names (if there are more than one).</p> */ + @Nullable public String getPropertyName() { String propertyName = null; if (mPropertyName != null) { @@ -174,7 +185,7 @@ * @param propertyName The name of the property being animated. */ private ObjectAnimator(Object target, String propertyName) { - mTarget = target; + setTarget(target); setPropertyName(propertyName); } @@ -185,13 +196,13 @@ * @param property The property being animated. */ private <T> ObjectAnimator(T target, Property<T, ?> property) { - mTarget = target; + setTarget(target); setProperty(property); } /** * Constructs and returns an ObjectAnimator that animates between int values. A single - * value implies that that value is the one being animated to. Two values imply a starting + * value implies that that value is the one being animated to. Two values imply starting * and ending values. More than two values imply a starting value, values to animate through * along the way, and an ending value (these values will be distributed evenly across * the duration of the animation). @@ -210,8 +221,35 @@ } /** + * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> + * using two properties. A <code>Path</code></> animation moves in two dimensions, animating + * coordinates <code>(x, y)</code> together to follow the line. In this variation, the + * coordinates are integers that are set to separate properties designated by + * <code>xPropertyName</code> and <code>yPropertyName</code>. + * + * @param target The object whose properties are to be animated. This object should + * have public methods on it called <code>setNameX()</code> and + * <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code> + * are the value of <code>xPropertyName</code> and <code>yPropertyName</code> + * parameters, respectively. + * @param xPropertyName The name of the property for the x coordinate being animated. + * @param yPropertyName The name of the property for the y coordinate being animated. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + public static ObjectAnimator ofInt(Object target, String xPropertyName, String yPropertyName, + Path path) { + PathKeyframes keyframes = KeyframeSet.ofPath(path); + PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xPropertyName, + keyframes.createXIntKeyframes()); + PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yPropertyName, + keyframes.createYIntKeyframes()); + return ofPropertyValuesHolder(target, x, y); + } + + /** * Constructs and returns an ObjectAnimator that animates between int values. A single - * value implies that that value is the one being animated to. Two values imply a starting + * value implies that that value is the one being animated to. Two values imply starting * and ending values. More than two values imply a starting value, values to animate through * along the way, and an ending value (these values will be distributed evenly across * the duration of the animation). @@ -228,8 +266,137 @@ } /** + * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> + * using two properties. A <code>Path</code></> animation moves in two dimensions, animating + * coordinates <code>(x, y)</code> together to follow the line. In this variation, the + * coordinates are integers that are set to separate properties, <code>xProperty</code> and + * <code>yProperty</code>. + * + * @param target The object whose properties are to be animated. + * @param xProperty The property for the x coordinate being animated. + * @param yProperty The property for the y coordinate being animated. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty, + Property<T, Integer> yProperty, Path path) { + PathKeyframes keyframes = KeyframeSet.ofPath(path); + PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xProperty, + keyframes.createXIntKeyframes()); + PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yProperty, + keyframes.createYIntKeyframes()); + return ofPropertyValuesHolder(target, x, y); + } + + /** + * Constructs and returns an ObjectAnimator that animates over int values for a multiple + * parameters setter. Only public methods that take only int parameters are supported. + * Each <code>int[]</code> contains a complete set of parameters to the setter method. + * At least two <code>int[]</code> values must be provided, a start and end. More than two + * values imply a starting value, values to animate through along the way, and an ending + * value (these values will be distributed evenly across the duration of the animation). + * + * @param target The object whose property is to be animated. This object may + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also + * be the case-sensitive complete name of the public setter method. + * @param propertyName The name of the property being animated or the name of the setter method. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofMultiInt(Object target, String propertyName, int[][] values) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, values); + return ofPropertyValuesHolder(target, pvh); + } + + /** + * Constructs and returns an ObjectAnimator that animates the target using a multi-int setter + * along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions, + * animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the + * coordinates are integer x and y coordinates used in the first and second parameter of the + * setter, respectively. + * + * @param target The object whose property is to be animated. This object may + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also + * be the case-sensitive complete name of the public setter method. + * @param propertyName The name of the property being animated or the name of the setter method. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + public static ObjectAnimator ofMultiInt(Object target, String propertyName, Path path) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, path); + return ofPropertyValuesHolder(target, pvh); + } + + /** + * Constructs and returns an ObjectAnimator that animates over values for a multiple int + * parameters setter. Only public methods that take only int parameters are supported. + * <p>At least two values must be provided, a start and end. More than two + * values imply a starting value, values to animate through along the way, and an ending + * value (these values will be distributed evenly across the duration of the animation).</p> + * + * @param target The object whose property is to be animated. This object may + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also + * be the case-sensitive complete name of the public setter method. + * @param propertyName The name of the property being animated or the name of the setter method. + * @param converter Converts T objects into int parameters for the multi-value setter. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static <T> ObjectAnimator ofMultiInt(Object target, String propertyName, + TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, converter, + evaluator, values); + return ObjectAnimator.ofPropertyValuesHolder(target, pvh); + } + + /** + * Constructs and returns an ObjectAnimator that animates between color values. A single + * value implies that that value is the one being animated to. Two values imply starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. This object should + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. + * @param propertyName The name of the property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofArgb(Object target, String propertyName, int... values) { + ObjectAnimator animator = ofInt(target, propertyName, values); + animator.setEvaluator(ArgbEvaluator.getInstance()); + return animator; + } + + /** + * Constructs and returns an ObjectAnimator that animates between color values. A single + * value implies that that value is the one being animated to. Two values imply starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static <T> ObjectAnimator ofArgb(T target, Property<T, Integer> property, + int... values) { + ObjectAnimator animator = ofInt(target, property, values); + animator.setEvaluator(ArgbEvaluator.getInstance()); + return animator; + } + + /** * Constructs and returns an ObjectAnimator that animates between float values. A single - * value implies that that value is the one being animated to. Two values imply a starting + * value implies that that value is the one being animated to. Two values imply starting * and ending values. More than two values imply a starting value, values to animate through * along the way, and an ending value (these values will be distributed evenly across * the duration of the animation). @@ -248,8 +415,35 @@ } /** + * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> + * using two properties. A <code>Path</code></> animation moves in two dimensions, animating + * coordinates <code>(x, y)</code> together to follow the line. In this variation, the + * coordinates are floats that are set to separate properties designated by + * <code>xPropertyName</code> and <code>yPropertyName</code>. + * + * @param target The object whose properties are to be animated. This object should + * have public methods on it called <code>setNameX()</code> and + * <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code> + * are the value of the <code>xPropertyName</code> and <code>yPropertyName</code> + * parameters, respectively. + * @param xPropertyName The name of the property for the x coordinate being animated. + * @param yPropertyName The name of the property for the y coordinate being animated. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName, + Path path) { + PathKeyframes keyframes = KeyframeSet.ofPath(path); + PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xPropertyName, + keyframes.createXFloatKeyframes()); + PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yPropertyName, + keyframes.createYFloatKeyframes()); + return ofPropertyValuesHolder(target, x, y); + } + + /** * Constructs and returns an ObjectAnimator that animates between float values. A single - * value implies that that value is the one being animated to. Two values imply a starting + * value implies that that value is the one being animated to. Two values imply starting * and ending values. More than two values imply a starting value, values to animate through * along the way, and an ending value (these values will be distributed evenly across * the duration of the animation). @@ -267,8 +461,99 @@ } /** + * Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code> + * using two properties. A <code>Path</code></> animation moves in two dimensions, animating + * coordinates <code>(x, y)</code> together to follow the line. In this variation, the + * coordinates are floats that are set to separate properties, <code>xProperty</code> and + * <code>yProperty</code>. + * + * @param target The object whose properties are to be animated. + * @param xProperty The property for the x coordinate being animated. + * @param yProperty The property for the y coordinate being animated. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty, + Property<T, Float> yProperty, Path path) { + PathKeyframes keyframes = KeyframeSet.ofPath(path); + PropertyValuesHolder x = PropertyValuesHolder.ofKeyframes(xProperty, + keyframes.createXFloatKeyframes()); + PropertyValuesHolder y = PropertyValuesHolder.ofKeyframes(yProperty, + keyframes.createYFloatKeyframes()); + return ofPropertyValuesHolder(target, x, y); + } + + /** + * Constructs and returns an ObjectAnimator that animates over float values for a multiple + * parameters setter. Only public methods that take only float parameters are supported. + * Each <code>float[]</code> contains a complete set of parameters to the setter method. + * At least two <code>float[]</code> values must be provided, a start and end. More than two + * values imply a starting value, values to animate through along the way, and an ending + * value (these values will be distributed evenly across the duration of the animation). + * + * @param target The object whose property is to be animated. This object may + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also + * be the case-sensitive complete name of the public setter method. + * @param propertyName The name of the property being animated or the name of the setter method. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofMultiFloat(Object target, String propertyName, + float[][] values) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, values); + return ofPropertyValuesHolder(target, pvh); + } + + /** + * Constructs and returns an ObjectAnimator that animates the target using a multi-float setter + * along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions, + * animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the + * coordinates are float x and y coordinates used in the first and second parameter of the + * setter, respectively. + * + * @param target The object whose property is to be animated. This object may + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also + * be the case-sensitive complete name of the public setter method. + * @param propertyName The name of the property being animated or the name of the setter method. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + public static ObjectAnimator ofMultiFloat(Object target, String propertyName, Path path) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, path); + return ofPropertyValuesHolder(target, pvh); + } + + /** + * Constructs and returns an ObjectAnimator that animates over values for a multiple float + * parameters setter. Only public methods that take only float parameters are supported. + * <p>At least two values must be provided, a start and end. More than two + * values imply a starting value, values to animate through along the way, and an ending + * value (these values will be distributed evenly across the duration of the animation).</p> + * + * @param target The object whose property is to be animated. This object may + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also + * be the case-sensitive complete name of the public setter method. + * @param propertyName The name of the property being animated or the name of the setter method. + * @param converter Converts T objects into float parameters for the multi-value setter. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static <T> ObjectAnimator ofMultiFloat(Object target, String propertyName, + TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, converter, + evaluator, values); + return ObjectAnimator.ofPropertyValuesHolder(target, pvh); + } + + /** * Constructs and returns an ObjectAnimator that animates between Object values. A single - * value implies that that value is the one being animated to. Two values imply a starting + * value implies that that value is the one being animated to. Two values imply starting * and ending values. More than two values imply a starting value, values to animate through * along the way, and an ending value (these values will be distributed evenly across * the duration of the animation). @@ -292,8 +577,33 @@ } /** + * Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>. + * A <code>Path</code></> animation moves in two dimensions, animating coordinates + * <code>(x, y)</code> together to follow the line. This variant animates the coordinates + * in a <code>PointF</code> to follow the <code>Path</code>. If the <code>Property</code> + * associated with <code>propertyName</code> uses a type other than <code>PointF</code>, + * <code>converter</code> can be used to change from <code>PointF</code> to the type + * associated with the <code>Property</code>. + * + * @param target The object whose property is to be animated. This object should + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. + * @param propertyName The name of the property being animated. + * @param converter Converts a PointF to the type associated with the setter. May be + * null if conversion is unnecessary. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + @NonNull + public static ObjectAnimator ofObject(Object target, String propertyName, + @Nullable TypeConverter<PointF, ?> converter, Path path) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(propertyName, converter, path); + return ofPropertyValuesHolder(target, pvh); + } + + /** * Constructs and returns an ObjectAnimator that animates between Object values. A single - * value implies that that value is the one being animated to. Two values imply a starting + * value implies that that value is the one being animated to. Two values imply starting * and ending values. More than two values imply a starting value, values to animate through * along the way, and an ending value (these values will be distributed evenly across * the duration of the animation). @@ -306,6 +616,7 @@ * @param values A set of values that the animation will animate between over time. * @return An ObjectAnimator object that is set up to animate between the given values. */ + @NonNull public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property, TypeEvaluator<V> evaluator, V... values) { ObjectAnimator anim = new ObjectAnimator(target, property); @@ -315,6 +626,59 @@ } /** + * Constructs and returns an ObjectAnimator that animates between Object values. A single + * value implies that that value is the one being animated to. Two values imply starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). This variant supplies a <code>TypeConverter</code> to + * convert from the animated values to the type of the property. If only one value is + * supplied, the <code>TypeConverter</code> must be a + * {@link android.animation.BidirectionalTypeConverter} to retrieve the current value. + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param converter Converts the animated object to the Property type. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + @NonNull + public static <T, V, P> ObjectAnimator ofObject(T target, Property<T, P> property, + TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, evaluator, + values); + return ofPropertyValuesHolder(target, pvh); + } + + /** + * Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>. + * A <code>Path</code></> animation moves in two dimensions, animating coordinates + * <code>(x, y)</code> together to follow the line. This variant animates the coordinates + * in a <code>PointF</code> to follow the <code>Path</code>. If <code>property</code> + * uses a type other than <code>PointF</code>, <code>converter</code> can be used to change + * from <code>PointF</code> to the type associated with the <code>Property</code>. + * + * <p>The PointF passed to <code>converter</code> or <code>property</code>, if + * <code>converter</code> is <code>null</code>, is reused on each animation frame and should + * not be stored by the setter or TypeConverter.</p> + * + * @param target The object whose property is to be animated. + * @param property The property being animated. Should not be null. + * @param converter Converts a PointF to the type associated with the setter. May be + * null if conversion is unnecessary. + * @param path The <code>Path</code> to animate values along. + * @return An ObjectAnimator object that is set up to animate along <code>path</code>. + */ + @NonNull + public static <T, V> ObjectAnimator ofObject(T target, @NonNull Property<T, V> property, + @Nullable TypeConverter<PointF, V> converter, Path path) { + PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, path); + return ofPropertyValuesHolder(target, pvh); + } + + /** * Constructs and returns an ObjectAnimator that animates between the sets of values specified * in <code>PropertyValueHolder</code> objects. This variant should be used when animating * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows @@ -331,10 +695,11 @@ * over time. * @return An ObjectAnimator object that is set up to animate between the given values. */ + @NonNull public static ObjectAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values) { ObjectAnimator anim = new ObjectAnimator(); - anim.mTarget = target; + anim.setTarget(target); anim.setValues(values); return anim; } @@ -400,10 +765,10 @@ mAutoCancel = cancel; } - private boolean hasSameTargetAndProperties(Animator anim) { + private boolean hasSameTargetAndProperties(@Nullable Animator anim) { if (anim instanceof ObjectAnimator) { PropertyValuesHolder[] theirValues = ((ObjectAnimator) anim).getValues(); - if (((ObjectAnimator) anim).getTarget() == mTarget && + if (((ObjectAnimator) anim).getTarget() == getTarget() && mValues.length == theirValues.length) { for (int i = 0; i < mValues.length; ++i) { PropertyValuesHolder pvhMine = mValues[i]; @@ -453,13 +818,12 @@ } } if (DBG) { - Log.d("ObjectAnimator", "Anim target, duration: " + mTarget + ", " + getDuration()); + Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration()); for (int i = 0; i < mValues.length; ++i) { PropertyValuesHolder pvh = mValues[i]; - ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes; - Log.d("ObjectAnimator", " Values[" + i + "]: " + - pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " + - keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue()); + Log.d(LOG_TAG, " Values[" + i + "]: " + + pvh.getPropertyName() + ", " + pvh.mKeyframes.getValue(0) + ", " + + pvh.mKeyframes.getValue(1)); } } super.start(); @@ -482,9 +846,12 @@ if (!mInitialized) { // mValueType may change due to setter/getter setup; do this before calling super.init(), // which uses mValueType to set up the default type evaluator. - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupSetterAndGetter(mTarget); + final Object target = getTarget(); + if (target != null) { + final int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupSetterAndGetter(target); + } } super.initAnimation(); } @@ -500,6 +867,7 @@ * <code>ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start()</code>. */ @Override + @NonNull public ObjectAnimator setDuration(long duration) { super.setDuration(duration); return this; @@ -511,8 +879,9 @@ * * @return The object being animated */ + @Nullable public Object getTarget() { - return mTarget; + return mTarget == null ? null : mTarget.get(); } /** @@ -521,14 +890,11 @@ * @param target The object being animated */ @Override - public void setTarget(Object target) { - if (mTarget != target) { - final Object oldTarget = mTarget; - mTarget = target; - if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) { - return; - } - // New target type should cause re-initialization prior to starting + public void setTarget(@Nullable Object target) { + final Object oldTarget = getTarget(); + if (oldTarget != target) { + mTarget = target == null ? null : new WeakReference<Object>(target); + // New target should cause re-initialization prior to starting mInitialized = false; } } @@ -536,18 +902,26 @@ @Override public void setupStartValues() { initAnimation(); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupStartValue(mTarget); + + final Object target = getTarget(); + if (target != null) { + final int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupStartValue(target); + } } } @Override public void setupEndValues() { initAnimation(); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupEndValue(mTarget); + + final Object target = getTarget(); + if (target != null) { + final int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupEndValue(target); + } } } @@ -565,10 +939,17 @@ */ @Override void animateValue(float fraction) { + final Object target = getTarget(); + if (mTarget != null && target == null) { + // We lost the target reference, cancel and clean up. + cancel(); + return; + } + super.animateValue(fraction); int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { - mValues[i].setAnimatedValue(mTarget); + mValues[i].setAnimatedValue(target); } } @@ -579,9 +960,10 @@ } @Override + @NonNull public String toString() { String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " + - mTarget; + getTarget(); if (mValues != null) { for (int i = 0; i < mValues.length; ++i) { returnVal += "\n " + mValues[i].toString();
diff --git a/core/java/android/animation/PathKeyframes.java b/core/java/android/animation/PathKeyframes.java new file mode 100644 index 0000000..2a47b68 --- /dev/null +++ b/core/java/android/animation/PathKeyframes.java
@@ -0,0 +1,258 @@ +/* + * Copyright (C) 2014 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.animation; + +import android.graphics.Path; +import android.graphics.PointF; + +import java.util.ArrayList; + +/** + * PathKeyframes relies on approximating the Path as a series of line segments. + * The line segments are recursively divided until there is less than 1/2 pixel error + * between the lines and the curve. Each point of the line segment is converted + * to a Keyframe and a linear interpolation between Keyframes creates a good approximation + * of the curve. + * <p> + * PathKeyframes is optimized to reduce the number of objects created when there are + * many keyframes for a curve. + * </p> + * <p> + * Typically, the returned type is a PointF, but the individual components can be extracted + * as either an IntKeyframes or FloatKeyframes. + * </p> + */ +class PathKeyframes implements Keyframes { + private static final int FRACTION_OFFSET = 0; + private static final int X_OFFSET = 1; + private static final int Y_OFFSET = 2; + private static final int NUM_COMPONENTS = 3; + private static final ArrayList<Keyframe> EMPTY_KEYFRAMES = new ArrayList<Keyframe>(); + + private PointF mTempPointF = new PointF(); + private float[] mKeyframeData; + + public PathKeyframes(Path path) { + this(path, 0.5f); + } + + public PathKeyframes(Path path, float error) { + if (path == null || path.isEmpty()) { + throw new IllegalArgumentException("The path must not be null or empty"); + } + mKeyframeData = path.approximate(error); + } + + @Override + public ArrayList<Keyframe> getKeyframes() { + return EMPTY_KEYFRAMES; + } + + @Override + public Object getValue(float fraction) { + int numPoints = mKeyframeData.length / 3; + if (fraction < 0) { + return interpolateInRange(fraction, 0, 1); + } else if (fraction > 1) { + return interpolateInRange(fraction, numPoints - 2, numPoints - 1); + } else if (fraction == 0) { + return pointForIndex(0); + } else if (fraction == 1) { + return pointForIndex(numPoints - 1); + } else { + // Binary search for the correct section + int low = 0; + int high = numPoints - 1; + + while (low <= high) { + int mid = (low + high) / 2; + float midFraction = mKeyframeData[(mid * NUM_COMPONENTS) + FRACTION_OFFSET]; + + if (fraction < midFraction) { + high = mid - 1; + } else if (fraction > midFraction) { + low = mid + 1; + } else { + return pointForIndex(mid); + } + } + + // now high is below the fraction and low is above the fraction + return interpolateInRange(fraction, high, low); + } + } + + private PointF interpolateInRange(float fraction, int startIndex, int endIndex) { + int startBase = (startIndex * NUM_COMPONENTS); + int endBase = (endIndex * NUM_COMPONENTS); + + float startFraction = mKeyframeData[startBase + FRACTION_OFFSET]; + float endFraction = mKeyframeData[endBase + FRACTION_OFFSET]; + + float intervalFraction = (fraction - startFraction)/(endFraction - startFraction); + + float startX = mKeyframeData[startBase + X_OFFSET]; + float endX = mKeyframeData[endBase + X_OFFSET]; + float startY = mKeyframeData[startBase + Y_OFFSET]; + float endY = mKeyframeData[endBase + Y_OFFSET]; + + float x = interpolate(intervalFraction, startX, endX); + float y = interpolate(intervalFraction, startY, endY); + + mTempPointF.set(x, y); + return mTempPointF; + } + + @Override + public void invalidateCache() { + } + + @Override + public void setEvaluator(TypeEvaluator evaluator) { + } + + @Override + public Class getType() { + return PointF.class; + } + + @Override + public Keyframes clone() { + Keyframes clone = null; + try { + clone = (Keyframes) super.clone(); + } catch (CloneNotSupportedException e) {} + return clone; + } + + private PointF pointForIndex(int index) { + int base = (index * NUM_COMPONENTS); + int xOffset = base + X_OFFSET; + int yOffset = base + Y_OFFSET; + mTempPointF.set(mKeyframeData[xOffset], mKeyframeData[yOffset]); + return mTempPointF; + } + + private static float interpolate(float fraction, float startValue, float endValue) { + float diff = endValue - startValue; + return startValue + (diff * fraction); + } + + /** + * Returns a FloatKeyframes for the X component of the Path. + * @return a FloatKeyframes for the X component of the Path. + */ + public FloatKeyframes createXFloatKeyframes() { + return new FloatKeyframesBase() { + @Override + public float getFloatValue(float fraction) { + PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); + return pointF.x; + } + }; + } + + /** + * Returns a FloatKeyframes for the Y component of the Path. + * @return a FloatKeyframes for the Y component of the Path. + */ + public FloatKeyframes createYFloatKeyframes() { + return new FloatKeyframesBase() { + @Override + public float getFloatValue(float fraction) { + PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); + return pointF.y; + } + }; + } + + /** + * Returns an IntKeyframes for the X component of the Path. + * @return an IntKeyframes for the X component of the Path. + */ + public IntKeyframes createXIntKeyframes() { + return new IntKeyframesBase() { + @Override + public int getIntValue(float fraction) { + PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); + return Math.round(pointF.x); + } + }; + } + + /** + * Returns an IntKeyframeSet for the Y component of the Path. + * @return an IntKeyframeSet for the Y component of the Path. + */ + public IntKeyframes createYIntKeyframes() { + return new IntKeyframesBase() { + @Override + public int getIntValue(float fraction) { + PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); + return Math.round(pointF.y); + } + }; + } + + private abstract static class SimpleKeyframes implements Keyframes { + @Override + public void setEvaluator(TypeEvaluator evaluator) { + } + + @Override + public void invalidateCache() { + } + + @Override + public ArrayList<Keyframe> getKeyframes() { + return EMPTY_KEYFRAMES; + } + + @Override + public Keyframes clone() { + Keyframes clone = null; + try { + clone = (Keyframes) super.clone(); + } catch (CloneNotSupportedException e) {} + return clone; + } + } + + private abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes { + @Override + public Class getType() { + return Integer.class; + } + + @Override + public Object getValue(float fraction) { + return getIntValue(fraction); + } + } + + private abstract static class FloatKeyframesBase extends SimpleKeyframes + implements FloatKeyframes { + @Override + public Class getType() { + return Float.class; + } + + @Override + public Object getValue(float fraction) { + return getFloatValue(fraction); + } + } +}
diff --git a/core/java/android/animation/PointFEvaluator.java b/core/java/android/animation/PointFEvaluator.java new file mode 100644 index 0000000..91d501fc --- /dev/null +++ b/core/java/android/animation/PointFEvaluator.java
@@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 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.animation; + +import android.graphics.PointF; + +/** + * This evaluator can be used to perform type interpolation between <code>PointF</code> values. + */ +public class PointFEvaluator implements TypeEvaluator<PointF> { + + /** + * When null, a new PointF is returned on every evaluate call. When non-null, + * mPoint will be modified and returned on every evaluate. + */ + private PointF mPoint; + + /** + * Construct a PointFEvaluator that returns a new PointF on every evaluate call. + * To avoid creating an object for each evaluate call, + * {@link PointFEvaluator#PointFEvaluator(android.graphics.PointF)} should be used + * whenever possible. + */ + public PointFEvaluator() { + } + + /** + * Constructs a PointFEvaluator that modifies and returns <code>reuse</code> + * in {@link #evaluate(float, android.graphics.PointF, android.graphics.PointF)} calls. + * The value returned from + * {@link #evaluate(float, android.graphics.PointF, android.graphics.PointF)} should + * not be cached because it will change over time as the object is reused on each + * call. + * + * @param reuse A PointF to be modified and returned by evaluate. + */ + public PointFEvaluator(PointF reuse) { + mPoint = reuse; + } + + /** + * This function returns the result of linearly interpolating the start and + * end PointF values, with <code>fraction</code> representing the proportion + * between the start and end values. The calculation is a simple parametric + * calculation on each of the separate components in the PointF objects + * (x, y). + * + * <p>If {@link #PointFEvaluator(android.graphics.PointF)} was used to construct + * this PointFEvaluator, the object returned will be the <code>reuse</code> + * passed into the constructor.</p> + * + * @param fraction The fraction from the starting to the ending values + * @param startValue The start PointF + * @param endValue The end PointF + * @return A linear interpolation between the start and end values, given the + * <code>fraction</code> parameter. + */ + @Override + public PointF evaluate(float fraction, PointF startValue, PointF endValue) { + float x = startValue.x + (fraction * (endValue.x - startValue.x)); + float y = startValue.y + (fraction * (endValue.y - startValue.y)); + + if (mPoint != null) { + mPoint.set(x, y); + return mPoint; + } else { + return new PointF(x, y); + } + } +}
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 21f6eda..d372933 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -16,6 +16,8 @@ package android.animation; +import android.graphics.Path; +import android.graphics.PointF; import android.util.FloatProperty; import android.util.IntProperty; import android.util.Log; @@ -23,6 +25,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -72,7 +75,7 @@ /** * The set of keyframes (time/value pairs) that define this animation. */ - KeyframeSet mKeyframeSet = null; + Keyframes mKeyframes = null; // type evaluators for the primitive types handled by this implementation @@ -124,6 +127,11 @@ private Object mAnimatedValue; /** + * Converts from the source Object type to the setter Object type. + */ + private TypeConverter mConverter; + + /** * Internal utility constructor, used by the factory methods to set the property name. * @param propertyName The name of the property for this holder. */ @@ -166,6 +174,102 @@ /** * Constructs and returns a PropertyValuesHolder with a given property name and + * set of <code>int[]</code> values. At least two <code>int[]</code> values must be supplied, + * a start and end value. If more values are supplied, the values will be animated from the + * start, through all intermediate values to the end value. When used with ObjectAnimator, + * the elements of the array represent the parameters of the setter function. + * + * @param propertyName The name of the property being animated. Can also be the + * case-sensitive name of the entire setter method. Should not be null. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see IntArrayEvaluator#IntArrayEvaluator(int[]) + * @see ObjectAnimator#ofMultiInt(Object, String, TypeConverter, TypeEvaluator, Object[]) + */ + public static PropertyValuesHolder ofMultiInt(String propertyName, int[][] values) { + if (values.length < 2) { + throw new IllegalArgumentException("At least 2 values must be supplied"); + } + int numParameters = 0; + for (int i = 0; i < values.length; i++) { + if (values[i] == null) { + throw new IllegalArgumentException("values must not be null"); + } + int length = values[i].length; + if (i == 0) { + numParameters = length; + } else if (length != numParameters) { + throw new IllegalArgumentException("Values must all have the same length"); + } + } + IntArrayEvaluator evaluator = new IntArrayEvaluator(new int[numParameters]); + return new MultiIntValuesHolder(propertyName, null, evaluator, (Object[]) values); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property name to use + * as a multi-int setter. The values are animated along the path, with the first + * parameter of the setter set to the x coordinate and the second set to the y coordinate. + * + * @param propertyName The name of the property being animated. Can also be the + * case-sensitive name of the entire setter method. Should not be null. + * The setter must take exactly two <code>int</code> parameters. + * @param path The Path along which the values should be animated. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...) + */ + public static PropertyValuesHolder ofMultiInt(String propertyName, Path path) { + Keyframes keyframes = KeyframeSet.ofPath(path); + PointFToIntArray converter = new PointFToIntArray(); + return new MultiIntValuesHolder(propertyName, converter, null, keyframes); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of Object values for use with ObjectAnimator multi-value setters. The Object + * values are converted to <code>int[]</code> using the converter. + * + * @param propertyName The property being animated or complete name of the setter. + * Should not be null. + * @param converter Used to convert the animated value to setter parameters. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see ObjectAnimator#ofMultiInt(Object, String, TypeConverter, TypeEvaluator, Object[]) + * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...) + */ + public static <V> PropertyValuesHolder ofMultiInt(String propertyName, + TypeConverter<V, int[]> converter, TypeEvaluator<V> evaluator, V... values) { + return new MultiIntValuesHolder(propertyName, converter, evaluator, values); + } + + /** + * Constructs and returns a PropertyValuesHolder object with the specified property name or + * setter name for use in a multi-int setter function using ObjectAnimator. The values can be + * of any type, but the type should be consistent so that the supplied + * {@link android.animation.TypeEvaluator} can be used to to evaluate the animated value. The + * <code>converter</code> converts the values to parameters in the setter function. + * + * <p>At least two values must be supplied, a start and an end value.</p> + * + * @param propertyName The name of the property to associate with the set of values. This + * may also be the complete name of a setter function. + * @param converter Converts <code>values</code> into int parameters for the setter. + * Can be null if the Keyframes have int[] values. + * @param evaluator Used to interpolate between values. + * @param values The values at specific fractional times to evaluate between + * @return A PropertyValuesHolder for a multi-int parameter setter. + */ + public static <T> PropertyValuesHolder ofMultiInt(String propertyName, + TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, Keyframe... values) { + KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); + return new MultiIntValuesHolder(propertyName, converter, evaluator, keyframeSet); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property name and * set of float values. * @param propertyName The name of the property being animated. * @param values The values that the named property will animate between. @@ -188,6 +292,101 @@ /** * Constructs and returns a PropertyValuesHolder with a given property name and + * set of <code>float[]</code> values. At least two <code>float[]</code> values must be supplied, + * a start and end value. If more values are supplied, the values will be animated from the + * start, through all intermediate values to the end value. When used with ObjectAnimator, + * the elements of the array represent the parameters of the setter function. + * + * @param propertyName The name of the property being animated. Can also be the + * case-sensitive name of the entire setter method. Should not be null. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see FloatArrayEvaluator#FloatArrayEvaluator(float[]) + * @see ObjectAnimator#ofMultiFloat(Object, String, TypeConverter, TypeEvaluator, Object[]) + */ + public static PropertyValuesHolder ofMultiFloat(String propertyName, float[][] values) { + if (values.length < 2) { + throw new IllegalArgumentException("At least 2 values must be supplied"); + } + int numParameters = 0; + for (int i = 0; i < values.length; i++) { + if (values[i] == null) { + throw new IllegalArgumentException("values must not be null"); + } + int length = values[i].length; + if (i == 0) { + numParameters = length; + } else if (length != numParameters) { + throw new IllegalArgumentException("Values must all have the same length"); + } + } + FloatArrayEvaluator evaluator = new FloatArrayEvaluator(new float[numParameters]); + return new MultiFloatValuesHolder(propertyName, null, evaluator, (Object[]) values); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property name to use + * as a multi-float setter. The values are animated along the path, with the first + * parameter of the setter set to the x coordinate and the second set to the y coordinate. + * + * @param propertyName The name of the property being animated. Can also be the + * case-sensitive name of the entire setter method. Should not be null. + * The setter must take exactly two <code>float</code> parameters. + * @param path The Path along which the values should be animated. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...) + */ + public static PropertyValuesHolder ofMultiFloat(String propertyName, Path path) { + Keyframes keyframes = KeyframeSet.ofPath(path); + PointFToFloatArray converter = new PointFToFloatArray(); + return new MultiFloatValuesHolder(propertyName, converter, null, keyframes); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of Object values for use with ObjectAnimator multi-value setters. The Object + * values are converted to <code>float[]</code> using the converter. + * + * @param propertyName The property being animated or complete name of the setter. + * Should not be null. + * @param converter Used to convert the animated value to setter parameters. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see ObjectAnimator#ofMultiFloat(Object, String, TypeConverter, TypeEvaluator, Object[]) + */ + public static <V> PropertyValuesHolder ofMultiFloat(String propertyName, + TypeConverter<V, float[]> converter, TypeEvaluator<V> evaluator, V... values) { + return new MultiFloatValuesHolder(propertyName, converter, evaluator, values); + } + + /** + * Constructs and returns a PropertyValuesHolder object with the specified property name or + * setter name for use in a multi-float setter function using ObjectAnimator. The values can be + * of any type, but the type should be consistent so that the supplied + * {@link android.animation.TypeEvaluator} can be used to to evaluate the animated value. The + * <code>converter</code> converts the values to parameters in the setter function. + * + * <p>At least two values must be supplied, a start and an end value.</p> + * + * @param propertyName The name of the property to associate with the set of values. This + * may also be the complete name of a setter function. + * @param converter Converts <code>values</code> into float parameters for the setter. + * Can be null if the Keyframes have float[] values. + * @param evaluator Used to interpolate between values. + * @param values The values at specific fractional times to evaluate between + * @return A PropertyValuesHolder for a multi-float parameter setter. + */ + public static <T> PropertyValuesHolder ofMultiFloat(String propertyName, + TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, Keyframe... values) { + KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); + return new MultiFloatValuesHolder(propertyName, converter, evaluator, keyframeSet); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property name and * set of Object values. This variant also takes a TypeEvaluator because the system * cannot automatically interpolate between objects of unknown type. * @@ -207,6 +406,31 @@ } /** + * Constructs and returns a PropertyValuesHolder with a given property name and + * a Path along which the values should be animated. This variant supports a + * <code>TypeConverter</code> to convert from <code>PointF</code> to the target + * type. + * + * <p>The PointF passed to <code>converter</code> or <code>property</code>, if + * <code>converter</code> is <code>null</code>, is reused on each animation frame and should + * not be stored by the setter or TypeConverter.</p> + * + * @param propertyName The name of the property being animated. + * @param converter Converts a PointF to the type associated with the setter. May be + * null if conversion is unnecessary. + * @param path The Path along which the values should be animated. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static PropertyValuesHolder ofObject(String propertyName, + TypeConverter<PointF, ?> converter, Path path) { + PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); + pvh.mKeyframes = KeyframeSet.ofPath(path); + pvh.mValueType = PointF.class; + pvh.setConverter(converter); + return pvh; + } + + /** * Constructs and returns a PropertyValuesHolder with a given property and * set of Object values. This variant also takes a TypeEvaluator because the system * cannot automatically interpolate between objects of unknown type. @@ -227,6 +451,59 @@ } /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of Object values. This variant also takes a TypeEvaluator because the system + * cannot automatically interpolate between objects of unknown type. This variant also + * takes a <code>TypeConverter</code> to convert from animated values to the type + * of the property. If only one value is supplied, the <code>TypeConverter</code> + * must be a {@link android.animation.BidirectionalTypeConverter} to retrieve the current + * value. + * + * @param property The property being animated. Should not be null. + * @param converter Converts the animated object to the Property type. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + * @see #setConverter(TypeConverter) + * @see TypeConverter + */ + public static <T, V> PropertyValuesHolder ofObject(Property<?, V> property, + TypeConverter<T, V> converter, TypeEvaluator<T> evaluator, T... values) { + PropertyValuesHolder pvh = new PropertyValuesHolder(property); + pvh.setConverter(converter); + pvh.setObjectValues(values); + pvh.setEvaluator(evaluator); + return pvh; + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * a Path along which the values should be animated. This variant supports a + * <code>TypeConverter</code> to convert from <code>PointF</code> to the target + * type. + * + * <p>The PointF passed to <code>converter</code> or <code>property</code>, if + * <code>converter</code> is <code>null</code>, is reused on each animation frame and should + * not be stored by the setter or TypeConverter.</p> + * + * @param property The property being animated. Should not be null. + * @param converter Converts a PointF to the type associated with the setter. May be + * null if conversion is unnecessary. + * @param path The Path along which the values should be animated. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static <V> PropertyValuesHolder ofObject(Property<?, V> property, + TypeConverter<PointF, V> converter, Path path) { + PropertyValuesHolder pvh = new PropertyValuesHolder(property); + pvh.mKeyframes = KeyframeSet.ofPath(path); + pvh.mValueType = PointF.class; + pvh.setConverter(converter); + return pvh; + } + + /** * Constructs and returns a PropertyValuesHolder object with the specified property name and set * of values. These values can be of any type, but the type should be consistent so that * an appropriate {@link android.animation.TypeEvaluator} can be found that matches @@ -247,17 +524,7 @@ */ public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) { KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); - if (keyframeSet instanceof IntKeyframeSet) { - return new IntPropertyValuesHolder(propertyName, (IntKeyframeSet) keyframeSet); - } else if (keyframeSet instanceof FloatKeyframeSet) { - return new FloatPropertyValuesHolder(propertyName, (FloatKeyframeSet) keyframeSet); - } - else { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.mKeyframeSet = keyframeSet; - pvh.mValueType = ((Keyframe)values[0]).getType(); - return pvh; - } + return ofKeyframes(propertyName, keyframeSet); } /** @@ -278,15 +545,32 @@ */ public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) { KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); - if (keyframeSet instanceof IntKeyframeSet) { - return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet); - } else if (keyframeSet instanceof FloatKeyframeSet) { - return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet); + return ofKeyframes(property, keyframeSet); + } + + static PropertyValuesHolder ofKeyframes(String propertyName, Keyframes keyframes) { + if (keyframes instanceof Keyframes.IntKeyframes) { + return new IntPropertyValuesHolder(propertyName, (Keyframes.IntKeyframes) keyframes); + } else if (keyframes instanceof Keyframes.FloatKeyframes) { + return new FloatPropertyValuesHolder(propertyName, + (Keyframes.FloatKeyframes) keyframes); + } else { + PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); + pvh.mKeyframes = keyframes; + pvh.mValueType = keyframes.getType(); + return pvh; } - else { + } + + static PropertyValuesHolder ofKeyframes(Property property, Keyframes keyframes) { + if (keyframes instanceof Keyframes.IntKeyframes) { + return new IntPropertyValuesHolder(property, (Keyframes.IntKeyframes) keyframes); + } else if (keyframes instanceof Keyframes.FloatKeyframes) { + return new FloatPropertyValuesHolder(property, (Keyframes.FloatKeyframes) keyframes); + } else { PropertyValuesHolder pvh = new PropertyValuesHolder(property); - pvh.mKeyframeSet = keyframeSet; - pvh.mValueType = ((Keyframe)values[0]).getType(); + pvh.mKeyframes = keyframes; + pvh.mValueType = keyframes.getType(); return pvh; } } @@ -306,7 +590,7 @@ */ public void setIntValues(int... values) { mValueType = int.class; - mKeyframeSet = KeyframeSet.ofInt(values); + mKeyframes = KeyframeSet.ofInt(values); } /** @@ -324,7 +608,7 @@ */ public void setFloatValues(float... values) { mValueType = float.class; - mKeyframeSet = KeyframeSet.ofFloat(values); + mKeyframes = KeyframeSet.ofFloat(values); } /** @@ -339,7 +623,7 @@ for (int i = 0; i < numKeyframes; ++i) { keyframes[i] = (Keyframe)values[i]; } - mKeyframeSet = new KeyframeSet(keyframes); + mKeyframes = new KeyframeSet(keyframes); } /** @@ -357,7 +641,20 @@ */ public void setObjectValues(Object... values) { mValueType = values[0].getClass(); - mKeyframeSet = KeyframeSet.ofObject(values); + mKeyframes = KeyframeSet.ofObject(values); + if (mEvaluator != null) { + mKeyframes.setEvaluator(mEvaluator); + } + } + + /** + * Sets the converter to convert from the values type to the setter's parameter type. + * If only one value is supplied, <var>converter</var> must be a + * {@link android.animation.BidirectionalTypeConverter}. + * @param converter The converter to use to convert values. + */ + public void setConverter(TypeConverter converter) { + mConverter = converter; } /** @@ -389,22 +686,24 @@ } else { args = new Class[1]; Class typeVariants[]; - if (mValueType.equals(Float.class)) { + if (valueType.equals(Float.class)) { typeVariants = FLOAT_VARIANTS; - } else if (mValueType.equals(Integer.class)) { + } else if (valueType.equals(Integer.class)) { typeVariants = INTEGER_VARIANTS; - } else if (mValueType.equals(Double.class)) { + } else if (valueType.equals(Double.class)) { typeVariants = DOUBLE_VARIANTS; } else { typeVariants = new Class[1]; - typeVariants[0] = mValueType; + typeVariants[0] = valueType; } for (Class typeVariant : typeVariants) { args[0] = typeVariant; try { returnVal = targetClass.getMethod(methodName, args); - // change the value type to suit - mValueType = typeVariant; + if (mConverter == null) { + // change the value type to suit + mValueType = typeVariant; + } return returnVal; } catch (NoSuchMethodException e) { // Swallow the error and keep trying other variants @@ -415,7 +714,7 @@ if (returnVal == null) { Log.w("PropertyValuesHolder", "Method " + - getMethodName(prefix, mPropertyName) + "() with type " + mValueType + + getMethodName(prefix, mPropertyName) + "() with type " + valueType + " not found on target class " + targetClass); } @@ -465,7 +764,8 @@ * @param targetClass The Class on which the requested method should exist. */ void setupSetter(Class targetClass) { - mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", mValueType); + Class<?> propertyType = mConverter == null ? mValueType : mConverter.getTargetType(); + mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", propertyType); } /** @@ -486,13 +786,21 @@ * @param target The object on which the setter (and possibly getter) exist. */ void setupSetterAndGetter(Object target) { + mKeyframes.invalidateCache(); if (mProperty != null) { // check to make sure that mProperty is on the class of target try { - Object testValue = mProperty.get(target); - for (Keyframe kf : mKeyframeSet.mKeyframes) { - if (!kf.hasValue()) { - kf.setValue(mProperty.get(target)); + Object testValue = null; + ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + int keyframeCount = keyframes == null ? 0 : keyframes.size(); + for (int i = 0; i < keyframeCount; i++) { + Keyframe kf = keyframes.get(i); + if (!kf.hasValue() || kf.valueWasSetOnStart()) { + if (testValue == null) { + testValue = convertBack(mProperty.get(target)); + } + kf.setValue(testValue); + kf.setValueWasSetOnStart(true); } } return; @@ -506,8 +814,11 @@ if (mSetter == null) { setupSetter(targetClass); } - for (Keyframe kf : mKeyframeSet.mKeyframes) { - if (!kf.hasValue()) { + ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + int keyframeCount = keyframes == null ? 0 : keyframes.size(); + for (int i = 0; i < keyframeCount; i++) { + Keyframe kf = keyframes.get(i); + if (!kf.hasValue() || kf.valueWasSetOnStart()) { if (mGetter == null) { setupGetter(targetClass); if (mGetter == null) { @@ -516,7 +827,9 @@ } } try { - kf.setValue(mGetter.invoke(target)); + Object value = convertBack(mGetter.invoke(target)); + kf.setValue(value); + kf.setValueWasSetOnStart(true); } catch (InvocationTargetException e) { Log.e("PropertyValuesHolder", e.toString()); } catch (IllegalAccessException e) { @@ -526,6 +839,18 @@ } } + private Object convertBack(Object value) { + if (mConverter != null) { + if (!(mConverter instanceof BidirectionalTypeConverter)) { + throw new IllegalArgumentException("Converter " + + mConverter.getClass().getName() + + " must be a BidirectionalTypeConverter"); + } + value = ((BidirectionalTypeConverter) mConverter).convertBack(value); + } + return value; + } + /** * Utility function to set the value stored in a particular Keyframe. The value used is * whatever the value is for the property name specified in the keyframe on the target object. @@ -535,7 +860,8 @@ */ private void setupValue(Object target, Keyframe kf) { if (mProperty != null) { - kf.setValue(mProperty.get(target)); + Object value = convertBack(mProperty.get(target)); + kf.setValue(value); } try { if (mGetter == null) { @@ -546,7 +872,8 @@ return; } } - kf.setValue(mGetter.invoke(target)); + Object value = convertBack(mGetter.invoke(target)); + kf.setValue(value); } catch (InvocationTargetException e) { Log.e("PropertyValuesHolder", e.toString()); } catch (IllegalAccessException e) { @@ -563,7 +890,10 @@ * @param target The object which holds the start values that should be set. */ void setupStartValue(Object target) { - setupValue(target, mKeyframeSet.mKeyframes.get(0)); + ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + if (!keyframes.isEmpty()) { + setupValue(target, keyframes.get(0)); + } } /** @@ -575,7 +905,10 @@ * @param target The object which holds the start values that should be set. */ void setupEndValue(Object target) { - setupValue(target, mKeyframeSet.mKeyframes.get(mKeyframeSet.mKeyframes.size() - 1)); + ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes(); + if (!keyframes.isEmpty()) { + setupValue(target, keyframes.get(keyframes.size() - 1)); + } } @Override @@ -584,7 +917,7 @@ PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); newPVH.mPropertyName = mPropertyName; newPVH.mProperty = mProperty; - newPVH.mKeyframeSet = mKeyframeSet.clone(); + newPVH.mKeyframes = mKeyframes.clone(); newPVH.mEvaluator = mEvaluator; return newPVH; } catch (CloneNotSupportedException e) { @@ -631,7 +964,7 @@ if (mEvaluator != null) { // KeyframeSet knows how to evaluate the common types - only give it a custom // evaluator if one has been set on this class - mKeyframeSet.setEvaluator(mEvaluator); + mKeyframes.setEvaluator(mEvaluator); } } @@ -647,7 +980,7 @@ */ public void setEvaluator(TypeEvaluator evaluator) { mEvaluator = evaluator; - mKeyframeSet.setEvaluator(evaluator); + mKeyframes.setEvaluator(evaluator); } /** @@ -657,7 +990,8 @@ * @param fraction The elapsed, interpolated fraction of the animation. */ void calculateValue(float fraction) { - mAnimatedValue = mKeyframeSet.getValue(fraction); + Object value = mKeyframes.getValue(fraction); + mAnimatedValue = mConverter == null ? value : mConverter.convert(value); } /** @@ -714,7 +1048,7 @@ @Override public String toString() { - return mPropertyName + ": " + mKeyframeSet.toString(); + return mPropertyName + ": " + mKeyframes.toString(); } /** @@ -748,21 +1082,21 @@ long mJniSetter; private IntProperty mIntProperty; - IntKeyframeSet mIntKeyframeSet; + Keyframes.IntKeyframes mIntKeyframes; int mIntAnimatedValue; - public IntPropertyValuesHolder(String propertyName, IntKeyframeSet keyframeSet) { + public IntPropertyValuesHolder(String propertyName, Keyframes.IntKeyframes keyframes) { super(propertyName); mValueType = int.class; - mKeyframeSet = keyframeSet; - mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + mKeyframes = keyframes; + mIntKeyframes = keyframes; } - public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) { + public IntPropertyValuesHolder(Property property, Keyframes.IntKeyframes keyframes) { super(property); mValueType = int.class; - mKeyframeSet = keyframeSet; - mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + mKeyframes = keyframes; + mIntKeyframes = keyframes; if (property instanceof IntProperty) { mIntProperty = (IntProperty) mProperty; } @@ -784,12 +1118,12 @@ @Override public void setIntValues(int... values) { super.setIntValues(values); - mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + mIntKeyframes = (Keyframes.IntKeyframes) mKeyframes; } @Override void calculateValue(float fraction) { - mIntAnimatedValue = mIntKeyframeSet.getIntValue(fraction); + mIntAnimatedValue = mIntKeyframes.getIntValue(fraction); } @Override @@ -800,7 +1134,7 @@ @Override public IntPropertyValuesHolder clone() { IntPropertyValuesHolder newPVH = (IntPropertyValuesHolder) super.clone(); - newPVH.mIntKeyframeSet = (IntKeyframeSet) newPVH.mKeyframeSet; + newPVH.mIntKeyframes = (Keyframes.IntKeyframes) newPVH.mKeyframes; return newPVH; } @@ -885,21 +1219,21 @@ long mJniSetter; private FloatProperty mFloatProperty; - FloatKeyframeSet mFloatKeyframeSet; + Keyframes.FloatKeyframes mFloatKeyframes; float mFloatAnimatedValue; - public FloatPropertyValuesHolder(String propertyName, FloatKeyframeSet keyframeSet) { + public FloatPropertyValuesHolder(String propertyName, Keyframes.FloatKeyframes keyframes) { super(propertyName); mValueType = float.class; - mKeyframeSet = keyframeSet; - mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + mKeyframes = keyframes; + mFloatKeyframes = keyframes; } - public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) { + public FloatPropertyValuesHolder(Property property, Keyframes.FloatKeyframes keyframes) { super(property); mValueType = float.class; - mKeyframeSet = keyframeSet; - mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + mKeyframes = keyframes; + mFloatKeyframes = keyframes; if (property instanceof FloatProperty) { mFloatProperty = (FloatProperty) mProperty; } @@ -921,12 +1255,12 @@ @Override public void setFloatValues(float... values) { super.setFloatValues(values); - mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes; } @Override void calculateValue(float fraction) { - mFloatAnimatedValue = mFloatKeyframeSet.getFloatValue(fraction); + mFloatAnimatedValue = mFloatKeyframes.getFloatValue(fraction); } @Override @@ -937,7 +1271,7 @@ @Override public FloatPropertyValuesHolder clone() { FloatPropertyValuesHolder newPVH = (FloatPropertyValuesHolder) super.clone(); - newPVH.mFloatKeyframeSet = (FloatKeyframeSet) newPVH.mKeyframeSet; + newPVH.mFloatKeyframes = (Keyframes.FloatKeyframes) newPVH.mKeyframes; return newPVH; } @@ -1015,8 +1349,263 @@ } + static class MultiFloatValuesHolder extends PropertyValuesHolder { + private long mJniSetter; + private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = + new HashMap<Class, HashMap<String, Long>>(); + + public MultiFloatValuesHolder(String propertyName, TypeConverter converter, + TypeEvaluator evaluator, Object... values) { + super(propertyName); + setConverter(converter); + setObjectValues(values); + setEvaluator(evaluator); + } + + public MultiFloatValuesHolder(String propertyName, TypeConverter converter, + TypeEvaluator evaluator, Keyframes keyframes) { + super(propertyName); + setConverter(converter); + mKeyframes = keyframes; + setEvaluator(evaluator); + } + + /** + * Internal function to set the value on the target object, using the setter set up + * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator + * to handle turning the value calculated by ValueAnimator into a value set on the object + * according to the name of the property. + * + * @param target The target object on which the value is set + */ + @Override + void setAnimatedValue(Object target) { + float[] values = (float[]) getAnimatedValue(); + int numParameters = values.length; + if (mJniSetter != 0) { + switch (numParameters) { + case 1: + nCallFloatMethod(target, mJniSetter, values[0]); + break; + case 2: + nCallTwoFloatMethod(target, mJniSetter, values[0], values[1]); + break; + case 4: + nCallFourFloatMethod(target, mJniSetter, values[0], values[1], + values[2], values[3]); + break; + default: { + nCallMultipleFloatMethod(target, mJniSetter, values); + break; + } + } + } + } + + /** + * Internal function (called from ObjectAnimator) to set up the setter and getter + * prior to running the animation. No getter can be used for multiple parameters. + * + * @param target The object on which the setter exists. + */ + @Override + void setupSetterAndGetter(Object target) { + setupSetter(target.getClass()); + } + + @Override + void setupSetter(Class targetClass) { + if (mJniSetter != 0) { + return; + } + try { + mPropertyMapLock.writeLock().lock(); + HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); + if (propertyMap != null) { + Long jniSetterLong = propertyMap.get(mPropertyName); + if (jniSetterLong != null) { + mJniSetter = jniSetterLong; + } + } + if (mJniSetter == 0) { + String methodName = getMethodName("set", mPropertyName); + calculateValue(0f); + float[] values = (float[]) getAnimatedValue(); + int numParams = values.length; + try { + mJniSetter = nGetMultipleFloatMethod(targetClass, methodName, numParams); + } catch (NoSuchMethodError e) { + // try without the 'set' prefix + mJniSetter = nGetMultipleFloatMethod(targetClass, mPropertyName, numParams); + } + if (mJniSetter != 0) { + if (propertyMap == null) { + propertyMap = new HashMap<String, Long>(); + sJNISetterPropertyMap.put(targetClass, propertyMap); + } + propertyMap.put(mPropertyName, mJniSetter); + } + } + } finally { + mPropertyMapLock.writeLock().unlock(); + } + } + } + + static class MultiIntValuesHolder extends PropertyValuesHolder { + private long mJniSetter; + private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = + new HashMap<Class, HashMap<String, Long>>(); + + public MultiIntValuesHolder(String propertyName, TypeConverter converter, + TypeEvaluator evaluator, Object... values) { + super(propertyName); + setConverter(converter); + setObjectValues(values); + setEvaluator(evaluator); + } + + public MultiIntValuesHolder(String propertyName, TypeConverter converter, + TypeEvaluator evaluator, Keyframes keyframes) { + super(propertyName); + setConverter(converter); + mKeyframes = keyframes; + setEvaluator(evaluator); + } + + /** + * Internal function to set the value on the target object, using the setter set up + * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator + * to handle turning the value calculated by ValueAnimator into a value set on the object + * according to the name of the property. + * + * @param target The target object on which the value is set + */ + @Override + void setAnimatedValue(Object target) { + int[] values = (int[]) getAnimatedValue(); + int numParameters = values.length; + if (mJniSetter != 0) { + switch (numParameters) { + case 1: + nCallIntMethod(target, mJniSetter, values[0]); + break; + case 2: + nCallTwoIntMethod(target, mJniSetter, values[0], values[1]); + break; + case 4: + nCallFourIntMethod(target, mJniSetter, values[0], values[1], + values[2], values[3]); + break; + default: { + nCallMultipleIntMethod(target, mJniSetter, values); + break; + } + } + } + } + + /** + * Internal function (called from ObjectAnimator) to set up the setter and getter + * prior to running the animation. No getter can be used for multiple parameters. + * + * @param target The object on which the setter exists. + */ + @Override + void setupSetterAndGetter(Object target) { + setupSetter(target.getClass()); + } + + @Override + void setupSetter(Class targetClass) { + if (mJniSetter != 0) { + return; + } + try { + mPropertyMapLock.writeLock().lock(); + HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); + if (propertyMap != null) { + Long jniSetterLong = propertyMap.get(mPropertyName); + if (jniSetterLong != null) { + mJniSetter = jniSetterLong; + } + } + if (mJniSetter == 0) { + String methodName = getMethodName("set", mPropertyName); + calculateValue(0f); + int[] values = (int[]) getAnimatedValue(); + int numParams = values.length; + try { + mJniSetter = nGetMultipleIntMethod(targetClass, methodName, numParams); + } catch (NoSuchMethodError e) { + // try without the 'set' prefix + mJniSetter = nGetMultipleIntMethod(targetClass, mPropertyName, numParams); + } + if (mJniSetter != 0) { + if (propertyMap == null) { + propertyMap = new HashMap<String, Long>(); + sJNISetterPropertyMap.put(targetClass, propertyMap); + } + propertyMap.put(mPropertyName, mJniSetter); + } + } + } finally { + mPropertyMapLock.writeLock().unlock(); + } + } + } + + /** + * Convert from PointF to float[] for multi-float setters along a Path. + */ + private static class PointFToFloatArray extends TypeConverter<PointF, float[]> { + private float[] mCoordinates = new float[2]; + + public PointFToFloatArray() { + super(PointF.class, float[].class); + } + + @Override + public float[] convert(PointF value) { + mCoordinates[0] = value.x; + mCoordinates[1] = value.y; + return mCoordinates; + } + }; + + /** + * Convert from PointF to int[] for multi-int setters along a Path. + */ + private static class PointFToIntArray extends TypeConverter<PointF, int[]> { + private int[] mCoordinates = new int[2]; + + public PointFToIntArray() { + super(PointF.class, int[].class); + } + + @Override + public int[] convert(PointF value) { + mCoordinates[0] = Math.round(value.x); + mCoordinates[1] = Math.round(value.y); + return mCoordinates; + } + }; + native static private long nGetIntMethod(Class targetClass, String methodName); native static private long nGetFloatMethod(Class targetClass, String methodName); + native static private long nGetMultipleIntMethod(Class targetClass, String methodName, + int numParams); + native static private long nGetMultipleFloatMethod(Class targetClass, String methodName, + int numParams); native static private void nCallIntMethod(Object target, long methodID, int arg); native static private void nCallFloatMethod(Object target, long methodID, float arg); + native static private void nCallTwoIntMethod(Object target, long methodID, int arg1, int arg2); + native static private void nCallFourIntMethod(Object target, long methodID, int arg1, int arg2, + int arg3, int arg4); + native static private void nCallMultipleIntMethod(Object target, long methodID, int[] args); + native static private void nCallTwoFloatMethod(Object target, long methodID, float arg1, + float arg2); + native static private void nCallFourFloatMethod(Object target, long methodID, float arg1, + float arg2, float arg3, float arg4); + native static private void nCallMultipleFloatMethod(Object target, long methodID, float[] args); }
diff --git a/core/java/android/animation/RectEvaluator.java b/core/java/android/animation/RectEvaluator.java index 28d496b..23eb766 100644 --- a/core/java/android/animation/RectEvaluator.java +++ b/core/java/android/animation/RectEvaluator.java
@@ -23,12 +23,45 @@ public class RectEvaluator implements TypeEvaluator<Rect> { /** + * When null, a new Rect is returned on every evaluate call. When non-null, + * mRect will be modified and returned on every evaluate. + */ + private Rect mRect; + + /** + * Construct a RectEvaluator that returns a new Rect on every evaluate call. + * To avoid creating an object for each evaluate call, + * {@link RectEvaluator#RectEvaluator(android.graphics.Rect)} should be used + * whenever possible. + */ + public RectEvaluator() { + } + + /** + * Constructs a RectEvaluator that modifies and returns <code>reuseRect</code> + * in {@link #evaluate(float, android.graphics.Rect, android.graphics.Rect)} calls. + * The value returned from + * {@link #evaluate(float, android.graphics.Rect, android.graphics.Rect)} should + * not be cached because it will change over time as the object is reused on each + * call. + * + * @param reuseRect A Rect to be modified and returned by evaluate. + */ + public RectEvaluator(Rect reuseRect) { + mRect = reuseRect; + } + + /** * This function returns the result of linearly interpolating the start and * end Rect values, with <code>fraction</code> representing the proportion * between the start and end values. The calculation is a simple parametric * calculation on each of the separate components in the Rect objects * (left, top, right, and bottom). * + * <p>If {@link #RectEvaluator(android.graphics.Rect)} was used to construct + * this RectEvaluator, the object returned will be the <code>reuseRect</code> + * passed into the constructor.</p> + * * @param fraction The fraction from the starting to the ending values * @param startValue The start Rect * @param endValue The end Rect @@ -37,9 +70,15 @@ */ @Override public Rect evaluate(float fraction, Rect startValue, Rect endValue) { - return new Rect(startValue.left + (int)((endValue.left - startValue.left) * fraction), - startValue.top + (int)((endValue.top - startValue.top) * fraction), - startValue.right + (int)((endValue.right - startValue.right) * fraction), - startValue.bottom + (int)((endValue.bottom - startValue.bottom) * fraction)); + int left = startValue.left + (int) ((endValue.left - startValue.left) * fraction); + int top = startValue.top + (int) ((endValue.top - startValue.top) * fraction); + int right = startValue.right + (int) ((endValue.right - startValue.right) * fraction); + int bottom = startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction); + if (mRect == null) { + return new Rect(left, top, right, bottom); + } else { + mRect.set(left, top, right, bottom); + return mRect; + } } }
diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java new file mode 100644 index 0000000..0f85f4906 --- /dev/null +++ b/core/java/android/animation/RevealAnimator.java
@@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 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.animation; + +import android.view.RenderNodeAnimator; +import android.view.View; + +/** + * Reveals a View with an animated clipping circle. + * The clipping is implemented efficiently by talking to a private reveal API on View. + * This hidden class currently only accessed by the {@link android.view.View}. + * + * @hide + */ +public class RevealAnimator extends RenderNodeAnimator { + + private View mClipView; + + public RevealAnimator(View clipView, int x, int y, + float startRadius, float endRadius) { + super(x, y, startRadius, endRadius); + mClipView = clipView; + setTarget(mClipView); + } + + @Override + protected void onFinished() { + mClipView.setRevealClip(false, 0, 0, 0); + super.onFinished(); + } + +}
diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java new file mode 100644 index 0000000..7256a06 --- /dev/null +++ b/core/java/android/animation/StateListAnimator.java
@@ -0,0 +1,212 @@ +/* + * Copyright (C) 2014 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.animation; + +import android.util.StateSet; +import android.view.View; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +/** + * Lets you define a number of Animators that will run on the attached View depending on the View's + * drawable state. + * <p> + * It can be defined in an XML file with the <code><selector></code> element. + * Each State Animator is defined in a nested <code><item></code> element. + * + * @attr ref android.R.styleable#DrawableStates_state_focused + * @attr ref android.R.styleable#DrawableStates_state_window_focused + * @attr ref android.R.styleable#DrawableStates_state_enabled + * @attr ref android.R.styleable#DrawableStates_state_checkable + * @attr ref android.R.styleable#DrawableStates_state_checked + * @attr ref android.R.styleable#DrawableStates_state_selected + * @attr ref android.R.styleable#DrawableStates_state_activated + * @attr ref android.R.styleable#DrawableStates_state_active + * @attr ref android.R.styleable#DrawableStates_state_single + * @attr ref android.R.styleable#DrawableStates_state_first + * @attr ref android.R.styleable#DrawableStates_state_middle + * @attr ref android.R.styleable#DrawableStates_state_last + * @attr ref android.R.styleable#DrawableStates_state_pressed + * @attr ref android.R.styleable#StateListAnimatorItem_animation + */ +public class StateListAnimator { + + private final ArrayList<Tuple> mTuples = new ArrayList<Tuple>(); + + private Tuple mLastMatch = null; + + private Animator mRunningAnimator = null; + + private WeakReference<View> mViewRef; + + private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animation.setTarget(null); + if (mRunningAnimator == animation) { + mRunningAnimator = null; + } + } + }; + + /** + * Associates the given animator with the provided drawable state specs so that it will be run + * when the View's drawable state matches the specs. + * + * @param specs The drawable state specs to match against + * @param animator The animator to run when the specs match + */ + public void addState(int[] specs, Animator animator) { + Tuple tuple = new Tuple(specs, animator); + tuple.mAnimator.addListener(mAnimatorListener); + mTuples.add(tuple); + } + + /** + * Returns the current {@link android.animation.Animator} which is started because of a state + * change. + * + * @return The currently running Animator or null if no Animator is running + * @hide + */ + public Animator getRunningAnimator() { + return mRunningAnimator; + } + + /** + * @hide + */ + public View getTarget() { + return mViewRef == null ? null : mViewRef.get(); + } + + /** + * Called by View + * @hide + */ + public void setTarget(View view) { + final View current = getTarget(); + if (current == view) { + return; + } + if (current != null) { + clearTarget(); + } + if (view != null) { + mViewRef = new WeakReference<View>(view); + } + + } + + private void clearTarget() { + final int size = mTuples.size(); + for (int i = 0; i < size; i++) { + mTuples.get(i).mAnimator.setTarget(null); + } + + mViewRef = null; + mLastMatch = null; + mRunningAnimator = null; + } + + /** + * Called by View + * @hide + */ + public void setState(int[] state) { + Tuple match = null; + final int count = mTuples.size(); + for (int i = 0; i < count; i++) { + final Tuple tuple = mTuples.get(i); + if (StateSet.stateSetMatches(tuple.mSpecs, state)) { + match = tuple; + break; + } + } + if (match == mLastMatch) { + return; + } + if (mLastMatch != null) { + cancel(); + } + mLastMatch = match; + if (match != null) { + start(match); + } + } + + private void start(Tuple match) { + match.mAnimator.setTarget(getTarget()); + mRunningAnimator = match.mAnimator; + mRunningAnimator.start(); + } + + private void cancel() { + if (mRunningAnimator != null) { + mRunningAnimator.cancel(); + mRunningAnimator = null; + } + } + + /** + * @hide + */ + public ArrayList<Tuple> getTuples() { + return mTuples; + } + + /** + * If there is an animation running for a recent state change, ends it. + * <p> + * This causes the animation to assign the end value(s) to the View. + */ + public void jumpToCurrentState() { + if (mRunningAnimator != null) { + mRunningAnimator.end(); + } + } + + /** + * @hide + */ + public static class Tuple { + + final int[] mSpecs; + + final Animator mAnimator; + + private Tuple(int[] specs, Animator animator) { + mSpecs = specs; + mAnimator = animator; + } + + /** + * @hide + */ + public int[] getSpecs() { + return mSpecs; + } + + /** + * @hide + */ + public Animator getAnimator() { + return mAnimator; + } + } +}
diff --git a/core/java/android/animation/TypeConverter.java b/core/java/android/animation/TypeConverter.java new file mode 100644 index 0000000..9ead2ad --- /dev/null +++ b/core/java/android/animation/TypeConverter.java
@@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 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.animation; + +/** + * Abstract base class used convert type T to another type V. This + * is necessary when the value types of in animation are different + * from the property type. + * @see PropertyValuesHolder#setConverter(TypeConverter) + */ +public abstract class TypeConverter<T, V> { + private Class<T> mFromClass; + private Class<V> mToClass; + + public TypeConverter(Class<T> fromClass, Class<V> toClass) { + mFromClass = fromClass; + mToClass = toClass; + } + + /** + * Returns the target converted type. Used by the animation system to determine + * the proper setter function to call. + * @return The Class to convert the input to. + */ + Class<V> getTargetType() { + return mToClass; + } + + /** + * Returns the source conversion type. + */ + Class<T> getSourceType() { + return mFromClass; + } + + /** + * Converts a value from one type to another. + * @param value The Object to convert. + * @return A value of type V, converted from <code>value</code>. + */ + public abstract V convert(T value); +}
diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java index 2640457..429c435 100644 --- a/core/java/android/animation/TypeEvaluator.java +++ b/core/java/android/animation/TypeEvaluator.java
@@ -29,7 +29,7 @@ /** * This function returns the result of linearly interpolating the start and end values, with * <code>fraction</code> representing the proportion between the start and end values. The - * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>, + * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>, * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>, * and <code>t</code> is <code>fraction</code>. *
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 86da673..9435dfb 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java
@@ -206,7 +206,7 @@ /** * The set of listeners to be sent events through the life of an animation. */ - private ArrayList<AnimatorUpdateListener> mUpdateListeners = null; + ArrayList<AnimatorUpdateListener> mUpdateListeners = null; /** * The property/value sets being animated. @@ -280,6 +280,24 @@ } /** + * Constructs and returns a ValueAnimator that animates between color values. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + * @param values A set of values that the animation will animate between over time. + * @return A ValueAnimator object that is set up to animate between the given values. + */ + public static ValueAnimator ofArgb(int... values) { + ValueAnimator anim = new ValueAnimator(); + anim.setIntValues(values); + anim.setEvaluator(ArgbEvaluator.getInstance()); + return anim; + } + + /** * Constructs and returns a ValueAnimator that animates between float values. A single * value implies that that value is the one being animated to. However, this is not typically * useful in a ValueAnimator object because there is no way for the object to determine the @@ -1020,6 +1038,7 @@ * play backwards. This behavior is only set for the current animation; future playing * of the animation will use the default behavior of playing forward. */ + @Override public void reverse() { mPlayingBackwards = !mPlayingBackwards; if (mPlayingState == RUNNING) { @@ -1035,10 +1054,19 @@ } /** + * @hide + */ + @Override + public boolean canReverse() { + return true; + } + + /** * Called internally to end an animation by removing it from the animations list. Must be * called on the UI thread. + * @hide */ - private void endAnimation(AnimationHandler handler) { + protected void endAnimation(AnimationHandler handler) { handler.mAnimations.remove(this); handler.mPendingAnimations.remove(this); handler.mDelayedAnims.remove(this); @@ -1106,28 +1134,27 @@ if (!mStartedDelay) { mStartedDelay = true; mDelayStartTime = currentTime; - } else { - if (mPaused) { - if (mPauseTime < 0) { - mPauseTime = currentTime; - } - return false; - } else if (mResumed) { - mResumed = false; - if (mPauseTime > 0) { - // Offset by the duration that the animation was paused - mDelayStartTime += (currentTime - mPauseTime); - } + } + if (mPaused) { + if (mPauseTime < 0) { + mPauseTime = currentTime; } - long deltaTime = currentTime - mDelayStartTime; - if (deltaTime > mStartDelay) { - // startDelay ended - start the anim and record the - // mStartTime appropriately - mStartTime = currentTime - (deltaTime - mStartDelay); - mPlayingState = RUNNING; - return true; + return false; + } else if (mResumed) { + mResumed = false; + if (mPauseTime > 0) { + // Offset by the duration that the animation was paused + mDelayStartTime += (currentTime - mPauseTime); } } + long deltaTime = currentTime - mDelayStartTime; + if (deltaTime > mStartDelay) { + // startDelay ended - start the anim and record the + // mStartTime appropriately + mStartTime = currentTime - (deltaTime - mStartDelay); + mPlayingState = RUNNING; + return true; + } return false; } @@ -1347,4 +1374,43 @@ } return returnVal; } + + /** + * <p>Whether or not the ValueAnimator is allowed to run asynchronously off of + * the UI thread. This is a hint that informs the ValueAnimator that it is + * OK to run the animation off-thread, however ValueAnimator may decide + * that it must run the animation on the UI thread anyway. For example if there + * is an {@link AnimatorUpdateListener} the animation will run on the UI thread, + * regardless of the value of this hint.</p> + * + * <p>Regardless of whether or not the animation runs asynchronously, all + * listener callbacks will be called on the UI thread.</p> + * + * <p>To be able to use this hint the following must be true:</p> + * <ol> + * <li>{@link #getAnimatedFraction()} is not needed (it will return undefined values).</li> + * <li>The animator is immutable while {@link #isStarted()} is true. Requests + * to change values, duration, delay, etc... may be ignored.</li> + * <li>Lifecycle callback events may be asynchronous. Events such as + * {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or + * {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed + * as they must be posted back to the UI thread, and any actions performed + * by those callbacks (such as starting new animations) will not happen + * in the same frame.</li> + * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...) + * may be asynchronous. It is guaranteed that all state changes that are + * performed on the UI thread in the same frame will be applied as a single + * atomic update, however that frame may be the current frame, + * the next frame, or some future frame. This will also impact the observed + * state of the Animator. For example, {@link #isStarted()} may still return true + * after a call to {@link #end()}. Using the lifecycle callbacks is preferred over + * queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()} + * for this reason.</li> + * </ol> + * @hide + */ + @Override + public void setAllowRunningAsynchronously(boolean mayRunAsync) { + // It is up to subclasses to support this, if they can. + } }
diff --git a/core/java/android/annotation/AnimRes.java b/core/java/android/annotation/AnimRes.java new file mode 100644 index 0000000..56f8acf --- /dev/null +++ b/core/java/android/annotation/AnimRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an anim resource reference (e.g. {@link android.R.anim#fade_in}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface AnimRes { +}
diff --git a/core/java/android/annotation/AnimatorRes.java b/core/java/android/annotation/AnimatorRes.java new file mode 100644 index 0000000..cd4c189 --- /dev/null +++ b/core/java/android/annotation/AnimatorRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an animator resource reference (e.g. {@link android.R.animator#fade_in}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface AnimatorRes { +}
diff --git a/core/java/android/annotation/AnyRes.java b/core/java/android/annotation/AnyRes.java new file mode 100644 index 0000000..44411a0 --- /dev/null +++ b/core/java/android/annotation/AnyRes.java
@@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a resource reference of any type. If the specific type is known, use + * one of the more specific annotations instead, such as {@link StringRes} or + * {@link DrawableRes}. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface AnyRes { +}
diff --git a/core/java/android/annotation/ArrayRes.java b/core/java/android/annotation/ArrayRes.java new file mode 100644 index 0000000..1407af1 --- /dev/null +++ b/core/java/android/annotation/ArrayRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an array resource reference (e.g. {@link android.R.array#phoneTypes}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface ArrayRes { +}
diff --git a/core/java/android/annotation/AttrRes.java b/core/java/android/annotation/AttrRes.java new file mode 100644 index 0000000..285b80c --- /dev/null +++ b/core/java/android/annotation/AttrRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an attribute reference (e.g. {@link android.R.attr#action}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface AttrRes { +}
diff --git a/core/java/android/annotation/BoolRes.java b/core/java/android/annotation/BoolRes.java new file mode 100644 index 0000000..f50785b --- /dev/null +++ b/core/java/android/annotation/BoolRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a boolean resource reference. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface BoolRes { +}
diff --git a/core/java/android/annotation/ColorRes.java b/core/java/android/annotation/ColorRes.java new file mode 100644 index 0000000..061faa0 --- /dev/null +++ b/core/java/android/annotation/ColorRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a color resource reference (e.g. {@link android.R.color#black}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface ColorRes { +}
diff --git a/core/java/android/annotation/DimenRes.java b/core/java/android/annotation/DimenRes.java new file mode 100644 index 0000000..02ae00c --- /dev/null +++ b/core/java/android/annotation/DimenRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a dimension resource reference (e.g. {@link android.R.dimen#app_icon_size}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface DimenRes { +}
diff --git a/core/java/android/annotation/DrawableRes.java b/core/java/android/annotation/DrawableRes.java new file mode 100644 index 0000000..ebefa1d --- /dev/null +++ b/core/java/android/annotation/DrawableRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a drawable resource reference (e.g. {@link android.R.attr#alertDialogIcon}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface DrawableRes { +}
diff --git a/core/java/android/annotation/FractionRes.java b/core/java/android/annotation/FractionRes.java new file mode 100644 index 0000000..fd84d3e --- /dev/null +++ b/core/java/android/annotation/FractionRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a fraction resource reference. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface FractionRes { +}
diff --git a/core/java/android/annotation/IdRes.java b/core/java/android/annotation/IdRes.java new file mode 100644 index 0000000..b286965 --- /dev/null +++ b/core/java/android/annotation/IdRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an id resource reference (e.g. {@link android.R.id#copy}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface IdRes { +}
diff --git a/core/java/android/annotation/IntDef.java b/core/java/android/annotation/IntDef.java new file mode 100644 index 0000000..3cae9c5 --- /dev/null +++ b/core/java/android/annotation/IntDef.java
@@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +/** + * Denotes that the annotated element of integer type, represents + * a logical type and that its value should be one of the explicitly + * named constants. If the {@link #flag()} attribute is set to true, + * multiple constants can be combined. + * <p> + * Example: + * <pre>{@code + * @Retention(CLASS) + * @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) + * public @interface NavigationMode {} + * public static final int NAVIGATION_MODE_STANDARD = 0; + * public static final int NAVIGATION_MODE_LIST = 1; + * public static final int NAVIGATION_MODE_TABS = 2; + * ... + * public abstract void setNavigationMode(@NavigationMode int mode); + * @NavigationMode + * public abstract int getNavigationMode(); + * }</pre> + * For a flag, set the flag attribute: + * <pre>{@code + * @IntDef( + * flag = true + * value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) + * }</pre> + * + * @hide + */ +@Retention(CLASS) +@Target({ANNOTATION_TYPE}) +public @interface IntDef { + /** Defines the allowed constants for this element */ + long[] value() default {}; + + /** Defines whether the constants can be used as a flag, or just as an enum (the default) */ + boolean flag() default false; +}
diff --git a/core/java/android/annotation/IntegerRes.java b/core/java/android/annotation/IntegerRes.java new file mode 100644 index 0000000..5313f4a --- /dev/null +++ b/core/java/android/annotation/IntegerRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an integer resource reference (e.g. {@link android.R.integer#config_shortAnimTime}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface IntegerRes { +}
diff --git a/core/java/android/annotation/InterpolatorRes.java b/core/java/android/annotation/InterpolatorRes.java new file mode 100644 index 0000000..8877a5f --- /dev/null +++ b/core/java/android/annotation/InterpolatorRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an interpolator resource reference (e.g. {@link android.R.interpolator#cycle}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface InterpolatorRes { +}
diff --git a/core/java/android/annotation/LayoutRes.java b/core/java/android/annotation/LayoutRes.java new file mode 100644 index 0000000..15ba86f --- /dev/null +++ b/core/java/android/annotation/LayoutRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a layout resource reference (e.g. {@link android.R.layout#list_content}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface LayoutRes { +}
diff --git a/core/java/android/annotation/MenuRes.java b/core/java/android/annotation/MenuRes.java new file mode 100644 index 0000000..b6dcc46 --- /dev/null +++ b/core/java/android/annotation/MenuRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a menu resource reference. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface MenuRes { +}
diff --git a/core/java/android/annotation/NonNull.java b/core/java/android/annotation/NonNull.java new file mode 100644 index 0000000..3ca9eea --- /dev/null +++ b/core/java/android/annotation/NonNull.java
@@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that a parameter, field or method return value can never be null. + * <p> + * This is a marker annotation and it has no specific attributes. + * + * @hide + */ +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface NonNull { +}
diff --git a/core/java/android/annotation/Nullable.java b/core/java/android/annotation/Nullable.java new file mode 100644 index 0000000..43f42fa --- /dev/null +++ b/core/java/android/annotation/Nullable.java
@@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that a parameter, field or method return value can be null. + * <p> + * When decorating a method call parameter, this denotes that the parameter can + * legitimately be null and the method will gracefully deal with it. Typically + * used on optional parameters. + * <p> + * When decorating a method, this denotes the method might legitimately return + * null. + * <p> + * This is a marker annotation and it has no specific attributes. + * + * @hide + */ +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface Nullable { +}
diff --git a/core/java/android/annotation/PluralsRes.java b/core/java/android/annotation/PluralsRes.java new file mode 100644 index 0000000..31ac729 --- /dev/null +++ b/core/java/android/annotation/PluralsRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a plurals resource reference. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface PluralsRes { +}
diff --git a/core/java/android/annotation/PrivateApi.java b/core/java/android/annotation/PrivateApi.java deleted file mode 100644 index 985eafe..0000000 --- a/core/java/android/annotation/PrivateApi.java +++ /dev/null
@@ -1,31 +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. - */ - -package android.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Indicates an API is exposed for use by bundled applications. - * <p> - * These APIs are not guaranteed to remain consistent release-to-release, - * and are not for use by apps linking against the SDK. - * @hide - */ -@Retention(RetentionPolicy.SOURCE) -public @interface PrivateApi { -}
diff --git a/core/java/android/annotation/RawRes.java b/core/java/android/annotation/RawRes.java new file mode 100644 index 0000000..39970b3 --- /dev/null +++ b/core/java/android/annotation/RawRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a raw resource reference. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface RawRes { +}
diff --git a/core/java/android/annotation/StringDef.java b/core/java/android/annotation/StringDef.java new file mode 100644 index 0000000..5f7f380 --- /dev/null +++ b/core/java/android/annotation/StringDef.java
@@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +/** + * Denotes that the annotated String element, represents a logical + * type and that its value should be one of the explicitly named constants. + * <p> + * Example: + * <pre>{@code + * @Retention(SOURCE) + * @StringDef({ + * POWER_SERVICE, + * WINDOW_SERVICE, + * LAYOUT_INFLATER_SERVICE + * }) + * public @interface ServiceName {} + * public static final String POWER_SERVICE = "power"; + * public static final String WINDOW_SERVICE = "window"; + * public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; + * ... + * public abstract Object getSystemService(@ServiceName String name); + * }</pre> + * + * @hide + */ +@Retention(CLASS) +@Target({ANNOTATION_TYPE}) +public @interface StringDef { + /** Defines the allowed constants for this element */ + String[] value() default {}; +}
diff --git a/core/java/android/annotation/StringRes.java b/core/java/android/annotation/StringRes.java new file mode 100644 index 0000000..190b68a --- /dev/null +++ b/core/java/android/annotation/StringRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be a String resource reference (e.g. {@link android.R.string#ok}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface StringRes { +}
diff --git a/core/java/android/annotation/StyleRes.java b/core/java/android/annotation/StyleRes.java new file mode 100644 index 0000000..4453b8d --- /dev/null +++ b/core/java/android/annotation/StyleRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that a integer parameter, field or method return value is expected + * to be a style resource reference (e.g. {@link android.R.style#TextAppearance}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface StyleRes { +}
diff --git a/core/java/android/annotation/StyleableRes.java b/core/java/android/annotation/StyleableRes.java new file mode 100644 index 0000000..3c1895e --- /dev/null +++ b/core/java/android/annotation/StyleableRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that a integer parameter, field or method return value is expected + * to be a styleable resource reference (e.g. {@link android.R.styleable#TextView_text}). + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface StyleableRes { +}
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java new file mode 100644 index 0000000..55028eb --- /dev/null +++ b/core/java/android/annotation/SystemApi.java
@@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014 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.annotation; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates an API is exposed for use by bundled system applications. + * <p> + * These APIs are not guaranteed to remain consistent release-to-release, + * and are not for use by apps linking against the Android SDK. + * </p><p> + * This annotation should only appear on API that is already marked <pre>@hide</pre>. + * </p> + * + * @hide + */ +@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE}) +@Retention(RetentionPolicy.SOURCE) +public @interface SystemApi { +}
diff --git a/core/java/android/annotation/XmlRes.java b/core/java/android/annotation/XmlRes.java new file mode 100644 index 0000000..5fb8a4a --- /dev/null +++ b/core/java/android/annotation/XmlRes.java
@@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that an integer parameter, field or method return value is expected + * to be an XML resource reference. + * + * {@hide} + */ +@Documented +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface XmlRes { +}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index c4ddf1f..014a7af 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java
@@ -16,39 +16,74 @@ package android.app; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.ActionMode; import android.view.Gravity; +import android.view.KeyEvent; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.view.Window; import android.widget.SpinnerAdapter; +import android.widget.Toolbar; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Map; /** - * A window feature at the top of the activity that may display the activity title, navigation - * modes, and other interactive items. + * A primary toolbar within the activity that may display the activity title, application-level + * navigation affordances, and other interactive items. + * * <p>Beginning with Android 3.0 (API level 11), the action bar appears at the top of an * activity's window when the activity uses the system's {@link * android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default. * You may otherwise add the action bar by calling {@link * android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a * custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property. - * <p>By default, the action bar shows the application icon on + * </p> + * + * <p>Beginning with Android L (API level 21), the action bar may be represented by any + * Toolbar widget within the application layout. The application may signal to the Activity + * which Toolbar should be treated as the Activity's action bar. Activities that use this + * feature should use one of the supplied <code>.NoActionBar</code> themes, set the + * {@link android.R.styleable#Theme_windowActionBar windowActionBar} attribute to <code>false</code> + * or otherwise not request the window feature.</p> + * + * <p>By adjusting the window features requested by the theme and the layouts used for + * an Activity's content view, an app can use the standard system action bar on older platform + * releases and the newer inline toolbars on newer platform releases. The <code>ActionBar</code> + * object obtained from the Activity can be used to control either configuration transparently.</p> + * + * <p>When using the Holo themes the action bar shows the application icon on * the left, followed by the activity title. If your activity has an options menu, you can make * select items accessible directly from the action bar as "action items". You can also * modify various characteristics of the action bar or remove it completely.</p> + * + * <p>When using the Material themes (default in API 21 or newer) the navigation button + * (formerly "Home") takes over the space previously occupied by the application icon. + * Apps wishing to express a stronger branding should use their brand colors heavily + * in the action bar and other application chrome or use a {@link #setLogo(int) logo} + * in place of their standard title text.</p> + * * <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link * android.app.Activity#getActionBar getActionBar()}.</p> + * * <p>In some cases, the action bar may be overlayed by another bar that enables contextual actions, * using an {@link android.view.ActionMode}. For example, when the user selects one or more items in * your activity, you can enable an action mode that offers actions specific to the selected * items, with a UI that temporarily replaces the action bar. Although the UI may occupy the * same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for - * {@link ActionBar}. + * {@link ActionBar}.</p> + * * <div class="special reference"> * <h3>Developer Guides</h3> * <p>For information about how to use the action bar, including how to add action items, navigation @@ -57,11 +92,21 @@ * </div> */ public abstract class ActionBar { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) + public @interface NavigationMode {} + /** * Standard navigation mode. Consists of either a logo or icon * and title text with an optional subtitle. Clicking any of these elements * will dispatch onOptionsItemSelected to the host Activity with * a MenuItem with item ID android.R.id.home. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public static final int NAVIGATION_MODE_STANDARD = 0; @@ -69,15 +114,38 @@ * List navigation mode. Instead of static title text this mode * presents a list menu for navigation within the activity. * e.g. this might be presented to the user as a dropdown list. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public static final int NAVIGATION_MODE_LIST = 1; /** * Tab navigation mode. Instead of static title text this mode * presents a series of tabs for navigation within the activity. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public static final int NAVIGATION_MODE_TABS = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, + value = { + DISPLAY_USE_LOGO, + DISPLAY_SHOW_HOME, + DISPLAY_HOME_AS_UP, + DISPLAY_SHOW_TITLE, + DISPLAY_SHOW_CUSTOM, + DISPLAY_TITLE_MULTIPLE_LINES + }) + public @interface DisplayOptions {} + /** * Use logo instead of icon if available. This flag will cause appropriate * navigation modes to use a wider logo in place of the standard icon. @@ -264,6 +332,11 @@ * within the dropdown navigation menu. * @param callback An OnNavigationListener that will receive events when the user * selects a navigation item. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback); @@ -272,6 +345,11 @@ * Set the selected navigation item in list or tabbed navigation modes. * * @param position Position of the item to select. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void setSelectedNavigationItem(int position); @@ -279,6 +357,11 @@ * Get the position of the selected navigation item in list or tabbed navigation modes. * * @return Position of the selected item. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract int getSelectedNavigationIndex(); @@ -286,6 +369,11 @@ * Get the number of navigation items present in the current navigation mode. * * @return Number of navigation items. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract int getNavigationItemCount(); @@ -341,7 +429,7 @@ * @param options A combination of the bits defined by the DISPLAY_ constants * defined in ActionBar. */ - public abstract void setDisplayOptions(int options); + public abstract void setDisplayOptions(@DisplayOptions int options); /** * Set selected display options. Only the options specified by mask will be changed. @@ -356,7 +444,7 @@ * defined in ActionBar. * @param mask A bit mask declaring which display options should be changed. */ - public abstract void setDisplayOptions(int options, int mask); + public abstract void setDisplayOptions(@DisplayOptions int options, @DisplayOptions int mask); /** * Set whether to display the activity logo rather than the activity icon. @@ -431,7 +519,7 @@ * @see #setStackedBackgroundDrawable(Drawable) * @see #setSplitBackgroundDrawable(Drawable) */ - public abstract void setBackgroundDrawable(Drawable d); + public abstract void setBackgroundDrawable(@Nullable Drawable d); /** * Set the ActionBar's stacked background. This will appear @@ -483,7 +571,13 @@ * </ul> * * @return The current navigation mode. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ + @NavigationMode public abstract int getNavigationMode(); /** @@ -493,8 +587,13 @@ * @see #NAVIGATION_MODE_STANDARD * @see #NAVIGATION_MODE_LIST * @see #NAVIGATION_MODE_TABS + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ - public abstract void setNavigationMode(int mode); + public abstract void setNavigationMode(@NavigationMode int mode); /** * @return The current set of display options. @@ -514,6 +613,11 @@ * @return A new Tab * * @see #addTab(Tab) + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract Tab newTab(); @@ -522,6 +626,11 @@ * If this is the first tab to be added it will become the selected tab. * * @param tab Tab to add + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void addTab(Tab tab); @@ -530,6 +639,11 @@ * * @param tab Tab to add * @param setSelected True if the added tab should become the selected tab. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void addTab(Tab tab, boolean setSelected); @@ -540,6 +654,11 @@ * * @param tab The tab to add * @param position The new position of the tab + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void addTab(Tab tab, int position); @@ -550,6 +669,11 @@ * @param tab The tab to add * @param position The new position of the tab * @param setSelected True if the added tab should become the selected tab. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void addTab(Tab tab, int position, boolean setSelected); @@ -558,6 +682,11 @@ * and another tab will be selected if present. * * @param tab The tab to remove + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void removeTab(Tab tab); @@ -566,11 +695,21 @@ * and another tab will be selected if present. * * @param position Position of the tab to remove + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void removeTabAt(int position); /** * Remove all tabs from the action bar and deselect the current tab. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void removeAllTabs(); @@ -580,6 +719,11 @@ * <p>Note: If you want to select by index, use {@link #setSelectedNavigationItem(int)}.</p> * * @param tab Tab to select + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract void selectTab(Tab tab); @@ -588,6 +732,11 @@ * one tab present. * * @return The currently selected tab or null + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract Tab getSelectedTab(); @@ -596,12 +745,22 @@ * * @param index Index value in the range 0-get * @return + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract Tab getTabAt(int index); /** * Returns the number of tabs currently registered with the action bar. * @return Tab count + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public abstract int getTabCount(); @@ -775,7 +934,144 @@ public void setHomeActionContentDescription(int resId) { } /** + * Enable hiding the action bar on content scroll. + * + * <p>If enabled, the action bar will scroll out of sight along with a + * {@link View#setNestedScrollingEnabled(boolean) nested scrolling child} view's content. + * The action bar must be in {@link Window#FEATURE_ACTION_BAR_OVERLAY overlay mode} + * to enable hiding on content scroll.</p> + * + * <p>When partially scrolled off screen the action bar is considered + * {@link #hide() hidden}. A call to {@link #show() show} will cause it to return to full view. + * </p> + * @param hideOnContentScroll true to enable hiding on content scroll. + */ + public void setHideOnContentScrollEnabled(boolean hideOnContentScroll) { + if (hideOnContentScroll) { + throw new UnsupportedOperationException("Hide on content scroll is not supported in " + + "this action bar configuration."); + } + } + + /** + * Return whether the action bar is configured to scroll out of sight along with + * a {@link View#setNestedScrollingEnabled(boolean) nested scrolling child}. + * + * @return true if hide-on-content-scroll is enabled + * @see #setHideOnContentScrollEnabled(boolean) + */ + public boolean isHideOnContentScrollEnabled() { + return false; + } + + /** + * Return the current vertical offset of the action bar. + * + * <p>The action bar's current hide offset is the distance that the action bar is currently + * scrolled offscreen in pixels. The valid range is 0 (fully visible) to the action bar's + * current measured {@link #getHeight() height} (fully invisible).</p> + * + * @return The action bar's offset toward its fully hidden state in pixels + */ + public int getHideOffset() { + return 0; + } + + /** + * Set the current hide offset of the action bar. + * + * <p>The action bar's current hide offset is the distance that the action bar is currently + * scrolled offscreen in pixels. The valid range is 0 (fully visible) to the action bar's + * current measured {@link #getHeight() height} (fully invisible).</p> + * + * @param offset The action bar's offset toward its fully hidden state in pixels. + */ + public void setHideOffset(int offset) { + if (offset != 0) { + throw new UnsupportedOperationException("Setting an explicit action bar hide offset " + + "is not supported in this action bar configuration."); + } + } + + /** + * Set the Z-axis elevation of the action bar in pixels. + * + * <p>The action bar's elevation is the distance it is placed from its parent surface. Higher + * values are closer to the user.</p> + * + * @param elevation Elevation value in pixels + */ + public void setElevation(float elevation) { + if (elevation != 0) { + throw new UnsupportedOperationException("Setting a non-zero elevation is " + + "not supported in this action bar configuration."); + } + } + + /** + * Get the Z-axis elevation of the action bar in pixels. + * + * <p>The action bar's elevation is the distance it is placed from its parent surface. Higher + * values are closer to the user.</p> + * + * @return Elevation value in pixels + */ + public float getElevation() { + return 0; + } + + /** @hide */ + public void setDefaultDisplayHomeAsUpEnabled(boolean enabled) { + } + + /** @hide */ + public void setShowHideAnimationEnabled(boolean enabled) { + } + + /** @hide */ + public void onConfigurationChanged(Configuration config) { + } + + /** @hide */ + public void dispatchMenuVisibilityChanged(boolean visible) { + } + + /** @hide */ + public ActionMode startActionMode(ActionMode.Callback callback) { + return null; + } + + /** @hide */ + public boolean openOptionsMenu() { + return false; + } + + /** @hide */ + public boolean invalidateOptionsMenu() { + return false; + } + + /** @hide */ + public boolean onMenuKeyEvent(KeyEvent event) { + return false; + } + + /** @hide */ + public boolean collapseActionView() { + return false; + } + + /** @hide */ + public void setWindowTitle(CharSequence title) { + } + + /** * Listener interface for ActionBar navigation events. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public interface OnNavigationListener { /** @@ -808,6 +1104,11 @@ * A tab in the action bar. * * <p>Tabs manage the hiding and showing of {@link Fragment}s. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public static abstract class Tab { /** @@ -959,6 +1260,11 @@ /** * Callback interface invoked when a tab is focused, unfocused, added, or removed. + * + * @deprecated Action bar navigation modes are deprecated and not supported by inline + * toolbar action bars. Consider using other + * <a href="http://developer.android.com/design/patterns/navigation.html">common + * navigation patterns</a> instead. */ public interface TabListener { /** @@ -1000,31 +1306,31 @@ * * @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity */ - public static class LayoutParams extends MarginLayoutParams { + public static class LayoutParams extends ViewGroup.MarginLayoutParams { /** * Gravity for the view associated with these LayoutParams. * * @see android.view.Gravity */ @ViewDebug.ExportedProperty(category = "layout", mapping = { - @ViewDebug.IntToString(from = -1, to = "NONE"), - @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"), - @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"), - @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"), - @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"), - @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"), - @ViewDebug.IntToString(from = Gravity.START, to = "START"), - @ViewDebug.IntToString(from = Gravity.END, to = "END"), - @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"), - @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"), - @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"), - @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"), - @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"), - @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL") + @ViewDebug.IntToString(from = -1, to = "NONE"), + @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"), + @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"), + @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"), + @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"), + @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"), + @ViewDebug.IntToString(from = Gravity.START, to = "START"), + @ViewDebug.IntToString(from = Gravity.END, to = "END"), + @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"), + @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"), + @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"), + @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"), + @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"), + @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL") }) public int gravity = Gravity.NO_GRAVITY; - public LayoutParams(Context c, AttributeSet attrs) { + public LayoutParams(@NonNull Context c, AttributeSet attrs) { super(c, attrs); TypedArray a = c.obtainStyledAttributes(attrs, @@ -1042,6 +1348,7 @@ public LayoutParams(int width, int height, int gravity) { super(width, height); + this.gravity = gravity; } @@ -1051,12 +1358,21 @@ public LayoutParams(LayoutParams source) { super(source); - this.gravity = source.gravity; } public LayoutParams(ViewGroup.LayoutParams source) { super(source); } + + /* + * Note for framework developers: + * + * You might notice that ActionBar.LayoutParams is missing a constructor overload + * for MarginLayoutParams. While it may seem like a good idea to add one, at this + * point it's dangerous for source compatibility. Upon building against a new + * version of the SDK an app can end up statically linking to the new MarginLayoutParams + * overload, causing a crash when running on older platform versions with no other changes. + */ } }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e8b3bb9c..9f683e3 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java
@@ -16,11 +16,23 @@ package android.app; +import android.annotation.NonNull; +import android.os.PersistableBundle; +import android.transition.Scene; +import android.transition.TransitionManager; import android.util.ArrayMap; import android.util.SuperNotCalledException; -import com.android.internal.app.ActionBarImpl; +import android.widget.Toolbar; + +import com.android.internal.app.IVoiceInteractor; +import com.android.internal.app.WindowDecorActionBar; +import com.android.internal.app.ToolbarActionBar; import com.android.internal.policy.PolicyManager; +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.admin.DevicePolicyManager; import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.ContentResolver; @@ -41,6 +53,7 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.media.AudioManager; +import android.media.session.MediaController; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -84,6 +97,8 @@ import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashMap; @@ -97,14 +112,14 @@ * or embedded inside of another activity (using {@link ActivityGroup}). * * There are two methods almost all subclasses of Activity will implement: - * + * * <ul> * <li> {@link #onCreate} is where you initialize your activity. Most * importantly, here you will usually call {@link #setContentView(int)} * with a layout resource defining your UI, and using {@link #findViewById} * to retrieve the widgets in that UI that you need to interact with * programmatically. - * + * * <li> {@link #onPause} is where you deal with the user leaving your * activity. Most importantly, any changes made by the user should at this * point be committed (usually to the @@ -115,7 +130,7 @@ * activity classes must have a corresponding * {@link android.R.styleable#AndroidManifestActivity <activity>} * declaration in their package's <code>AndroidManifest.xml</code>.</p> - * + * * <p>Topics covered here: * <ol> * <li><a href="#Fragments">Fragments</a> @@ -158,14 +173,14 @@ * and becomes the running activity -- the previous activity always remains * below it in the stack, and will not come to the foreground again until * the new activity exits.</p> - * + * * <p>An activity has essentially four states:</p> * <ul> * <li> If an activity in the foreground of the screen (at the top of * the stack), * it is <em>active</em> or <em>running</em>. </li> * <li>If an activity has lost focus but is still visible (that is, a new non-full-sized - * or transparent activity has focus on top of your activity), it + * or transparent activity has focus on top of your activity), it * is <em>paused</em>. A paused activity is completely alive (it * maintains all state and member information and remains attached to * the window manager), but can be killed by the system in extreme @@ -185,13 +200,13 @@ * The square rectangles represent callback methods you can implement to * perform operations when the Activity moves between states. The colored * ovals are major states the Activity can be in.</p> - * + * * <p><img src="../../../images/activity_lifecycle.png" * alt="State diagram for an Android Activity Lifecycle." border="0" /></p> - * + * * <p>There are three key loops you may be interested in monitoring within your * activity: - * + * * <ul> * <li>The <b>entire lifetime</b> of an activity happens between the first call * to {@link android.app.Activity#onCreate} through to a single final call @@ -200,7 +215,7 @@ * onDestroy(). For example, if it has a thread running in the background * to download data from the network, it may create that thread in onCreate() * and then stop the thread in onDestroy(). - * + * * <li>The <b>visible lifetime</b> of an activity happens between a call to * {@link android.app.Activity#onStart} until a corresponding call to * {@link android.app.Activity#onStop}. During this time the user can see the @@ -212,7 +227,7 @@ * longer sees what you are displaying. The onStart() and onStop() methods * can be called multiple times, as the activity becomes visible and hidden * to the user. - * + * * <li>The <b>foreground lifetime</b> of an activity happens between a call to * {@link android.app.Activity#onResume} until a corresponding call to * {@link android.app.Activity#onPause}. During this time the activity is @@ -222,7 +237,7 @@ * intent is delivered -- so the code in these methods should be fairly * lightweight. * </ul> - * + * * <p>The entire lifecycle of an activity is defined by the following * Activity methods. All of these are hooks that you can override * to do appropriate work when the activity changes state. All @@ -238,7 +253,7 @@ * protected void onCreate(Bundle savedInstanceState); * * protected void onStart(); - * + * * protected void onRestart(); * * protected void onResume(); @@ -354,7 +369,7 @@ * {@link #onSaveInstanceState(Bundle)} is called before placing the activity * in such a background state, allowing you to save away any dynamic instance * state in your activity into the given Bundle, to be later received in - * {@link #onCreate} if the activity needs to be re-created. + * {@link #onCreate} if the activity needs to be re-created. * See the <a href="#ProcessLifecycle">Process Lifecycle</a> * section for more information on how the lifecycle of a process is tied * to the activities it is hosting. Note that it is important to save @@ -378,14 +393,14 @@ * * <a name="ConfigurationChanges"></a> * <h3>Configuration Changes</h3> - * + * * <p>If the configuration of the device (as defined by the * {@link Configuration Resources.Configuration} class) changes, * then anything displaying a user interface will need to update to match that * configuration. Because Activity is the primary mechanism for interacting * with the user, it includes special support for handling configuration * changes.</p> - * + * * <p>Unless you specify otherwise, a configuration change (such as a change * in screen orientation, language, input devices, etc) will cause your * current activity to be <em>destroyed</em>, going through the normal activity @@ -395,7 +410,7 @@ * called in that instance then a new instance of the activity will be * created, with whatever savedInstanceState the previous instance had generated * from {@link #onSaveInstanceState}.</p> - * + * * <p>This is done because any application resource, * including layout files, can change based on any configuration value. Thus * the only safe way to handle a configuration change is to re-retrieve all @@ -403,7 +418,7 @@ * must already know how to save their state and re-create themselves from * that state, this is a convenient way to have an activity restart itself * with a new configuration.</p> - * + * * <p>In some special cases, you may want to bypass restarting of your * activity based on one or more types of configuration changes. This is * done with the {@link android.R.attr#configChanges android:configChanges} @@ -413,7 +428,7 @@ * a configuration change involves any that you do not handle, however, the * activity will still be restarted and {@link #onConfigurationChanged} * will not be called.</p> - * + * * <a name="StartingActivities"></a> * <h3>Starting Activities and Getting Results</h3> * @@ -428,10 +443,10 @@ * ends. For example, you may start an activity that lets the user pick * a person in a list of contacts; when it ends, it returns the person * that was selected. To do this, you call the - * {@link android.app.Activity#startActivityForResult(Intent, int)} - * version with a second integer parameter identifying the call. The result + * {@link android.app.Activity#startActivityForResult(Intent, int)} + * version with a second integer parameter identifying the call. The result * will come back through your {@link android.app.Activity#onActivityResult} - * method.</p> + * method.</p> * * <p>When an activity exits, it can call * {@link android.app.Activity#setResult(int)} @@ -452,7 +467,7 @@ * * static final int PICK_CONTACT_REQUEST = 0; * - * protected boolean onKeyDown(int keyCode, KeyEvent event) { + * public boolean onKeyDown(int keyCode, KeyEvent event) { * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { * // When the user center presses, let them pick a contact. * startActivityForResult( @@ -558,17 +573,17 @@ * * protected void onPause() { * super.onPause(); - * + * * SharedPreferences.Editor ed = mPrefs.edit(); * ed.putInt("view_mode", mCurViewMode); * ed.commit(); * } * } * </pre> - * + * * <a name="Permissions"></a> * <h3>Permissions</h3> - * + * * <p>The ability to start a particular Activity can be enforced when it is * declared in its * manifest's {@link android.R.styleable#AndroidManifestActivity <activity>} @@ -589,10 +604,10 @@ * * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> * document for more information on permissions and security in general. - * + * * <a name="ProcessLifecycle"></a> * <h3>Process Lifecycle</h3> - * + * * <p>The Android system attempts to keep application process around for as * long as possible, but eventually will need to remove old processes when * memory runs low. As described in <a href="#ActivityLifecycle">Activity @@ -602,7 +617,7 @@ * listed here in order of importance. The system will kill less important * processes (the last ones) before it resorts to killing more important * processes (the first ones). - * + * * <ol> * <li> <p>The <b>foreground activity</b> (the activity at the top of the screen * that the user is currently interacting with) is considered the most important. @@ -630,7 +645,7 @@ * context of an activity BroadcastReceiver or Service to ensure that the system * knows it needs to keep your process around. * </ol> - * + * * <p>Sometimes an Activity may need to do a long-running operation that exists * independently of the activity lifecycle itself. An example may be a camera * application that allows you to upload a picture to a web site. The upload @@ -705,9 +720,10 @@ HashMap<String, Object> children; ArrayList<Fragment> fragments; ArrayMap<String, LoaderManagerImpl> loaders; + VoiceInteractor voiceInteractor; } /* package */ NonConfigurationInstances mLastNonConfigurationInstances; - + private Window mWindow; private WindowManager mWindowManager; @@ -715,9 +731,11 @@ /*package*/ boolean mWindowAdded = false; /*package*/ boolean mVisibleFromServer = false; /*package*/ boolean mVisibleFromClient = true; - /*package*/ ActionBarImpl mActionBar = null; + /*package*/ ActionBar mActionBar = null; private boolean mEnableDefaultActionBarUp; + private VoiceInteractor mVoiceInteractor; + private CharSequence mTitle; private int mTitleColor = 0; @@ -727,11 +745,19 @@ public View findViewById(int id) { return Activity.this.findViewById(id); } + @Override + public boolean hasView() { + Window window = Activity.this.getWindow(); + return (window != null && window.peekDecorView() != null); + } }; - + + // Most recent call to requestVisibleBehind(). + boolean mVisibleBehind; + ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers; LoaderManagerImpl mLoaderManager; - + private static final class ManagedCursor { ManagedCursor(Cursor cursor) { mCursor = cursor; @@ -746,9 +772,10 @@ private final ArrayList<ManagedCursor> mManagedCursors = new ArrayList<ManagedCursor>(); - // protected by synchronized (this) + // protected by synchronized (this) int mResultCode = RESULT_CANCELED; Intent mResultData = null; + private TranslucentConversionListener mTranslucentCallback; private boolean mChangeCanvasToTranslucent; @@ -756,7 +783,7 @@ private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE; private SpannableStringBuilder mDefaultKeySsb = null; - + protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused}; @SuppressWarnings("unused") @@ -765,21 +792,25 @@ private Thread mUiThread; final Handler mHandler = new Handler(); + ActivityTransitionState mActivityTransitionState = new ActivityTransitionState(); + SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK; + SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK; + /** Return the intent that started this activity. */ public Intent getIntent() { return mIntent; } - /** - * Change the intent returned by {@link #getIntent}. This holds a - * reference to the given intent; it does not copy it. Often used in - * conjunction with {@link #onNewIntent}. - * - * @param newIntent The new Intent object to return from getIntent - * + /** + * Change the intent returned by {@link #getIntent}. This holds a + * reference to the given intent; it does not copy it. Often used in + * conjunction with {@link #onNewIntent}. + * + * @param newIntent The new Intent object to return from getIntent + * * @see #getIntent * @see #onNewIntent - */ + */ public void setIntent(Intent newIntent) { mIntent = newIntent; } @@ -793,7 +824,7 @@ public final boolean isChild() { return mParent != null; } - + /** Return the parent activity if this view is an embedded child. */ public final Activity getParent() { return mParent; @@ -808,7 +839,7 @@ * Retrieve the current {@link android.view.Window} for the activity. * This can be used to directly access parts of the Window API that * are not available through Activity/Screen. - * + * * @return Window The current window, or null if the activity is not * visual. */ @@ -827,7 +858,7 @@ mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true); return mLoaderManager; } - + LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) { if (mAllLoaderManagers == null) { mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>(); @@ -843,16 +874,17 @@ } return lm; } - + /** * Calls {@link android.view.Window#getCurrentFocus} on the * Window of this Activity to return the currently focused view. - * + * * @return View The current View with focus or null. - * + * * @see #getWindow * @see android.view.Window#getCurrentFocus */ + @Nullable public View getCurrentFocus() { return mWindow != null ? mWindow.getCurrentFocus() : null; } @@ -864,26 +896,26 @@ * with widgets in the UI, calling * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve * cursors for data being displayed, etc. - * + * * <p>You can call {@link #finish} from within this function, in * which case onDestroy() will be immediately called without any of the rest * of the activity lifecycle ({@link #onStart}, {@link #onResume}, * {@link #onPause}, etc) executing. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b> - * + * * @see #onStart * @see #onSaveInstanceState * @see #onRestoreInstanceState * @see #onPostCreate */ - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); if (mLastNonConfigurationInstances != null) { mAllLoaderManagers = mLastNonConfigurationInstances.loaders; @@ -902,10 +934,38 @@ } mFragments.dispatchCreate(); getApplication().dispatchActivityCreated(this, savedInstanceState); + if (mVoiceInteractor != null) { + mVoiceInteractor.attachActivity(this); + } mCalled = true; } /** + * Same as {@link #onCreate(android.os.Bundle)} but called for those activities created with + * the attribute {@link android.R.attr#persistableMode} set to + * <code>persistAcrossReboots</code>. + * + * @param savedInstanceState if the activity is being re-initialized after + * previously being shut down then this Bundle contains the data it most + * recently supplied in {@link #onSaveInstanceState}. + * <b><i>Note: Otherwise it is null.</i></b> + * @param persistentState if the activity is being re-initialized after + * previously being shut down or powered off then this Bundle contains the data it most + * recently supplied to outPersistentState in {@link #onSaveInstanceState}. + * <b><i>Note: Otherwise it is null.</i></b> + * + * @see #onCreate(android.os.Bundle) + * @see #onStart + * @see #onSaveInstanceState + * @see #onRestoreInstanceState + * @see #onPostCreate + */ + public void onCreate(@Nullable Bundle savedInstanceState, + @Nullable PersistableBundle persistentState) { + onCreate(savedInstanceState); + } + + /** * The hook for {@link ActivityThread} to restore the state of this activity. * * Calls {@link #onSaveInstanceState(android.os.Bundle)} and @@ -919,6 +979,23 @@ } /** + * The hook for {@link ActivityThread} to restore the state of this activity. + * + * Calls {@link #onSaveInstanceState(android.os.Bundle)} and + * {@link #restoreManagedDialogs(android.os.Bundle)}. + * + * @param savedInstanceState contains the saved state + * @param persistentState contains the persistable saved state + */ + final void performRestoreInstanceState(Bundle savedInstanceState, + PersistableBundle persistentState) { + onRestoreInstanceState(savedInstanceState, persistentState); + if (savedInstanceState != null) { + restoreManagedDialogs(savedInstanceState); + } + } + + /** * This method is called after {@link #onStart} when the activity is * being re-initialized from a previously saved state, given here in * <var>savedInstanceState</var>. Most implementations will simply use {@link #onCreate} @@ -927,12 +1004,12 @@ * decide whether to use your default implementation. The default * implementation of this method performs a restore of any view state that * had previously been frozen by {@link #onSaveInstanceState}. - * + * * <p>This method is called between {@link #onStart} and * {@link #onPostCreate}. - * + * * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}. - * + * * @see #onCreate * @see #onPostCreate * @see #onResume @@ -946,7 +1023,35 @@ } } } - + + /** + * This is the same as {@link #onRestoreInstanceState(Bundle)} but is called for activities + * created with the attribute {@link android.R.attr#persistableMode} set to + * <code>persistAcrossReboots</code>. The {@link android.os.PersistableBundle} passed + * came from the restored PersistableBundle first + * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}. + * + * <p>This method is called between {@link #onStart} and + * {@link #onPostCreate}. + * + * <p>If this method is called {@link #onRestoreInstanceState(Bundle)} will not be called. + * + * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}. + * @param persistentState the data most recently supplied in {@link #onSaveInstanceState}. + * + * @see #onRestoreInstanceState(Bundle) + * @see #onCreate + * @see #onPostCreate + * @see #onResume + * @see #onSaveInstanceState + */ + public void onRestoreInstanceState(Bundle savedInstanceState, + PersistableBundle persistentState) { + if (savedInstanceState != null) { + onRestoreInstanceState(savedInstanceState); + } + } + /** * Restore the state of any saved managed dialogs. * @@ -1001,17 +1106,17 @@ * and {@link #onRestoreInstanceState} have been called). Applications will * generally not implement this method; it is intended for system * classes to do final initialization after application code has run. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b> * @see #onCreate */ - protected void onPostCreate(Bundle savedInstanceState) { + protected void onPostCreate(@Nullable Bundle savedInstanceState) { if (!isChild()) { mTitleReady = true; onTitleChanged(getTitle(), getTitleColor()); @@ -1020,14 +1125,30 @@ } /** - * Called after {@link #onCreate} — or after {@link #onRestart} when - * the activity had been stopped, but is now again being displayed to the - * user. It will be followed by {@link #onResume}. + * This is the same as {@link #onPostCreate(Bundle)} but is called for activities + * created with the attribute {@link android.R.attr#persistableMode} set to + * <code>persistAcrossReboots</code>. + * + * @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState} + * @param persistentState The data caming from the PersistableBundle first + * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}. + * + * @see #onCreate + */ + public void onPostCreate(@Nullable Bundle savedInstanceState, + @Nullable PersistableBundle persistentState) { + onPostCreate(savedInstanceState); + } + + /** + * Called after {@link #onCreate} — or after {@link #onRestart} when + * the activity had been stopped, but is now again being displayed to the + * user. It will be followed by {@link #onResume}. * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onCreate * @see #onStop * @see #onResume @@ -1035,7 +1156,7 @@ protected void onStart() { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this); mCalled = true; - + if (!mLoadersStarted) { mLoadersStarted = true; if (mLoaderManager != null) { @@ -1060,11 +1181,11 @@ * this is usually the place * where the cursor should be requeried (because you had deactivated it in * {@link #onStop}. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onStop * @see #onStart * @see #onResume @@ -1087,7 +1208,7 @@ * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onRestoreInstanceState * @see #onRestart * @see #onPostResume @@ -1096,6 +1217,7 @@ protected void onResume() { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this); getApplication().dispatchActivityResumed(this); + mActivityTransitionState.onResume(); mCalled = true; } @@ -1104,11 +1226,11 @@ * been called). Applications will generally not implement this method; * it is intended for system classes to do final setup after application * resume code has run. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onResume */ protected void onPostResume() { @@ -1119,25 +1241,46 @@ } /** + * @hide + * Check whether this activity is running as part of a voice interaction with the user. + * If true, it should perform its interaction with the user through the + * {@link VoiceInteractor} returned by {@link #getVoiceInteractor}. + */ + @SystemApi + public boolean isVoiceInteraction() { + return mVoiceInteractor != null; + } + + /** + * @hide + * Retrieve the active {@link VoiceInteractor} that the user is going through to + * interact with this activity. + */ + @SystemApi + public VoiceInteractor getVoiceInteractor() { + return mVoiceInteractor; + } + + /** * This is called for activities that set launchMode to "singleTop" in * their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} * flag when calling {@link #startActivity}. In either case, when the * activity is re-launched while at the top of the activity stack instead * of a new instance of the activity being started, onNewIntent() will be * called on the existing instance with the Intent that was used to - * re-launch it. - * - * <p>An activity will always be paused before receiving a new intent, so - * you can count on {@link #onResume} being called after this method. - * - * <p>Note that {@link #getIntent} still returns the original Intent. You - * can use {@link #setIntent} to update it to this new Intent. - * - * @param intent The new intent that was started for the activity. - * + * re-launch it. + * + * <p>An activity will always be paused before receiving a new intent, so + * you can count on {@link #onResume} being called after this method. + * + * <p>Note that {@link #getIntent} still returns the original Intent. You + * can use {@link #setIntent} to update it to this new Intent. + * + * @param intent The new intent that was started for the activity. + * * @see #getIntent - * @see #setIntent - * @see #onResume + * @see #setIntent + * @see #onResume */ protected void onNewIntent(Intent intent) { } @@ -1153,10 +1296,27 @@ final void performSaveInstanceState(Bundle outState) { onSaveInstanceState(outState); saveManagedDialogs(outState); + mActivityTransitionState.saveState(outState); if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState); } /** + * The hook for {@link ActivityThread} to save the state of this activity. + * + * Calls {@link #onSaveInstanceState(android.os.Bundle)} + * and {@link #saveManagedDialogs(android.os.Bundle)}. + * + * @param outState The bundle to save the state to. + * @param outPersistentState The bundle to save persistent state to. + */ + final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { + onSaveInstanceState(outState, outPersistentState); + saveManagedDialogs(outState); + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState + + ", " + outPersistentState); + } + + /** * Called to retrieve per-instance state from an activity before being killed * so that the state can be restored in {@link #onCreate} or * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method @@ -1194,9 +1354,9 @@ * * <p>If called, this method will occur before {@link #onStop}. There are * no guarantees about whether it will occur before or after {@link #onPause}. - * + * * @param outState Bundle in which to place your saved state. - * + * * @see #onCreate * @see #onRestoreInstanceState * @see #onPause @@ -1211,6 +1371,25 @@ } /** + * This is the same as {@link #onSaveInstanceState} but is called for activities + * created with the attribute {@link android.R.attr#persistableMode} set to + * <code>persistAcrossReboots</code>. The {@link android.os.PersistableBundle} passed + * in will be saved and presented in {@link #onCreate(Bundle, PersistableBundle)} + * the first time that this activity is restarted following the next device reboot. + * + * @param outState Bundle in which to place your saved state. + * @param outPersistentState State which will be saved across reboots. + * + * @see #onSaveInstanceState(Bundle) + * @see #onCreate + * @see #onRestoreInstanceState(Bundle, PersistableBundle) + * @see #onPause + */ + public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { + onSaveInstanceState(outState); + } + + /** * Save the state of any managed dialogs. * * @param outState place to store the saved state. @@ -1262,23 +1441,23 @@ * noticeable amount of CPU in order to make the switch to the next activity * as fast as possible, or to close resources that are exclusive access * such as the camera. - * + * * <p>In situations where the system needs more memory it may kill paused * processes to reclaim resources. Because of this, you should be sure * that all of your state is saved by the time you return from * this function. In general {@link #onSaveInstanceState} is used to save * per-instance state in the activity and this method is used to store * global persistent data (in content providers, files, etc.) - * + * * <p>After receiving this call you will usually receive a following call * to {@link #onStop} (after the next activity has been resumed and * displayed), however in some cases there will be a direct call back to * {@link #onResume} without going through the stopped state. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onResume * @see #onSaveInstanceState * @see #onStop @@ -1297,32 +1476,32 @@ * brought to the foreground, {@link #onUserLeaveHint} will not be called on * the activity being interrupted. In cases when it is invoked, this method * is called right before the activity's {@link #onPause} callback. - * + * * <p>This callback and {@link #onUserInteraction} are intended to help * activities manage status bar notifications intelligently; specifically, * for helping activities determine the proper time to cancel a notfication. - * + * * @see #onUserInteraction() */ protected void onUserLeaveHint() { } - + /** * Generate a new thumbnail for this activity. This method is called before * pausing the activity, and should draw into <var>outBitmap</var> the * imagery for the desired thumbnail in the dimensions of that bitmap. It * can use the given <var>canvas</var>, which is configured to draw into the * bitmap, for rendering if desired. - * + * * <p>The default implementation returns fails and does not draw a thumbnail; * this will result in the platform creating its own thumbnail if needed. - * + * * @param outBitmap The bitmap to contain the thumbnail. * @param canvas Can be used to render into the bitmap. - * + * * @return Return true if you have drawn into the bitmap; otherwise after * you return it will be filled with a default thumbnail. - * + * * @see #onCreateDescription * @see #onSaveInstanceState * @see #onPause @@ -1335,19 +1514,20 @@ * Generate a new description for this activity. This method is called * before pausing the activity and can, if desired, return some textual * description of its current state to be displayed to the user. - * + * * <p>The default implementation returns null, which will cause you to * inherit the description from the previous activity. If all activities * return null, generally the label of the top activity will be used as the * description. - * + * * @return A description of what the user is doing. It should be short and * sweet (only a few words). - * + * * @see #onCreateThumbnail * @see #onSaveInstanceState * @see #onPause */ + @Nullable public CharSequence onCreateDescription() { return null; } @@ -1370,15 +1550,15 @@ * Called when you are no longer visible to the user. You will next * receive either {@link #onRestart}, {@link #onDestroy}, or nothing, * depending on later user activity. - * + * * <p>Note that this method may never be called, in low memory situations * where the system does not have enough memory to keep your activity's * process running after its {@link #onPause} method is called. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onRestart * @see #onResume * @see #onSaveInstanceState @@ -1387,6 +1567,7 @@ protected void onStop() { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this); if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false); + mActivityTransitionState.onStop(); getApplication().dispatchActivityStopped(this); mTranslucentCallback = null; mCalled = true; @@ -1398,7 +1579,7 @@ * {@link #finish} on it, or because the system is temporarily destroying * this instance of the activity to save space. You can distinguish * between these two scenarios with the {@link #isFinishing} method. - * + * * <p><em>Note: do not count on this method being called as a place for * saving data! For example, if an activity is editing data in a content * provider, those edits should be committed in either {@link #onPause} or @@ -1410,11 +1591,11 @@ * calling this method (or any others) in it, so it should not be used to * do things that are intended to remain around after the process goes * away. - * + * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> - * + * * @see #onPause * @see #onStop * @see #finish @@ -1488,11 +1669,11 @@ * by that attribute, then instead of reporting it the system will stop * and restart the activity (to have it launched with the new * configuration). - * + * * <p>At the time that this function has been called, your Resources * object will have been updated to return resource values matching the * new configuration. - * + * * @param newConfig The new device configuration. */ public void onConfigurationChanged(Configuration newConfig) { @@ -1512,7 +1693,7 @@ mActionBar.onConfigurationChanged(newConfig); } } - + /** * If this activity is being destroyed because it can not handle a * configuration parameter being changed (and thus its @@ -1522,7 +1703,7 @@ * destroyed. Note that there is no guarantee that these will be * accurate (other changes could have happened at any time), so you should * only use this as an optimization hint. - * + * * @return Returns a bit field of the configuration parameters that are * changing, as defined by the {@link android.content.res.Configuration} * class. @@ -1530,21 +1711,21 @@ public int getChangingConfigurations() { return mConfigChangeFlags; } - + /** * Retrieve the non-configuration instance data that was previously * returned by {@link #onRetainNonConfigurationInstance()}. This will * be available from the initial {@link #onCreate} and * {@link #onStart} calls to the new instance, allowing you to extract * any useful dynamic state from the previous instance. - * + * * <p>Note that the data you retrieve here should <em>only</em> be used * as an optimization for handling configuration changes. You should always * be able to handle getting a null pointer back, and an activity must * still be able to restore itself to its previous state (through the * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this * function returns null. - * + * * @return Returns the object previously returned by * {@link #onRetainNonConfigurationInstance()}. * @@ -1552,12 +1733,13 @@ * {@link Fragment#setRetainInstance(boolean)} instead; this is also * available on older platforms through the Android compatibility package. */ + @Nullable @Deprecated public Object getLastNonConfigurationInstance() { return mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.activity : null; } - + /** * Called by the system, as part of destroying an * activity due to a configuration change, when it is known that a new @@ -1566,7 +1748,7 @@ * itself, which can later be retrieved by calling * {@link #getLastNonConfigurationInstance()} in the new activity * instance. - * + * * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB} * or later, consider instead using a {@link Fragment} with * {@link Fragment#setRetainInstance(boolean) @@ -1586,14 +1768,14 @@ * the {@link #getLastNonConfigurationInstance()} method of the following * activity instance as described there. * </ul> - * + * * <p>These guarantees are designed so that an activity can use this API * to propagate extensive state from the old to new activity instance, from * loaded bitmaps, to network connections, to evenly actively running * threads. Note that you should <em>not</em> propagate any data that * may change based on the configuration, including any data loaded from * resources such as strings, layouts, or drawables. - * + * * <p>The guarantee of no message handling during the switch to the next * activity simplifies use with active objects. For example if your retained * state is an {@link android.os.AsyncTask} you are guaranteed that its @@ -1613,29 +1795,30 @@ public Object onRetainNonConfigurationInstance() { return null; } - + /** * Retrieve the non-configuration instance data that was previously * returned by {@link #onRetainNonConfigurationChildInstances()}. This will * be available from the initial {@link #onCreate} and * {@link #onStart} calls to the new instance, allowing you to extract * any useful dynamic state from the previous instance. - * + * * <p>Note that the data you retrieve here should <em>only</em> be used * as an optimization for handling configuration changes. You should always * be able to handle getting a null pointer back, and an activity must * still be able to restore itself to its previous state (through the * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this * function returns null. - * + * * @return Returns the object previously returned by * {@link #onRetainNonConfigurationChildInstances()} */ + @Nullable HashMap<String, Object> getLastNonConfigurationChildInstances() { return mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.children : null; } - + /** * This method is similar to {@link #onRetainNonConfigurationInstance()} except that * it should return either a mapping from child activity id strings to arbitrary objects, @@ -1643,10 +1826,11 @@ * set of child activities, such as ActivityGroup. The same guarantees and restrictions apply * as for {@link #onRetainNonConfigurationInstance()}. The default implementation returns null. */ + @Nullable HashMap<String,Object> onRetainNonConfigurationChildInstances() { return null; } - + NonConfigurationInstances retainNonConfigurationInstances() { Object activity = onRetainNonConfigurationInstance(); HashMap<String, Object> children = onRetainNonConfigurationChildInstances(); @@ -1670,15 +1854,17 @@ } } } - if (activity == null && children == null && fragments == null && !retainLoaders) { + if (activity == null && children == null && fragments == null && !retainLoaders + && mVoiceInteractor == null) { return null; } - + NonConfigurationInstances nci = new NonConfigurationInstances(); nci.activity = activity; nci.children = children; nci.fragments = fragments; nci.loaders = mAllLoaderManagers; + nci.voiceInteractor = mVoiceInteractor; return nci; } @@ -1712,7 +1898,7 @@ } } } - + /** * Called when a Fragment is being attached to this activity, immediately * after the call to its {@link Fragment#onAttach Fragment.onAttach()} @@ -1720,14 +1906,14 @@ */ public void onAttachFragment(Fragment fragment) { } - + /** * Wrapper around * {@link ContentResolver#query(android.net.Uri , String[], String, String[], String)} * that gives the resulting {@link Cursor} to call * {@link #startManagingCursor} so that the activity will manage its * lifecycle for you. - * + * * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB} * or later, consider instead using {@link LoaderManager} instead, available * via {@link #getLoaderManager()}.</em> @@ -1737,14 +1923,14 @@ * you call {@link #stopManagingCursor} on a cursor from a managed query, the system <em>will * not</em> automatically close the cursor and, in that case, you must call * {@link Cursor#close()}.</p> - * + * * @param uri The URI of the content provider to query. * @param projection List of columns to return. * @param selection SQL WHERE clause. * @param sortOrder SQL ORDER BY clause. - * + * * @return The Cursor that was returned by query(). - * + * * @see ContentResolver#query(android.net.Uri , String[], String, String[], String) * @see #startManagingCursor * @hide @@ -1767,7 +1953,7 @@ * that gives the resulting {@link Cursor} to call * {@link #startManagingCursor} so that the activity will manage its * lifecycle for you. - * + * * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB} * or later, consider instead using {@link LoaderManager} instead, available * via {@link #getLoaderManager()}.</em> @@ -1777,15 +1963,15 @@ * you call {@link #stopManagingCursor} on a cursor from a managed query, the system <em>will * not</em> automatically close the cursor and, in that case, you must call * {@link Cursor#close()}.</p> - * + * * @param uri The URI of the content provider to query. * @param projection List of columns to return. * @param selection SQL WHERE clause. * @param selectionArgs The arguments to selection, if any ?s are pesent * @param sortOrder SQL ORDER BY clause. - * + * * @return The Cursor that was returned by query(). - * + * * @see ContentResolver#query(android.net.Uri , String[], String, String[], String) * @see #startManagingCursor * @@ -1808,7 +1994,7 @@ * {@link Cursor#deactivate} on the given Cursor, and when it is later restarted * it will call {@link Cursor#requery} for you. When the activity is * destroyed, all managed Cursors will be closed automatically. - * + * * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB} * or later, consider instead using {@link LoaderManager} instead, available * via {@link #getLoaderManager()}.</em> @@ -1818,9 +2004,9 @@ * However, if you call {@link #stopManagingCursor} on a cursor from a managed query, the system * <em>will not</em> automatically close the cursor and, in that case, you must call * {@link Cursor#close()}.</p> - * + * * @param c The Cursor to be managed. - * + * * @see #managedQuery(android.net.Uri , String[], String, String[], String) * @see #stopManagingCursor * @@ -1839,13 +2025,13 @@ * Given a Cursor that was previously given to * {@link #startManagingCursor}, stop the activity's management of that * cursor. - * + * * <p><strong>Warning:</strong> After calling this method on a cursor from a managed query, - * the system <em>will not</em> automatically close the cursor and you must call + * the system <em>will not</em> automatically close the cursor and you must call * {@link Cursor#close()}.</p> - * + * * @param c The Cursor that was being managed. - * + * * @see #startManagingCursor * * @deprecated Use the new {@link android.content.CursorLoader} class with @@ -1884,22 +2070,50 @@ public View findViewById(int id) { return getWindow().findViewById(id); } - + /** * Retrieve a reference to this activity's ActionBar. * * @return The Activity's ActionBar, or null if it does not have one. */ + @Nullable public ActionBar getActionBar() { - initActionBar(); + initWindowDecorActionBar(); return mActionBar; } - + + /** + * Set a {@link android.widget.Toolbar Toolbar} to act as the {@link ActionBar} for this + * Activity window. + * + * <p>When set to a non-null value the {@link #getActionBar()} method will return + * an {@link ActionBar} object that can be used to control the given toolbar as if it were + * a traditional window decor action bar. The toolbar's menu will be populated with the + * Activity's options menu and the navigation button will be wired through the standard + * {@link android.R.id#home home} menu select action.</p> + * + * <p>In order to use a Toolbar within the Activity's window content the application + * must not request the window feature {@link Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p> + * + * @param toolbar Toolbar to set as the Activity's action bar + */ + public void setActionBar(@Nullable Toolbar toolbar) { + if (getActionBar() instanceof WindowDecorActionBar) { + throw new IllegalStateException("This Activity already has an action bar supplied " + + "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + + "android:windowActionBar to false in your theme to use a Toolbar instead."); + } + ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this); + mActionBar = tbab; + mWindow.setCallback(tbab.getWrappedWindowCallback()); + mActionBar.invalidateOptionsMenu(); + } + /** * Creates a new ActionBar, locates the inflated ActionBarView, * initializes the ActionBar with the view, and sets mActionBar. */ - private void initActionBar() { + private void initWindowDecorActionBar() { Window window = getWindow(); // Initializing the window decor can change window feature flags. @@ -1910,25 +2124,25 @@ return; } - mActionBar = new ActionBarImpl(this); + mActionBar = new WindowDecorActionBar(this); mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp); mWindow.setDefaultIcon(mActivityInfo.getIconResource()); mWindow.setDefaultLogo(mActivityInfo.getLogoResource()); } - + /** * Set the activity content from a layout resource. The resource will be * inflated, adding all top-level views to the activity. * * @param layoutResID Resource ID to be inflated. - * + * * @see #setContentView(android.view.View) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); - initActionBar(); + initWindowDecorActionBar(); } /** @@ -1940,7 +2154,7 @@ * your own layout parameters, invoke * {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)} * instead. - * + * * @param view The desired content to display. * * @see #setContentView(int) @@ -1948,14 +2162,14 @@ */ public void setContentView(View view) { getWindow().setContentView(view); - initActionBar(); + initWindowDecorActionBar(); } /** * Set the activity content to an explicit view. This view is placed * directly into the activity's view hierarchy. It can itself be a complex * view hierarchy. - * + * * @param view The desired content to display. * @param params Layout parameters for the view. * @@ -1964,19 +2178,54 @@ */ public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); - initActionBar(); + initWindowDecorActionBar(); } /** * Add an additional content view to the activity. Added after any existing * ones in the activity -- existing views are NOT removed. - * + * * @param view The desired content to display. * @param params Layout parameters for the view. */ public void addContentView(View view, ViewGroup.LayoutParams params) { getWindow().addContentView(view, params); - initActionBar(); + initWindowDecorActionBar(); + } + + /** + * Retrieve the {@link TransitionManager} responsible for default transitions in this window. + * Requires {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * + * <p>This method will return non-null after content has been initialized (e.g. by using + * {@link #setContentView}) if {@link Window#FEATURE_CONTENT_TRANSITIONS} has been granted.</p> + * + * @return This window's content TransitionManager or null if none is set. + */ + public TransitionManager getContentTransitionManager() { + return getWindow().getTransitionManager(); + } + + /** + * Set the {@link TransitionManager} to use for default transitions in this window. + * Requires {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * + * @param tm The TransitionManager to use for scene changes. + */ + public void setContentTransitionManager(TransitionManager tm) { + getWindow().setTransitionManager(tm); + } + + /** + * Retrieve the {@link Scene} representing this window's current content. + * Requires {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * + * <p>This method will return null if the current content is not represented by a Scene.</p> + * + * @return Current Scene being shown or null + */ + public Scene getContentScene() { + return getWindow().getContentScene(); } /** @@ -1986,27 +2235,37 @@ public void setFinishOnTouchOutside(boolean finish) { mWindow.setCloseOnTouchOutside(finish); } - + + /** @hide */ + @IntDef({ + DEFAULT_KEYS_DISABLE, + DEFAULT_KEYS_DIALER, + DEFAULT_KEYS_SHORTCUT, + DEFAULT_KEYS_SEARCH_LOCAL, + DEFAULT_KEYS_SEARCH_GLOBAL}) + @Retention(RetentionPolicy.SOURCE) + @interface DefaultKeyMode {} + /** * Use with {@link #setDefaultKeyMode} to turn off default handling of * keys. - * + * * @see #setDefaultKeyMode */ static public final int DEFAULT_KEYS_DISABLE = 0; /** * Use with {@link #setDefaultKeyMode} to launch the dialer during default * key handling. - * + * * @see #setDefaultKeyMode */ static public final int DEFAULT_KEYS_DIALER = 1; /** * Use with {@link #setDefaultKeyMode} to execute a menu shortcut in * default key handling. - * + * * <p>That is, the user does not need to hold down the menu key to execute menu shortcuts. - * + * * @see #setDefaultKeyMode */ static public final int DEFAULT_KEYS_SHORTCUT = 2; @@ -2014,9 +2273,9 @@ * Use with {@link #setDefaultKeyMode} to specify that unhandled keystrokes * will start an application-defined search. (If the application or activity does not * actually define a search, the the keys will be ignored.) - * + * * <p>See {@link android.app.SearchManager android.app.SearchManager} for more details. - * + * * @see #setDefaultKeyMode */ static public final int DEFAULT_KEYS_SEARCH_LOCAL = 3; @@ -2025,9 +2284,9 @@ * Use with {@link #setDefaultKeyMode} to specify that unhandled keystrokes * will start a global search (typically web search, but some platforms may define alternate * methods for global search) - * + * * <p>See {@link android.app.SearchManager android.app.SearchManager} for more details. - * + * * @see #setDefaultKeyMode */ static public final int DEFAULT_KEYS_SEARCH_GLOBAL = 4; @@ -2039,16 +2298,16 @@ * floor. Other modes allow you to launch the dialer * ({@link #DEFAULT_KEYS_DIALER}), execute a shortcut in your options * menu without requiring the menu key be held down - * ({@link #DEFAULT_KEYS_SHORTCUT}), or launch a search ({@link #DEFAULT_KEYS_SEARCH_LOCAL} + * ({@link #DEFAULT_KEYS_SHORTCUT}), or launch a search ({@link #DEFAULT_KEYS_SEARCH_LOCAL} * and {@link #DEFAULT_KEYS_SEARCH_GLOBAL}). - * + * * <p>Note that the mode selected here does not impact the default * handling of system keys, such as the "back" and "menu" keys, and your * activity and its views always get a first chance to receive and handle * all application keys. - * + * * @param mode The desired default key mode constant. - * + * * @see #DEFAULT_KEYS_DISABLE * @see #DEFAULT_KEYS_DIALER * @see #DEFAULT_KEYS_SHORTCUT @@ -2056,9 +2315,9 @@ * @see #DEFAULT_KEYS_SEARCH_GLOBAL * @see #onKeyDown */ - public final void setDefaultKeyMode(int mode) { + public final void setDefaultKeyMode(@DefaultKeyMode int mode) { mDefaultKeyMode = mode; - + // Some modes use a SpannableStringBuilder to track & dispatch input events // This list must remain in sync with the switch in onKeyDown() switch (mode) { @@ -2079,10 +2338,10 @@ /** * Called when a key was pressed down and not handled by any of the views - * inside of the activity. So, for example, key presses while the cursor + * inside of the activity. So, for example, key presses while the cursor * is inside a TextView will not trigger the event (unless it is a navigation * to another object) because TextView handles its own key presses. - * + * * <p>If the focused view didn't want this event, this method is called. * * <p>The default implementation takes care of {@link KeyEvent#KEYCODE_BACK} @@ -2093,12 +2352,12 @@ * will be performed; for earlier applications, it will perform the * action immediately in on-down, as those versions of the platform * behaved. - * + * * <p>Other additional default key handling may be performed * if configured with {@link #setDefaultKeyMode}. - * + * * @return Return <code>true</code> to prevent this event from being propagated - * further, or <code>false</code> to indicate that you have not handled + * further, or <code>false</code> to indicate that you have not handled * this event and it should continue to be propagated. * @see #onKeyUp * @see android.view.KeyEvent @@ -2113,11 +2372,11 @@ } return true; } - + if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) { return false; } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) { - if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL, + if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL, keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) { return true; } @@ -2137,12 +2396,12 @@ final String str = mDefaultKeySsb.toString(); clearSpannable = true; - + switch (mDefaultKeyMode) { case DEFAULT_KEYS_DIALER: Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + str)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); + startActivity(intent); break; case DEFAULT_KEYS_SEARCH_LOCAL: startSearch(str, false, null, false); @@ -2173,16 +2432,16 @@ /** * Called when a key was released and not handled by any of the views - * inside of the activity. So, for example, key presses while the cursor + * inside of the activity. So, for example, key presses while the cursor * is inside a TextView will not trigger the event (unless it is a navigation * to another object) because TextView handles its own key presses. - * + * * <p>The default implementation handles KEYCODE_BACK to stop the activity * and go back. - * + * * @return Return <code>true</code> to prevent this event from being propagated - * further, or <code>false</code> to indicate that you have not handled - * this event and it should continue to be propagated. + * further, or <code>false</code> to indicate that you have not handled + * this event and it should continue to be propagated. * @see #onKeyDown * @see KeyEvent */ @@ -2206,15 +2465,19 @@ public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return false; } - + /** * Called when the activity has detected the user's press of the back * key. The default implementation simply finishes the current activity, * but you can override this to do whatever you want. */ public void onBackPressed() { + if (mActionBar != null && mActionBar.collapseActionView()) { + return; + } + if (!mFragments.popBackStackImmediate()) { - finish(); + finishAfterTransition(); } } @@ -2236,9 +2499,9 @@ * Called when a touch screen event was not handled by any of the views * under it. This is most useful to process touch events that happen * outside of your window bounds, where there is no view to receive it. - * + * * @param event The touch screen event being processed. - * + * * @return Return true if you have consumed the event, false if you haven't. * The default implementation always returns false. */ @@ -2247,10 +2510,10 @@ finish(); return true; } - + return false; } - + /** * Called when the trackball was moved and not handled by any of the * views inside of the activity. So, for example, if the trackball moves @@ -2259,9 +2522,9 @@ * here happens <em>before</em> trackball movements are converted to * DPAD key events, which then get sent back to the view hierarchy, and * will be processed at the point for things like focus navigation. - * + * * @param event The trackball event being processed. - * + * * @return Return true if you have consumed the event, false if you haven't. * The default implementation always returns false. */ @@ -2305,21 +2568,21 @@ * This callback and {@link #onUserLeaveHint} are intended to help * activities manage status bar notifications intelligently; specifically, * for helping activities determine the proper time to cancel a notfication. - * + * * <p>All calls to your activity's {@link #onUserLeaveHint} callback will * be accompanied by calls to {@link #onUserInteraction}. This * ensures that your activity will be told of relevant user activity such * as pulling down the notification pane and touching an item there. - * + * * <p>Note that this callback will be invoked for the touch down action * that begins a touch gesture, but may not be invoked for the touch-moved * and touch-up actions that follow. - * + * * @see #onUserLeaveHint() */ public void onUserInteraction() { } - + public void onWindowAttributesChanged(WindowManager.LayoutParams params) { // Update window manager if: we have a view, that view is // attached to its parent (which will be a RootView), and @@ -2340,14 +2603,14 @@ * focus. This is the best indicator of whether this activity is visible * to the user. The default implementation clears the key tracking * state, so should always be called. - * + * * <p>Note that this provides information about global focus state, which * is managed independently of activity lifecycles. As such, while focus * changes will generally have some relation to lifecycle changes (an * activity that is stopped will not generally get window focus), you * should not rely on any particular order between the callbacks here and * those in the other lifecycle methods such as {@link #onResume}. - * + * * <p>As a general rule, however, a resumed activity will have window * focus... unless it has displayed other dialogs or popups that take * input focus, in which case the activity itself will not have focus @@ -2357,14 +2620,14 @@ * pausing the foreground activity. * * @param hasFocus Whether the window of this activity has focus. - * + * * @see #hasWindowFocus() * @see #onResume * @see View#onWindowFocusChanged(boolean) */ public void onWindowFocusChanged(boolean hasFocus) { } - + /** * Called when the main window associated with the activity has been * attached to the window manager. @@ -2374,7 +2637,7 @@ */ public void onAttachedToWindow() { } - + /** * Called when the main window associated with the activity has been * detached from the window manager. @@ -2384,13 +2647,13 @@ */ public void onDetachedFromWindow() { } - + /** * Returns true if this activity's <em>main</em> window currently has window focus. * Note that this is not the same as the view itself having focus. - * + * * @return True if this activity's main window currently has window focus. - * + * * @see #onWindowAttributesChanged(android.view.WindowManager.LayoutParams) */ public boolean hasWindowFocus() { @@ -2412,18 +2675,26 @@ public void onWindowDismissed() { finish(); } - + /** - * Called to process key events. You can override this to intercept all - * key events before they are dispatched to the window. Be sure to call + * Called to process key events. You can override this to intercept all + * key events before they are dispatched to the window. Be sure to call * this implementation for key events that should be handled normally. - * + * * @param event The key event. - * + * * @return boolean Return true if this event was consumed. */ public boolean dispatchKeyEvent(KeyEvent event) { onUserInteraction(); + + // Let action bars open menus in response to the menu key prioritized over + // the window handling it + if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && + mActionBar != null && mActionBar.onMenuKeyEvent(event)) { + return true; + } + Window win = getWindow(); if (win.superDispatchKeyEvent(event)) { return true; @@ -2456,9 +2727,9 @@ * intercept all touch screen events before they are dispatched to the * window. Be sure to call this implementation for touch screen events * that should be handled normally. - * + * * @param ev The touch screen event. - * + * * @return boolean Return true if this event was consumed. */ public boolean dispatchTouchEvent(MotionEvent ev) { @@ -2470,15 +2741,15 @@ } return onTouchEvent(ev); } - + /** * Called to process trackball events. You can override this to * intercept all trackball events before they are dispatched to the * window. Be sure to call this implementation for trackball events * that should be handled normally. - * + * * @param ev The trackball event. - * + * * @return boolean Return true if this event was consumed. */ public boolean dispatchTrackballEvent(MotionEvent ev) { @@ -2531,6 +2802,7 @@ * simply returns null so that all panel sub-windows will have the default * menu behavior. */ + @Nullable public View onCreatePanelView(int featureId) { return null; } @@ -2572,12 +2844,12 @@ /** * {@inheritDoc} - * + * * @return The default implementation returns true. */ public boolean onMenuOpened(int featureId, Menu menu) { if (featureId == Window.FEATURE_ACTION_BAR) { - initActionBar(); + initWindowDecorActionBar(); if (mActionBar != null) { mActionBar.dispatchMenuVisibilityChanged(true); } else { @@ -2622,7 +2894,7 @@ } } return false; - + case Window.FEATURE_CONTEXT_MENU: if(titleCondensed != null) { EventLog.writeEvent(50000, 1, titleCondensed.toString()); @@ -2636,7 +2908,7 @@ return false; } } - + /** * Default implementation of * {@link android.view.Window.Callback#onPanelClosed(int, Menu)} for @@ -2652,13 +2924,13 @@ mFragments.dispatchOptionsMenuClosed(menu); onOptionsMenuClosed(menu); break; - + case Window.FEATURE_CONTEXT_MENU: onContextMenuClosed(menu); break; case Window.FEATURE_ACTION_BAR: - initActionBar(); + initWindowDecorActionBar(); mActionBar.dispatchMenuVisibilityChanged(false); break; } @@ -2670,34 +2942,36 @@ * time it needs to be displayed. */ public void invalidateOptionsMenu() { - mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL); + if (mActionBar == null || !mActionBar.invalidateOptionsMenu()) { + mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL); + } } - + /** * Initialize the contents of the Activity's standard options menu. You * should place your menu items in to <var>menu</var>. - * + * * <p>This is only called once, the first time the options menu is * displayed. To update the menu every time it is displayed, see * {@link #onPrepareOptionsMenu}. - * + * * <p>The default implementation populates the menu with standard system - * menu items. These are placed in the {@link Menu#CATEGORY_SYSTEM} group so that - * they will be correctly ordered with application-defined menu items. - * Deriving classes should always call through to the base implementation. - * + * menu items. These are placed in the {@link Menu#CATEGORY_SYSTEM} group so that + * they will be correctly ordered with application-defined menu items. + * Deriving classes should always call through to the base implementation. + * * <p>You can safely hold on to <var>menu</var> (and any items created * from it), making modifications to it as desired, until the next * time onCreateOptionsMenu() is called. - * + * * <p>When you add items to the menu, you can implement the Activity's * {@link #onOptionsItemSelected} method to handle them there. - * + * * @param menu The options menu in which you place your items. - * + * * @return You must return true for the menu to be displayed; * if you return false it will not be shown. - * + * * @see #onPrepareOptionsMenu * @see #onOptionsItemSelected */ @@ -2713,17 +2987,17 @@ * called right before the menu is shown, every time it is shown. You can * use this method to efficiently enable/disable items or otherwise * dynamically modify the contents. - * + * * <p>The default implementation updates the system menu items based on the * activity's state. Deriving classes should always call through to the * base class implementation. - * + * * @param menu The options menu as last shown or first initialized by * onCreateOptionsMenu(). - * + * * @return You must return true for the menu to be displayed; * if you return false it will not be shown. - * + * * @see #onCreateOptionsMenu */ public boolean onPrepareOptionsMenu(Menu menu) { @@ -2740,15 +3014,15 @@ * its Handler as appropriate). You can use this method for any items * for which you would like to do processing without those other * facilities. - * + * * <p>Derived classes should call through to the base class for it to * perform the default menu handling.</p> - * + * * @param item The menu item that was selected. - * + * * @return boolean Return false to allow normal menu processing to * proceed, true to consume it here. - * + * * @see #onCreateOptionsMenu */ public boolean onOptionsItemSelected(MenuItem item) { @@ -2865,7 +3139,7 @@ /** * This hook is called whenever the options menu is being closed (either by the user canceling * the menu with the back/menu button, or when an item is selected). - * + * * @param menu The options menu as last shown or first initialized by * onCreateOptionsMenu(). */ @@ -2874,15 +3148,17 @@ mParent.onOptionsMenuClosed(menu); } } - + /** * Programmatically opens the options menu. If the options menu is already * open, this method does nothing. */ public void openOptionsMenu() { - mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null); + if (mActionBar == null || !mActionBar.openOptionsMenu()) { + mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null); + } } - + /** * Progammatically closes the options menu. If the options menu is already * closed, this method does nothing. @@ -2913,43 +3189,43 @@ * {@link OnCreateContextMenuListener} on the view to this activity, so * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be * called when it is time to show the context menu. - * + * * @see #unregisterForContextMenu(View) * @param view The view that should show a context menu. */ public void registerForContextMenu(View view) { view.setOnCreateContextMenuListener(this); } - + /** * Prevents a context menu to be shown for the given view. This method will remove the * {@link OnCreateContextMenuListener} on the view. - * + * * @see #registerForContextMenu(View) * @param view The view that should stop showing a context menu. */ public void unregisterForContextMenu(View view) { view.setOnCreateContextMenuListener(null); } - + /** * Programmatically opens the context menu for a particular {@code view}. * The {@code view} should have been added via * {@link #registerForContextMenu(View)}. - * + * * @param view The view to show the context menu for. */ public void openContextMenu(View view) { view.showContextMenu(); } - + /** * Programmatically closes the most recently opened context menu, if showing. */ public void closeContextMenu() { mWindow.closePanel(Window.FEATURE_CONTEXT_MENU); } - + /** * This hook is called whenever an item in a context menu is selected. The * default implementation simply returns false to have the normal processing @@ -2962,7 +3238,7 @@ * <p> * Derived classes should call through to the base class for it to perform * the default menu handling. - * + * * @param item The context menu item that was selected. * @return boolean Return false to allow normal context menu processing to * proceed, true to consume it here. @@ -2978,7 +3254,7 @@ * This hook is called whenever the context menu is being closed (either by * the user canceling the menu with the back/menu button, or when an item is * selected). - * + * * @param menu The context menu that is being closed. */ public void onContextMenuClosed(Menu menu) { @@ -3028,6 +3304,7 @@ * {@link FragmentManager} instead; this is also * available on older platforms through the Android compatibility package. */ + @Nullable @Deprecated protected Dialog onCreateDialog(int id, Bundle args) { return onCreateDialog(id); @@ -3046,14 +3323,14 @@ * Provides an opportunity to prepare a managed dialog before it is being * shown. The default implementation calls through to * {@link #onPrepareDialog(int, Dialog)} for compatibility. - * + * * <p> * Override this if you need to update a managed dialog based on the state * of the application each time it is shown. For example, a time picker * dialog might want to be updated with the current time. You should call * through to the superclass's implementation. The default implementation * will set this Activity as the owner activity on the Dialog. - * + * * @param id The id of the managed dialog. * @param dialog The dialog. * @param args The dialog arguments provided to {@link #showDialog(int, Bundle)}. @@ -3104,7 +3381,7 @@ * If you need to rebuild the dialog, call {@link #removeDialog(int)} first. * @return Returns true if the Dialog was created; false is returned if * it is not created because {@link #onCreateDialog(int, Bundle)} returns false. - * + * * @see Dialog * @see #onCreateDialog(int, Bundle) * @see #onPrepareDialog(int, Dialog, Bundle) @@ -3115,6 +3392,7 @@ * {@link FragmentManager} instead; this is also * available on older platforms through the Android compatibility package. */ + @Nullable @Deprecated public final boolean showDialog(int id, Bundle args) { if (mManagedDialogs == null) { @@ -3129,7 +3407,7 @@ } mManagedDialogs.put(id, md); } - + md.mArgs = args; onPrepareDialog(id, md.mDialog, args); md.mDialog.show(); @@ -3158,7 +3436,7 @@ if (mManagedDialogs == null) { throw missingDialog(id); } - + final ManagedDialog md = mManagedDialogs.get(id); if (md == null) { throw missingDialog(id); @@ -3185,7 +3463,7 @@ * <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, this function * will not throw an exception if you try to remove an ID that does not * currently have an associated dialog.</p> - * + * * @param id The id of the managed dialog. * * @see #onCreateDialog(int, Bundle) @@ -3210,61 +3488,61 @@ /** * This hook is called when the user signals the desire to start a search. - * + * * <p>You can use this function as a simple way to launch the search UI, in response to a - * menu item, search button, or other widgets within your activity. Unless overidden, + * menu item, search button, or other widgets within your activity. Unless overidden, * calling this function is the same as calling * {@link #startSearch startSearch(null, false, null, false)}, which launches * search for the current activity as specified in its manifest, see {@link SearchManager}. - * + * * <p>You can override this function to force global search, e.g. in response to a dedicated * search key, or to block search entirely (by simply returning false). - * + * * @return Returns {@code true} if search launched, and {@code false} if activity blocks it. * The default implementation always returns {@code true}. - * + * * @see android.app.SearchManager */ public boolean onSearchRequested() { - startSearch(null, false, null, false); + startSearch(null, false, null, false); return true; } - + /** * This hook is called to launch the search UI. - * - * <p>It is typically called from onSearchRequested(), either directly from - * Activity.onSearchRequested() or from an overridden version in any given + * + * <p>It is typically called from onSearchRequested(), either directly from + * Activity.onSearchRequested() or from an overridden version in any given * Activity. If your goal is simply to activate search, it is preferred to call - * onSearchRequested(), which may have been overriden elsewhere in your Activity. If your goal + * onSearchRequested(), which may have been overridden elsewhere in your Activity. If your goal * is to inject specific data such as context data, it is preferred to <i>override</i> * onSearchRequested(), so that any callers to it will benefit from the override. - * - * @param initialQuery Any non-null non-empty string will be inserted as + * + * @param initialQuery Any non-null non-empty string will be inserted as * pre-entered text in the search query box. - * @param selectInitialQuery If true, the intial query will be preselected, which means that + * @param selectInitialQuery If true, the initial query will be preselected, which means that * any further typing will replace it. This is useful for cases where an entire pre-formed * query is being inserted. If false, the selection point will be placed at the end of the * inserted query. This is useful when the inserted query is text that the user entered, * and the user would expect to be able to keep typing. <i>This parameter is only meaningful * if initialQuery is a non-empty string.</i> - * @param appSearchData An application can insert application-specific - * context here, in order to improve quality or specificity of its own + * @param appSearchData An application can insert application-specific + * context here, in order to improve quality or specificity of its own * searches. This data will be returned with SEARCH intent(s). Null if * no extra data is required. * @param globalSearch If false, this will only launch the search that has been specifically - * defined by the application (which is usually defined as a local search). If no default + * defined by the application (which is usually defined as a local search). If no default * search is defined in the current application or activity, global search will be launched. * If true, this will always launch a platform-global (e.g. web-based) search instead. - * + * * @see android.app.SearchManager * @see #onSearchRequested */ - public void startSearch(String initialQuery, boolean selectInitialQuery, - Bundle appSearchData, boolean globalSearch) { + public void startSearch(@Nullable String initialQuery, boolean selectInitialQuery, + @Nullable Bundle appSearchData, boolean globalSearch) { ensureSearchManager(); mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(), - appSearchData, globalSearch); + appSearchData, globalSearch); } /** @@ -3277,7 +3555,7 @@ * searches. This data will be returned with SEARCH intent(s). Null if * no extra data is required. */ - public void triggerSearch(String query, Bundle appSearchData) { + public void triggerSearch(String query, @Nullable Bundle appSearchData) { ensureSearchManager(); mSearchManager.triggerSearch(query, getComponentName(), appSearchData); } @@ -3286,7 +3564,7 @@ * Request that key events come to this activity. Use this if your * activity has no views with focus, but the activity still wants * a chance to process key events. - * + * * @see android.view.Window#takeKeyEvents */ public void takeKeyEvents(boolean get) { @@ -3296,12 +3574,12 @@ /** * Enable extended window features. This is a convenience for calling * {@link android.view.Window#requestFeature getWindow().requestFeature()}. - * + * * @param featureId The desired feature as defined in * {@link android.view.Window}. * @return Returns true if the requested feature is supported and now * enabled. - * + * * @see android.view.Window#requestFeature */ public final boolean requestWindowFeature(int featureId) { @@ -3344,6 +3622,7 @@ * Convenience for calling * {@link android.view.Window#getLayoutInflater}. */ + @NonNull public LayoutInflater getLayoutInflater() { return getWindow().getLayoutInflater(); } @@ -3351,10 +3630,11 @@ /** * Returns a {@link MenuInflater} with this context. */ + @NonNull public MenuInflater getMenuInflater() { // Make sure that action views can get an appropriate theme. if (mMenuInflater == null) { - initActionBar(); + initWindowDecorActionBar(); if (mActionBar != null) { mMenuInflater = new MenuInflater(mActionBar.getThemedContext(), this); } else { @@ -3377,6 +3657,18 @@ } theme.applyStyle(resid, false); } + + // Get the primary color and update the TaskDescription for this activity + if (theme != null) { + TypedArray a = theme.obtainStyledAttributes(com.android.internal.R.styleable.Theme); + int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0); + a.recycle(); + if (colorPrimary != 0) { + ActivityManager.TaskDescription v = new ActivityManager.TaskDescription(null, null, + colorPrimary); + setTaskDescription(v); + } + } } /** @@ -3389,7 +3681,7 @@ * * @throws android.content.ActivityNotFoundException * - * @see #startActivity + * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); @@ -3398,8 +3690,8 @@ /** * Launch an activity for which you would like a result when it finished. * When this activity exits, your - * onActivityResult() method will be called with the given requestCode. - * Using a negative requestCode is the same as calling + * onActivityResult() method will be called with the given requestCode. + * Using a negative requestCode is the same as calling * {@link #startActivity} (the activity is not launched as a sub-activity). * * <p>Note that this method should only be used with Intent protocols @@ -3409,11 +3701,11 @@ * are launching uses the singleTask launch mode, it will not run in your * task and thus you will immediately receive a cancel result. * - * <p>As a special case, if you call startActivityForResult() with a requestCode + * <p>As a special case, if you call startActivityForResult() with a requestCode * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your - * activity, then your window will not be displayed until a result is - * returned back from the started activity. This is to avoid visible - * flickering when redirecting to another activity. + * activity, then your window will not be displayed until a result is + * returned back from the started activity. This is to avoid visible + * flickering when redirecting to another activity. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. @@ -3427,9 +3719,9 @@ * * @throws android.content.ActivityNotFoundException * - * @see #startActivity + * @see #startActivity */ - public void startActivityForResult(Intent intent, int requestCode, Bundle options) { + public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( @@ -3465,6 +3757,51 @@ mParent.startActivityFromChild(this, intent, requestCode); } } + if (options != null && !isTopOfTask()) { + mActivityTransitionState.startExitOutTransition(this, options); + } + } + + /** + * @hide Implement to provide correct calling token. + */ + public void startActivityForResultAsUser(Intent intent, int requestCode, UserHandle user) { + startActivityForResultAsUser(intent, requestCode, null, user); + } + + /** + * @hide Implement to provide correct calling token. + */ + public void startActivityForResultAsUser(Intent intent, int requestCode, + @Nullable Bundle options, UserHandle user) { + if (options != null) { + mActivityTransitionState.startExitOutTransition(this, options); + } + if (mParent != null) { + throw new RuntimeException("Can't be called from a child"); + } + Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( + this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, + options, user); + if (ar != null) { + mMainThread.sendActivityResult( + mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); + } + if (requestCode >= 0) { + // If this start is requesting a result, we can avoid making + // the activity visible until the result is received. Setting + // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the + // activity hidden during this time, to avoid flickering. + // This can only be done when a result is requested because + // that guarantees we will get information back when the + // activity is finished, no matter what happens to it. + mStartedActivity = true; + } + + final View decor = mWindow != null ? mWindow.peekDecorView() : null; + if (decor != null) { + decor.cancelPendingInputEvents(); + } } /** @@ -3479,7 +3816,7 @@ */ public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) { if (mParent != null) { - throw new RuntimeException("Called be called from a child"); + throw new RuntimeException("Can't be called from a child"); } Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( @@ -3493,6 +3830,29 @@ } /** + * Start a new activity as if it was started by the activity that started our + * current activity. This is for the resolver and chooser activities, which operate + * as intermediaries that dispatch their intent to the target the user selects -- to + * do this, they must perform all security checks including permission grants as if + * their launch had come from the original activity. + * @hide + */ + public void startActivityAsCaller(Intent intent, @Nullable Bundle options) { + if (mParent != null) { + throw new RuntimeException("Can't be called from a child"); + } + Instrumentation.ActivityResult ar = + mInstrumentation.execStartActivityAsCaller( + this, mMainThread.getApplicationThread(), mToken, this, + intent, -1, options); + if (ar != null) { + mMainThread.sendActivityResult( + mToken, mEmbeddedID, -1, ar.getResultCode(), + ar.getResultData()); + } + } + + /** * Same as calling {@link #startIntentSenderForResult(IntentSender, int, * Intent, int, int, int, Bundle)} with no options. * @@ -3508,7 +3868,7 @@ * @param extraFlags Always set to 0. */ public void startIntentSenderForResult(IntentSender intent, int requestCode, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) + @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) throws IntentSender.SendIntentException { startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask, flagsValues, extraFlags, null); @@ -3522,7 +3882,7 @@ * here; otherwise, its associated action will be executed (such as * sending a broadcast) as if you had called * {@link IntentSender#sendIntent IntentSender.sendIntent} on it. - * + * * @param intent The IntentSender to launch. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. @@ -3540,7 +3900,7 @@ * override any that conflict with those given by the IntentSender. */ public void startIntentSenderForResult(IntentSender intent, int requestCode, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, + @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) throws IntentSender.SendIntentException { if (mParent == null) { startIntentSenderForResultInner(intent, requestCode, fillInIntent, @@ -3602,7 +3962,7 @@ */ @Override public void startActivity(Intent intent) { - startActivity(intent, null); + this.startActivity(intent, null); } /** @@ -3613,22 +3973,22 @@ * information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not * required; if not specified, the new activity will be added to the * task of the caller. - * + * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. - * - * @param intent The intent to start. + * + * @param intent The intent to start. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. - * + * * @throws android.content.ActivityNotFoundException * * @see {@link #startActivity(Intent)} - * @see #startActivityForResult + * @see #startActivityForResult */ @Override - public void startActivity(Intent intent, Bundle options) { + public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { @@ -3677,7 +4037,7 @@ * @see #startActivityForResult */ @Override - public void startActivities(Intent[] intents, Bundle options) { + public void startActivities(Intent[] intents, @Nullable Bundle options) { mInstrumentation.execStartActivities(this, mMainThread.getApplicationThread(), mToken, this, intents, options); } @@ -3685,7 +4045,7 @@ /** * Same as calling {@link #startIntentSender(IntentSender, Intent, int, int, int, Bundle)} * with no options. - * + * * @param intent The IntentSender to launch. * @param fillInIntent If non-null, this will be provided as the * intent parameter to {@link IntentSender#sendIntent}. @@ -3696,7 +4056,7 @@ * @param extraFlags Always set to 0. */ public void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) + @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) throws IntentSender.SendIntentException { startIntentSender(intent, fillInIntent, flagsMask, flagsValues, extraFlags, null); @@ -3723,7 +4083,7 @@ * override any that conflict with those given by the IntentSender. */ public void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, + @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) throws IntentSender.SendIntentException { if (options != null) { startIntentSenderForResult(intent, -1, fillInIntent, flagsMask, @@ -3751,26 +4111,26 @@ * @see #startActivity * @see #startActivityForResult */ - public boolean startActivityIfNeeded(Intent intent, int requestCode) { + public boolean startActivityIfNeeded(@NonNull Intent intent, int requestCode) { return startActivityIfNeeded(intent, requestCode, null); } /** * A special variation to launch an activity only if a new activity * instance is needed to handle the given Intent. In other words, this is - * just like {@link #startActivityForResult(Intent, int)} except: if you are + * just like {@link #startActivityForResult(Intent, int)} except: if you are * using the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} flag, or - * singleTask or singleTop + * singleTask or singleTop * {@link android.R.styleable#AndroidManifestActivity_launchMode launchMode}, - * and the activity - * that handles <var>intent</var> is the same as your currently running - * activity, then a new instance is not needed. In this case, instead of - * the normal behavior of calling {@link #onNewIntent} this function will - * return and you can handle the Intent yourself. - * + * and the activity + * that handles <var>intent</var> is the same as your currently running + * activity, then a new instance is not needed. In this case, instead of + * the normal behavior of calling {@link #onNewIntent} this function will + * return and you can handle the Intent yourself. + * * <p>This function can only be called from a top-level activity; if it is * called from a child activity, a runtime exception will be thrown. - * + * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits, as described in @@ -3778,14 +4138,15 @@ * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. - * + * * @return If a new activity was launched then true is returned; otherwise * false is returned and you must handle the Intent yourself. - * + * * @see #startActivity * @see #startActivityForResult */ - public boolean startActivityIfNeeded(Intent intent, int requestCode, Bundle options) { + public boolean startActivityIfNeeded(@NonNull Intent intent, int requestCode, + @Nullable Bundle options) { if (mParent == null) { int result = ActivityManager.START_RETURN_INTENT_TO_CALLER; try { @@ -3793,10 +4154,9 @@ intent.prepareToLeaveProcess(); result = ActivityManagerNative.getDefault() .startActivity(mMainThread.getApplicationThread(), getBasePackageName(), - intent, intent.resolveTypeIfNeeded(getContentResolver()), - mToken, mEmbeddedID, requestCode, - ActivityManager.START_FLAG_ONLY_IF_NEEDED, null, null, - options); + intent, intent.resolveTypeIfNeeded(getContentResolver()), mToken, + mEmbeddedID, requestCode, ActivityManager.START_FLAG_ONLY_IF_NEEDED, + null, options); } catch (RemoteException e) { // Empty } @@ -3834,7 +4194,7 @@ * wasn't. In general, if true is returned you will then want to call * finish() on yourself. */ - public boolean startNextMatchingActivity(Intent intent) { + public boolean startNextMatchingActivity(@NonNull Intent intent) { return startNextMatchingActivity(intent, null); } @@ -3843,7 +4203,7 @@ * other activity components. You can use this to hand the Intent off * to the next Activity that can handle it. You typically call this in * {@link #onCreate} with the Intent returned by {@link #getIntent}. - * + * * @param intent The intent to dispatch to the next activity. For * correct behavior, this must be the same as the Intent that started * your own activity; the only changes you can make are to the extras @@ -3851,13 +4211,13 @@ * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. - * + * * @return Returns a boolean indicating whether there was another Activity * to start: true if there was a next activity to start, false if there * wasn't. In general, if true is returned you will then want to call * finish() on yourself. */ - public boolean startNextMatchingActivity(Intent intent, Bundle options) { + public boolean startNextMatchingActivity(@NonNull Intent intent, @Nullable Bundle options) { if (mParent == null) { try { intent.migrateExtraStreamToClipData(); @@ -3887,32 +4247,32 @@ * @see #startActivity * @see #startActivityForResult */ - public void startActivityFromChild(Activity child, Intent intent, + public void startActivityFromChild(@NonNull Activity child, Intent intent, int requestCode) { startActivityFromChild(child, intent, requestCode, null); } /** - * This is called when a child activity of this one calls its + * This is called when a child activity of this one calls its * {@link #startActivity} or {@link #startActivityForResult} method. - * + * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. - * + * * @param child The activity making the call. * @param intent The intent to start. * @param requestCode Reply request code. < 0 if reply is not requested. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. - * + * * @throws android.content.ActivityNotFoundException - * - * @see #startActivity - * @see #startActivityForResult + * + * @see #startActivity + * @see #startActivityForResult */ - public void startActivityFromChild(Activity child, Intent intent, - int requestCode, Bundle options) { + public void startActivityFromChild(@NonNull Activity child, Intent intent, + int requestCode, @Nullable Bundle options) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, child, @@ -3937,33 +4297,36 @@ * @see Fragment#startActivity * @see Fragment#startActivityForResult */ - public void startActivityFromFragment(Fragment fragment, Intent intent, + public void startActivityFromFragment(@NonNull Fragment fragment, Intent intent, int requestCode) { startActivityFromFragment(fragment, intent, requestCode, null); } /** - * This is called when a Fragment in this activity calls its + * This is called when a Fragment in this activity calls its * {@link Fragment#startActivity} or {@link Fragment#startActivityForResult} * method. - * + * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. - * + * * @param fragment The fragment making the call. * @param intent The intent to start. - * @param requestCode Reply request code. < 0 if reply is not requested. + * @param requestCode Reply request code. < 0 if reply is not requested. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. - * + * * @throws android.content.ActivityNotFoundException - * - * @see Fragment#startActivity - * @see Fragment#startActivityForResult + * + * @see Fragment#startActivity + * @see Fragment#startActivityForResult */ - public void startActivityFromFragment(Fragment fragment, Intent intent, - int requestCode, Bundle options) { + public void startActivityFromFragment(@NonNull Fragment fragment, Intent intent, + int requestCode, @Nullable Bundle options) { + if (options != null) { + mActivityTransitionState.startExitOutTransition(this, options); + } Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, fragment, @@ -3995,7 +4358,7 @@ */ public void startIntentSenderFromChild(Activity child, IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, - int extraFlags, Bundle options) + int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException { startIntentSenderForResultInner(intent, requestCode, fillInIntent, flagsMask, flagsValues, child, options); @@ -4025,14 +4388,14 @@ } catch (RemoteException e) { } } - + /** * Call this to set the result that your activity will return to its * caller. - * + * * @param resultCode The result code to propagate back to the originating * activity, often RESULT_CANCELED or RESULT_OK - * + * * @see #RESULT_CANCELED * @see #RESULT_OK * @see #RESULT_FIRST_USER @@ -4061,7 +4424,7 @@ * @param resultCode The result code to propagate back to the originating * activity, often RESULT_CANCELED or RESULT_OK * @param data The data to propagate back to the originating activity. - * + * * @see #RESULT_CANCELED * @see #RESULT_OK * @see #RESULT_FIRST_USER @@ -4079,10 +4442,10 @@ * the data in {@link #setResult setResult()} will be sent to. You can * use this information to validate that the recipient is allowed to * receive the data. - * + * * <p class="note">Note: if the calling activity is not expecting a result (that is it - * did not use the {@link #startActivityForResult} - * form that includes a request code), then the calling package will be + * did not use the {@link #startActivityForResult} + * form that includes a request code), then the calling package will be * null.</p> * * <p class="note">Note: prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, @@ -4090,10 +4453,11 @@ * package was no longer running, it would return null instead of the proper package * name. You can use {@link #getCallingActivity()} and retrieve the package name * from that instead.</p> - * + * * @return The package of the activity that will receive your * reply, or null if none. */ + @Nullable public String getCallingPackage() { try { return ActivityManagerNative.getDefault().getCallingPackage(mToken); @@ -4107,15 +4471,16 @@ * who the data in {@link #setResult setResult()} will be sent to. You * can use this information to validate that the recipient is allowed to * receive the data. - * + * * <p class="note">Note: if the calling activity is not expecting a result (that is it - * did not use the {@link #startActivityForResult} - * form that includes a request code), then the calling package will be - * null. - * + * did not use the {@link #startActivityForResult} + * form that includes a request code), then the calling package will be + * null. + * * @return The ComponentName of the activity that will receive your * reply, or null if none. */ + @Nullable public ComponentName getCallingActivity() { try { return ActivityManagerNative.getDefault().getCallingActivity(mToken); @@ -4130,7 +4495,7 @@ * UI itself, but can't just finish prior to onResume() because it needs * to wait for a service binding or such. Setting this to false allows * you to prevent your UI from being shown during that time. - * + * * <p>The default value for this is taken from the * {@link android.R.attr#windowNoDisplay} attribute of the activity's theme. */ @@ -4143,7 +4508,7 @@ } } } - + void makeVisible() { if (!mWindowAdded) { ViewManager wm = getWindowManager(); @@ -4152,16 +4517,16 @@ } mDecor.setVisibility(View.VISIBLE); } - + /** * Check to see whether this activity is in the process of finishing, * either because you called {@link #finish} on it or someone else * has requested that it finished. This is often used in * {@link #onPause} to determine whether the activity is simply pausing or * completely finishing. - * + * * @return If the activity is finishing, returns true; else returns false. - * + * * @see #finish */ public boolean isFinishing() { @@ -4181,7 +4546,7 @@ * recreated with a new configuration. This is often used in * {@link #onStop} to determine whether the state needs to be cleaned up or will be passed * on to the next instance of the activity via {@link #onRetainNonConfigurationInstance()}. - * + * * @return If the activity is being torn down in order to be recreated with a new configuration, * returns true; else returns false. */ @@ -4206,11 +4571,10 @@ } /** - * Call this when your activity is done and should be closed. The - * ActivityResult is propagated back to whoever launched you via - * onActivityResult(). + * Finishes the current activity and specifies whether to remove the task associated with this + * activity. */ - public void finish() { + private void finish(boolean finishTask) { if (mParent == null) { int resultCode; Intent resultData; @@ -4224,7 +4588,7 @@ resultData.prepareToLeaveProcess(); } if (ActivityManagerNative.getDefault() - .finishActivity(mToken, resultCode, resultData)) { + .finishActivity(mToken, resultCode, resultData, finishTask)) { mFinished = true; } } catch (RemoteException e) { @@ -4236,6 +4600,15 @@ } /** + * Call this when your activity is done and should be closed. The + * ActivityResult is propagated back to whoever launched you via + * onActivityResult(). + */ + public void finish() { + finish(false); + } + + /** * Finish this activity as well as all activities immediately below it * in the current task that have the same affinity. This is typically * used when an application can be launched on to another task (such as @@ -4266,12 +4639,12 @@ } /** - * This is called when a child activity of this one calls its + * This is called when a child activity of this one calls its * {@link #finish} method. The default implementation simply calls * finish() on this activity (the parent), finishing the entire group. - * + * * @param child The activity making the call. - * + * * @see #finish */ public void finishFromChild(Activity child) { @@ -4279,9 +4652,22 @@ } /** + * Reverses the Activity Scene entry Transition and triggers the calling Activity + * to reverse its exit Transition. When the exit Transition completes, + * {@link #finish()} is called. If no entry Transition was used, finish() is called + * immediately and the Activity exit Transition is run. + * @see android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, android.util.Pair[]) + */ + public void finishAfterTransition() { + if (!mActivityTransitionState.startExitBackTransition(this)) { + finish(); + } + } + + /** * Force finish another activity that you had previously started with * {@link #startActivityForResult}. - * + * * @param requestCode The request code of the activity that you had * given to startActivityForResult(). If there are multiple * activities started with this request code, they @@ -4303,12 +4689,12 @@ /** * This is called when a child activity of this one calls its * finishActivity(). - * + * * @param child The activity making the call. * @param requestCode Request code that had been used to start the * activity. */ - public void finishActivityFromChild(Activity child, int requestCode) { + public void finishActivityFromChild(@NonNull Activity child, int requestCode) { try { ActivityManagerNative.getDefault() .finishSubActivity(mToken, child.mEmbeddedID, requestCode); @@ -4318,15 +4704,43 @@ } /** + * Call this when your activity is done and should be closed and the task should be completely + * removed as a part of finishing the Activity. + */ + public void finishAndRemoveTask() { + finish(true); + } + + /** + * Ask that the local app instance of this activity be released to free up its memory. + * This is asking for the activity to be destroyed, but does <b>not</b> finish the activity -- + * a new instance of the activity will later be re-created if needed due to the user + * navigating back to it. + * + * @return Returns true if the activity was in a state that it has started the process + * of destroying its current instance; returns false if for any reason this could not + * be done: it is currently visible to the user, it is already being destroyed, it is + * being finished, it hasn't yet saved its state, etc. + */ + public boolean releaseInstance() { + try { + return ActivityManagerNative.getDefault().releaseActivityInstance(mToken); + } catch (RemoteException e) { + // Empty + } + return false; + } + + /** * Called when an activity you launched exits, giving you the requestCode * you started it with, the resultCode it returned, and any additional * data from it. The <var>resultCode</var> will be * {@link #RESULT_CANCELED} if the activity explicitly returned that, * didn't return any result, or crashed during its operation. - * + * * <p>You will receive this call immediately before onResume() when your * activity is re-starting. - * + * * @param requestCode The integer request code originally supplied to * startActivityForResult(), allowing you to identify who this * result came from. @@ -4334,7 +4748,7 @@ * through its setResult(). * @param data An Intent, which can return result data to the caller * (various data can be attached to Intent "extras"). - * + * * @see #startActivityForResult * @see #createPendingResult * @see #setResult(int) @@ -4343,12 +4757,33 @@ } /** - * Create a new PendingIntent object which you can hand to others - * for them to use to send result data back to your - * {@link #onActivityResult} callback. The created object will be either - * one-shot (becoming invalid after a result is sent back) or multiple - * (allowing any number of results to be sent through it). - * + * Called when an activity you launched with an activity transition exposes this + * Activity through a returning activity transition, giving you the resultCode + * and any additional data from it. This method will only be called if the activity + * set a result code other than {@link #RESULT_CANCELED} and it supports activity + * transitions with {@link Window#FEATURE_ACTIVITY_TRANSITIONS}. + * + * <p>The purpose of this function is to let the called Activity send a hint about + * its state so that this underlying Activity can prepare to be exposed. A call to + * this method does not guarantee that the called Activity has or will be exiting soon. + * It only indicates that it will expose this Activity's Window and it has + * some data to pass to prepare it.</p> + * + * @param resultCode The integer result code returned by the child activity + * through its setResult(). + * @param data An Intent, which can return result data to the caller + * (various data can be attached to Intent "extras"). + */ + public void onActivityReenter(int resultCode, Intent data) { + } + + /** + * Create a new PendingIntent object which you can hand to others + * for them to use to send result data back to your + * {@link #onActivityResult} callback. The created object will be either + * one-shot (becoming invalid after a result is sent back) or multiple + * (allowing any number of results to be sent through it). + * * @param requestCode Private request code for the sender that will be * associated with the result data when it is returned. The sender can not * modify this value, allowing you to identify incoming results. @@ -4361,16 +4796,16 @@ * or any of the flags as supported by * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts * of the intent that can be supplied when the actual send happens. - * + * * @return Returns an existing or new PendingIntent matching the given * parameters. May return null only if * {@link PendingIntent#FLAG_NO_CREATE PendingIntent.FLAG_NO_CREATE} has been * supplied. - * + * * @see PendingIntent */ - public PendingIntent createPendingResult(int requestCode, Intent data, - int flags) { + public PendingIntent createPendingResult(int requestCode, @NonNull Intent data, + @PendingIntent.Flags int flags) { String packageName = getPackageName(); try { data.prepareToLeaveProcess(); @@ -4393,11 +4828,11 @@ * orientation, the screen will immediately be changed (possibly causing * the activity to be restarted). Otherwise, this will be used the next * time the activity is visible. - * + * * @param requestedOrientation An orientation constant as used in * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}. */ - public void setRequestedOrientation(int requestedOrientation) { + public void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) { if (mParent == null) { try { ActivityManagerNative.getDefault().setRequestedOrientation( @@ -4409,16 +4844,17 @@ mParent.setRequestedOrientation(requestedOrientation); } } - + /** * Return the current requested orientation of the activity. This will * either be the orientation requested in its component's manifest, or * the last requested orientation given to * {@link #setRequestedOrientation(int)}. - * + * * @return Returns an orientation constant as used in * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}. */ + @ActivityInfo.ScreenOrientation public int getRequestedOrientation() { if (mParent == null) { try { @@ -4432,11 +4868,11 @@ } return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; } - + /** * Return the identifier of the task this activity is in. This identifier * will remain the same for the lifetime of the activity. - * + * * @return Task identifier, an opaque integer. */ public int getTaskId() { @@ -4451,7 +4887,7 @@ /** * Return whether this activity is the root of a task. The root is the * first activity in a task. - * + * * @return True if this is the root activity, else false. */ public boolean isTaskRoot() { @@ -4466,11 +4902,11 @@ /** * Move the task containing this activity to the back of the activity * stack. The activity's order within the task is unchanged. - * + * * @param nonRoot If false then this only works if the activity is the root * of a task; if true it will work for any activity in * a task. - * + * * @return If the task was moved (or it was already at the * back) true is returned, else false. */ @@ -4487,9 +4923,10 @@ /** * Returns class name for this activity with the package prefix removed. * This is the default name used to read and write settings. - * + * * @return The local class name. */ + @NonNull public String getLocalClassName() { final String pkg = getPackageName(); final String cls = mComponent.getClassName(); @@ -4500,10 +4937,10 @@ } return cls.substring(packageLen+1); } - + /** * Returns complete component name of this activity. - * + * * @return Returns the complete component name for this activity */ public ComponentName getComponentName() @@ -4516,9 +4953,9 @@ * that are private to this activity. This simply calls the underlying * {@link #getSharedPreferences(String, int)} method by passing in this activity's * class name as the preferences name. - * - * @param mode Operating mode. Use {@link #MODE_PRIVATE} for the default - * operation, {@link #MODE_WORLD_READABLE} and + * + * @param mode Operating mode. Use {@link #MODE_PRIVATE} for the default + * operation, {@link #MODE_WORLD_READABLE} and * {@link #MODE_WORLD_WRITEABLE} to control permissions. * * @return Returns the single SharedPreferences instance that can be used @@ -4527,17 +4964,17 @@ public SharedPreferences getPreferences(int mode) { return getSharedPreferences(getLocalClassName(), mode); } - + private void ensureSearchManager() { if (mSearchManager != null) { return; } - + mSearchManager = new SearchManager(this, null); } - + @Override - public Object getSystemService(String name) { + public Object getSystemService(@ServiceName @NonNull String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); @@ -4577,6 +5014,17 @@ setTitle(getText(titleId)); } + /** + * Change the color of the title associated with this activity. + * <p> + * This method is deprecated starting in API Level 11 and replaced by action + * bar styles. For information on styling the Action Bar, read the <a + * href="{@docRoot} guide/topics/ui/actionbar.html">Action Bar</a> developer + * guide. + * + * @deprecated Use action bar styles instead. + */ + @Deprecated public void setTitleColor(int textColor) { mTitleColor = textColor; onTitleChanged(mTitle, textColor); @@ -4599,6 +5047,9 @@ win.setTitleColor(color); } } + if (mActionBar != null) { + mActionBar.setWindowTitle(title); + } } } @@ -4606,11 +5057,40 @@ } /** + * Sets information describing the task with this activity for presentation inside the Recents + * System UI. When {@link ActivityManager#getRecentTasks} is called, the activities of each task + * are traversed in order from the topmost activity to the bottommost. The traversal continues + * for each property until a suitable value is found. For each task the taskDescription will be + * returned in {@link android.app.ActivityManager.TaskDescription}. + * + * @see ActivityManager#getRecentTasks + * @see android.app.ActivityManager.TaskDescription + * + * @param taskDescription The TaskDescription properties that describe the task with this activity + */ + public void setTaskDescription(ActivityManager.TaskDescription taskDescription) { + ActivityManager.TaskDescription td; + // Scale the icon down to something reasonable if it is provided + if (taskDescription.getIconFilename() == null && taskDescription.getIcon() != null) { + final int size = ActivityManager.getLauncherLargeIconSizeInner(this); + final Bitmap icon = Bitmap.createScaledBitmap(taskDescription.getIcon(), size, size, true); + td = new ActivityManager.TaskDescription(taskDescription.getLabel(), icon, + taskDescription.getPrimaryColor()); + } else { + td = taskDescription; + } + try { + ActivityManagerNative.getDefault().setTaskDescription(mToken, td); + } catch (RemoteException e) { + } + } + + /** * Sets the visibility of the progress bar in the title. * <p> * In order for the progress bar to be shown, the feature must be requested * via {@link #requestWindowFeature(int)}. - * + * * @param visible Whether to show the progress bars in the title. */ public final void setProgressBarVisibility(boolean visible) { @@ -4630,27 +5110,28 @@ getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF); } - + /** * Sets whether the horizontal progress bar in the title should be indeterminate (the circular * is always indeterminate). * <p> * In order for the progress bar to be shown, the feature must be requested * via {@link #requestWindowFeature(int)}. - * + * * @param indeterminate Whether the horizontal progress bar should be indeterminate. */ public final void setProgressBarIndeterminate(boolean indeterminate) { getWindow().setFeatureInt(Window.FEATURE_PROGRESS, - indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF); + indeterminate ? Window.PROGRESS_INDETERMINATE_ON + : Window.PROGRESS_INDETERMINATE_OFF); } - + /** * Sets the progress for the progress bars in the title. * <p> * In order for the progress bar to be shown, the feature must be requested * via {@link #requestWindowFeature(int)}. - * + * * @param progress The progress for the progress bar. Valid ranges are from * 0 to 10000 (both inclusive). If 10000 is given, the progress * bar will be completely filled and will fade out. @@ -4658,7 +5139,7 @@ public final void setProgress(int progress) { getWindow().setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START); } - + /** * Sets the secondary progress for the progress bar in the title. This * progress is drawn between the primary progress (set via @@ -4668,7 +5149,7 @@ * <p> * In order for the progress bar to be shown, the feature must be requested * via {@link #requestWindowFeature(int)}. - * + * * @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from * 0 to 10000 (both inclusive). */ @@ -4682,16 +5163,16 @@ * volume controls. * <p> * The suggested audio stream will be tied to the window of this Activity. - * If the Activity is switched, the stream set here is no longer the - * suggested stream. The client does not need to save and restore the old - * suggested stream value in onPause and onResume. - * + * Volume requests which are received while the Activity is in the + * foreground will affect this stream. + * <p> + * It is not guaranteed that the hardware volume controls will always change + * this stream's volume (for example, if a call is in progress, its stream's + * volume may be changed instead). To reset back to the default, use + * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}. + * * @param streamType The type of the audio stream whose volume should be - * changed by the hardware volume controls. It is not guaranteed that - * the hardware volume controls will always change this stream's - * volume (for example, if a call is in progress, its stream's volume - * may be changed instead). To reset back to the default, use - * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}. + * changed by the hardware volume controls. */ public final void setVolumeControlStream(int streamType) { getWindow().setVolumeControlStream(streamType); @@ -4699,8 +5180,8 @@ /** * Gets the suggested audio stream whose volume should be changed by the - * harwdare volume controls. - * + * hardware volume controls. + * * @return The suggested audio stream type whose volume should be changed by * the hardware volume controls. * @see #setVolumeControlStream(int) @@ -4708,7 +5189,40 @@ public final int getVolumeControlStream() { return getWindow().getVolumeControlStream(); } - + + /** + * Sets a {@link MediaController} to send media keys and volume changes to. + * <p> + * The controller will be tied to the window of this Activity. Media key and + * volume events which are received while the Activity is in the foreground + * will be forwarded to the controller and used to invoke transport controls + * or adjust the volume. This may be used instead of or in addition to + * {@link #setVolumeControlStream} to affect a specific session instead of a + * specific stream. + * <p> + * It is not guaranteed that the hardware volume controls will always change + * this session's volume (for example, if a call is in progress, its + * stream's volume may be changed instead). To reset back to the default use + * null as the controller. + * + * @param controller The controller for the session which should receive + * media keys and volume changes. + */ + public final void setMediaController(MediaController controller) { + getWindow().setMediaController(controller); + } + + /** + * Gets the controller which should be receiving media key and volume events + * while this activity is in the foreground. + * + * @return The controller which should receive events. + * @see #setMediaController(android.media.session.MediaController) + */ + public final MediaController getMediaController() { + return getWindow().getMediaController(); + } + /** * Runs the specified action on the UI thread. If the current thread is the UI * thread, then the action is executed immediately. If the current thread is @@ -4735,6 +5249,7 @@ * @see android.view.LayoutInflater#createView * @see android.view.Window#getLayoutInflater */ + @Nullable public View onCreateView(String name, Context context, AttributeSet attrs) { return null; } @@ -4753,79 +5268,8 @@ if (!"fragment".equals(name)) { return onCreateView(name, context, attrs); } - - String fname = attrs.getAttributeValue(null, "class"); - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment); - if (fname == null) { - fname = a.getString(com.android.internal.R.styleable.Fragment_name); - } - int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID); - String tag = a.getString(com.android.internal.R.styleable.Fragment_tag); - a.recycle(); - - int containerId = parent != null ? parent.getId() : 0; - if (containerId == View.NO_ID && id == View.NO_ID && tag == null) { - throw new IllegalArgumentException(attrs.getPositionDescription() - + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname); - } - // If we restored from a previous state, we may already have - // instantiated this fragment from the state and should use - // that instance instead of making a new one. - Fragment fragment = id != View.NO_ID ? mFragments.findFragmentById(id) : null; - if (fragment == null && tag != null) { - fragment = mFragments.findFragmentByTag(tag); - } - if (fragment == null && containerId != View.NO_ID) { - fragment = mFragments.findFragmentById(containerId); - } - - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x" - + Integer.toHexString(id) + " fname=" + fname - + " existing=" + fragment); - if (fragment == null) { - fragment = Fragment.instantiate(this, fname); - fragment.mFromLayout = true; - fragment.mFragmentId = id != 0 ? id : containerId; - fragment.mContainerId = containerId; - fragment.mTag = tag; - fragment.mInLayout = true; - fragment.mFragmentManager = mFragments; - fragment.onInflate(this, attrs, fragment.mSavedFragmentState); - mFragments.addFragment(fragment, true); - - } else if (fragment.mInLayout) { - // A fragment already exists and it is not one we restored from - // previous state. - throw new IllegalArgumentException(attrs.getPositionDescription() - + ": Duplicate id 0x" + Integer.toHexString(id) - + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId) - + " with another fragment for " + fname); - } else { - // This fragment was retained from a previous instance; get it - // going now. - fragment.mInLayout = true; - // If this fragment is newly instantiated (either right now, or - // from last saved state), then give it the attributes to - // initialize itself. - if (!fragment.mRetaining) { - fragment.onInflate(this, attrs, fragment.mSavedFragmentState); - } - mFragments.moveToState(fragment); - } - - if (fragment.mView == null) { - throw new IllegalStateException("Fragment " + fname - + " did not create a view."); - } - if (id != 0) { - fragment.mView.setId(id); - } - if (fragment.mView.getTag() == null) { - fragment.mView.setTag(tag); - } - return fragment.mView; + return mFragments.onCreateView(parent, name, context, attrs); } /** @@ -4896,6 +5340,21 @@ } /** + * Indication of whether this is the highest level activity in this task. Can be used to + * determine whether an activity launched by this activity was placed in the same task or + * another task. + * + * @return true if this is the topmost, non-finishing activity in its task. + */ + private boolean isTopOfTask() { + try { + return ActivityManagerNative.getDefault().isTopOfTask(mToken); + } catch (RemoteException e) { + return false; + } + } + + /** * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a * fullscreen opaque Activity. * <p> @@ -4905,11 +5364,13 @@ * This call has no effect on non-translucent activities or on activities with the * {@link android.R.attr#windowIsFloating} attribute. * - * @see #convertToTranslucent(TranslucentConversionListener) + * @see #convertToTranslucent(android.app.Activity.TranslucentConversionListener, + * ActivityOptions) * @see TranslucentConversionListener * * @hide */ + @SystemApi public void convertFromTranslucent() { try { mTranslucentCallback = null; @@ -4936,20 +5397,36 @@ * * @param callback the method to call when all visible Activities behind this one have been * drawn and it is safe to make this Activity translucent again. + * @param options activity options delivered to the activity below this one. The options + * are retrieved using {@link #getActivityOptions}. + * @return <code>true</code> if Window was opaque and will become translucent or + * <code>false</code> if window was translucent and no change needed to be made. * * @see #convertFromTranslucent() * @see TranslucentConversionListener * * @hide */ - public void convertToTranslucent(TranslucentConversionListener callback) { + @SystemApi + public boolean convertToTranslucent(TranslucentConversionListener callback, + ActivityOptions options) { + boolean drawComplete; try { mTranslucentCallback = callback; mChangeCanvasToTranslucent = - ActivityManagerNative.getDefault().convertToTranslucent(mToken); + ActivityManagerNative.getDefault().convertToTranslucent(mToken, options); + WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false); + drawComplete = true; } catch (RemoteException e) { - // pass + // Make callback return as though it timed out. + mChangeCanvasToTranslucent = false; + drawComplete = false; } + if (!mChangeCanvasToTranslucent && mTranslucentCallback != null) { + // Window is already translucent. + mTranslucentCallback.onTranslucentConversionComplete(drawComplete); + } + return mChangeCanvasToTranslucent; } /** @hide */ @@ -4963,6 +5440,141 @@ } } + /** @hide */ + public void onNewActivityOptions(ActivityOptions options) { + mActivityTransitionState.setEnterActivityOptions(this, options); + if (!mStopped) { + mActivityTransitionState.enterReady(this); + } + } + + /** + * Retrieve the ActivityOptions passed in from the launching activity or passed back + * from an activity launched by this activity in its call to {@link + * #convertToTranslucent(TranslucentConversionListener, ActivityOptions)} + * + * @return The ActivityOptions passed to {@link #convertToTranslucent}. + * @hide + */ + ActivityOptions getActivityOptions() { + try { + return ActivityManagerNative.getDefault().getActivityOptions(mToken); + } catch (RemoteException e) { + } + return null; + } + + /** + * Activities that want to remain visible behind a translucent activity above them must call + * this method anytime between the start of {@link #onResume()} and the return from + * {@link #onPause()}. If this call is successful then the activity will remain visible after + * {@link #onPause()} is called, and is allowed to continue playing media in the background. + * + * <p>The actions of this call are reset each time that this activity is brought to the + * front. That is, every time {@link #onResume()} is called the activity will be assumed + * to not have requested visible behind. Therefore, if you want this activity to continue to + * be visible in the background you must call this method again. + * + * <p>Only fullscreen opaque activities may make this call. I.e. this call is a nop + * for dialog and translucent activities. + * + * <p>Under all circumstances, the activity must stop playing and release resources prior to or + * within a call to {@link #onVisibleBehindCanceled()} or if this call returns false. + * + * <p>False will be returned any time this method is called between the return of onPause and + * the next call to onResume. + * + * @param visible true to notify the system that the activity wishes to be visible behind other + * translucent activities, false to indicate otherwise. Resources must be + * released when passing false to this method. + * @return the resulting visibiity state. If true the activity will remain visible beyond + * {@link #onPause()} if the next activity is translucent or not fullscreen. If false + * then the activity may not count on being visible behind other translucent activities, + * and must stop any media playback and release resources. + * Returning false may occur in lieu of a call to {@link #onVisibleBehindCanceled()} so + * the return value must be checked. + * + * @see #onVisibleBehindCanceled() + * @see #onBackgroundVisibleBehindChanged(boolean) + */ + public boolean requestVisibleBehind(boolean visible) { + if (!mResumed) { + // Do not permit paused or stopped activities to do this. + visible = false; + } + try { + mVisibleBehind = ActivityManagerNative.getDefault() + .requestVisibleBehind(mToken, visible) && visible; + } catch (RemoteException e) { + mVisibleBehind = false; + } + return mVisibleBehind; + } + + /** + * Called when a translucent activity over this activity is becoming opaque or another + * activity is being launched. Activities that override this method must call + * <code>super.onVisibleBehindCanceled()</code> or a SuperNotCalledException will be thrown. + * + * <p>When this method is called the activity has 500 msec to release any resources it may be + * using while visible in the background. + * If the activity has not returned from this method in 500 msec the system will destroy + * the activity and kill the process in order to recover the resources for another + * process. Otherwise {@link #onStop()} will be called following return. + * + * @see #requestVisibleBehind(boolean) + * @see #onBackgroundVisibleBehindChanged(boolean) + */ + public void onVisibleBehindCanceled() { + mCalled = true; + } + + /** + * Translucent activities may call this to determine if there is an activity below them that + * is currently set to be visible in the background. + * + * @return true if an activity below is set to visible according to the most recent call to + * {@link #requestVisibleBehind(boolean)}, false otherwise. + * + * @see #requestVisibleBehind(boolean) + * @see #onVisibleBehindCanceled() + * @see #onBackgroundVisibleBehindChanged(boolean) + * @hide + */ + @SystemApi + public boolean isBackgroundVisibleBehind() { + try { + return ActivityManagerNative.getDefault().isBackgroundVisibleBehind(mToken); + } catch (RemoteException e) { + } + return false; + } + + /** + * The topmost foreground activity will receive this call when the background visibility state + * of the activity below it changes. + * + * This call may be a consequence of {@link #requestVisibleBehind(boolean)} or might be + * due to a background activity finishing itself. + * + * @param visible true if a background activity is visible, false otherwise. + * + * @see #requestVisibleBehind(boolean) + * @see #onVisibleBehindCanceled() + * @hide + */ + @SystemApi + public void onBackgroundVisibleBehindChanged(boolean visible) { + } + + /** + * Activities cannot draw during the period that their windows are animating in. In order + * to know when it is safe to begin drawing they can override this method which will be + * called when the entering animation has completed. + */ + public void onEnterAnimationComplete() { + } + /** * Adjust the current immersive mode setting. * @@ -4993,6 +5605,7 @@ * * @see ActionMode */ + @Nullable public ActionMode startActionMode(ActionMode.Callback callback) { return mWindow.getDecorView().startActionMode(callback); } @@ -5008,9 +5621,10 @@ * @return The new action mode, or <code>null</code> if the activity does not want to * provide special handling for this action mode. (It will be handled by the system.) */ + @Nullable @Override public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) { - initActionBar(); + initWindowDecorActionBar(); if (mActionBar != null) { return mActionBar.startActionMode(callback); } @@ -5061,8 +5675,8 @@ if (info.taskAffinity == null) { return false; } - return !ActivityManagerNative.getDefault() - .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity); + return ActivityManagerNative.getDefault() + .shouldUpRecreateTask(mToken, info.taskAffinity); } catch (RemoteException e) { return false; } catch (NameNotFoundException e) { @@ -5151,6 +5765,7 @@ * @return a new Intent targeting the defined parent of this activity or null if * there is no valid parent. */ + @Nullable public Intent getParentActivityIntent() { final String parentName = mActivityInfo.parentActivityName; if (TextUtils.isEmpty(parentName)) { @@ -5173,30 +5788,81 @@ } } + /** + * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, + * android.view.View, String)} was used to start an Activity, <var>callback</var> + * will be called to handle shared elements on the <i>launched</i> Activity. This requires + * {@link Window#FEATURE_ACTIVITY_TRANSITIONS}. + * + * @param callback Used to manipulate shared element transitions on the launched Activity. + */ + public void setEnterSharedElementCallback(SharedElementCallback callback) { + if (callback == null) { + callback = SharedElementCallback.NULL_CALLBACK; + } + mEnterTransitionListener = callback; + } + + /** + * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, + * android.view.View, String)} was used to start an Activity, <var>callback</var> + * will be called to handle shared elements on the <i>launching</i> Activity. Most + * calls will only come when returning from the started Activity. + * This requires {@link Window#FEATURE_ACTIVITY_TRANSITIONS}. + * + * @param callback Used to manipulate shared element transitions on the launching Activity. + */ + public void setExitSharedElementCallback(SharedElementCallback callback) { + if (callback == null) { + callback = SharedElementCallback.NULL_CALLBACK; + } + mExitTransitionListener = callback; + } + + /** + * Postpone the entering activity transition when Activity was started with + * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, + * android.util.Pair[])}. + * <p>This method gives the Activity the ability to delay starting the entering and + * shared element transitions until all data is loaded. Until then, the Activity won't + * draw into its window, leaving the window transparent. This may also cause the + * returning animation to be delayed until data is ready. This method should be + * called in {@link #onCreate(android.os.Bundle)} or in + * {@link #onActivityReenter(int, android.content.Intent)}. + * {@link #startPostponedEnterTransition()} must be called to allow the Activity to + * start the transitions. If the Activity did not use + * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, + * android.util.Pair[])}, then this method does nothing.</p> + */ + public void postponeEnterTransition() { + mActivityTransitionState.postponeEnterTransition(); + } + + /** + * Begin postponed transitions after {@link #postponeEnterTransition()} was called. + * If postponeEnterTransition() was called, you must call startPostponedEnterTransition() + * to have your Activity start drawing. + */ + public void startPostponedEnterTransition() { + mActivityTransitionState.startPostponedEnterTransition(); + } + // ------------------ Internal API ------------------ - + final void setParent(Activity parent) { mParent = parent; } - final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, - Application application, Intent intent, ActivityInfo info, CharSequence title, - Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, - Configuration config) { - attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id, - lastNonConfigurationInstances, config); - } - final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, - Configuration config) { + Configuration config, IVoiceInteractor voiceInteractor) { attachBaseContext(context); mFragments.attachActivity(this, mContainer, null); - + mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); @@ -5208,7 +5874,7 @@ mWindow.setUiOptions(info.uiOptions); } mUiThread = Thread.currentThread(); - + mMainThread = aThread; mInstrumentation = instr; mToken = token; @@ -5221,6 +5887,14 @@ mParent = parent; mEmbeddedID = id; mLastNonConfigurationInstances = lastNonConfigurationInstances; + if (voiceInteractor != null) { + if (lastNonConfigurationInstances != null) { + mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor; + } else { + mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this, + Looper.myLooper()); + } + } mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), @@ -5238,14 +5912,27 @@ return mParent != null ? mParent.getActivityToken() : mToken; } - final void performCreate(Bundle icicle) { - onCreate(icicle); + final void performCreateCommon() { mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, false); mFragments.dispatchActivityCreated(); + mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); } - + + final void performCreate(Bundle icicle) { + onCreate(icicle); + mActivityTransitionState.readState(icicle); + performCreateCommon(); + } + + final void performCreate(Bundle icicle, PersistableBundle persistentState) { + onCreate(icicle, persistentState); + mActivityTransitionState.readState(icicle); + performCreateCommon(); + } + final void performStart() { + mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); mFragments.noteStateNotSaved(); mCalled = false; mFragments.execPendingActions(); @@ -5268,8 +5955,9 @@ lm.doReportStart(); } } + mActivityTransitionState.enterReady(this); } - + final void performRestart() { mFragments.noteStateNotSaved(); @@ -5308,14 +5996,14 @@ performStart(); } } - + final void performResume() { performRestart(); - + mFragments.execPendingActions(); - + mLastNonConfigurationInstances = null; - + mCalled = false; // mResumed is set by the instrumentation mInstrumentation.callActivityOnResume(this); @@ -5327,10 +6015,10 @@ // Now really resume, and install the current status bar and menu. mCalled = false; - + mFragments.dispatchResume(); mFragments.execPendingActions(); - + onPostResume(); if (!mCalled) { throw new SuperNotCalledException( @@ -5353,12 +6041,12 @@ } mResumed = false; } - + final void performUserLeaving() { onUserInteraction(); onUserLeaveHint(); } - + final void performStop() { mDoReportFullyDrawn = false; if (mLoadersStarted) { @@ -5371,7 +6059,7 @@ } } } - + if (!mStopped) { if (mWindow != null) { mWindow.closeAllPanels(); @@ -5380,9 +6068,9 @@ if (mToken != null && mParent == null) { WindowManagerGlobal.getInstance().setStoppedState(mToken, true); } - + mFragments.dispatchStop(); - + mCalled = false; mInstrumentation.callActivityOnStop(this); if (!mCalled) { @@ -5390,7 +6078,7 @@ "Activity " + mComponent.toShortString() + " did not call through to super.onStop()"); } - + synchronized (mManagedCursors) { final int N = mManagedCursors.size(); for (int i=0; i<N; i++) { @@ -5401,7 +6089,7 @@ } } } - + mStopped = true; } mResumed = false; @@ -5415,8 +6103,11 @@ if (mLoaderManager != null) { mLoaderManager.doDestroy(); } + if (mVoiceInteractor != null) { + mVoiceInteractor.detachActivity(); + } } - + /** * @hide */ @@ -5424,7 +6115,7 @@ return mResumed; } - void dispatchActivityResult(String who, int requestCode, + void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data) { if (false) Log.v( TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode @@ -5441,14 +6132,56 @@ } /** + * Request to put this Activity in a mode where the user is locked to the + * current task. + * + * This will prevent the user from launching other apps, going to settings, + * or reaching the home screen. + * + * If {@link DevicePolicyManager#isLockTaskPermitted(String)} returns true + * for this component then the app will go directly into Lock Task mode. The user + * will not be able to exit this mode until {@link Activity#stopLockTask()} is called. + * + * If {@link DevicePolicyManager#isLockTaskPermitted(String)} returns false + * then the system will prompt the user with a dialog requesting permission to enter + * this mode. When entered through this method the user can exit at any time through + * an action described by the request dialog. Calling stopLockTask will also exit the + * mode. + */ + public void startLockTask() { + try { + ActivityManagerNative.getDefault().startLockTaskMode(mToken); + } catch (RemoteException e) { + } + } + + /** + * Allow the user to switch away from the current task. + * + * Called to end the mode started by {@link Activity#startLockTask}. This + * can only be called by activities that have successfully called + * startLockTask previously. + * + * This will allow the user to exit this app and move onto other activities. + */ + public void stopLockTask() { + try { + ActivityManagerNative.getDefault().stopLockTaskMode(); + } catch (RemoteException e) { + } + } + + /** * Interface for informing a translucent {@link Activity} once all visible activities below it * have completed drawing. This is necessary only after an {@link Activity} has been made * opaque using {@link Activity#convertFromTranslucent()} and before it has been drawn * translucent again following a call to {@link - * Activity#convertToTranslucent(TranslucentConversionListener)}. + * Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener, + * ActivityOptions)} * * @hide */ + @SystemApi public interface TranslucentConversionListener { /** * Callback made following {@link Activity#convertToTranslucent} once all visible Activities @@ -5459,7 +6192,7 @@ * occurred waiting for the Activity to complete drawing. * * @see Activity#convertFromTranslucent() - * @see Activity#convertToTranslucent(TranslucentConversionListener) + * @see Activity#convertToTranslucent(TranslucentConversionListener, ActivityOptions) */ public void onTranslucentConversionComplete(boolean drawComplete); }
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl new file mode 100644 index 0000000..92350da --- /dev/null +++ b/core/java/android/app/ActivityManager.aidl
@@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014, 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; + +parcelable ActivityManager.RecentTaskInfo;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index c877cd3..cd6088f 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java
@@ -16,11 +16,17 @@ package android.app; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Point; import android.os.BatteryStats; import android.os.IBinder; -import com.android.internal.app.IUsageStats; +import android.os.ParcelFileDescriptor; + import com.android.internal.app.ProcessStats; -import com.android.internal.os.PkgUsageStats; import com.android.internal.os.TransferPipe; import com.android.internal.util.FastPrintWriter; @@ -34,6 +40,7 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; import android.os.Debug; @@ -47,15 +54,16 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.DisplayMetrics; -import android.util.Log; +import android.util.Size; import android.util.Slog; +import org.xmlpull.v1.XmlSerializer; import java.io.FileDescriptor; import java.io.FileOutputStream; +import java.io.IOException; import java.io.PrintWriter; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * Interact with the overall activities running in the system. @@ -64,6 +72,8 @@ private static String TAG = "ActivityManager"; private static boolean localLOGV = false; + private static int gMaxRecentTasks = -1; + private final Context mContext; private final Handler mHandler; @@ -76,6 +86,13 @@ public static final String META_HOME_ALTERNATE = "android.app.home.alternate"; /** + * Result for IActivityManager.startActivity: trying to start an activity under voice + * control when that activity does not support the VOICE category. + * @hide + */ + public static final int START_NOT_VOICE_COMPATIBLE = -7; + + /** * Result for IActivityManager.startActivity: an error where the * start had to be canceled. * @hide @@ -155,6 +172,13 @@ public static final int START_SWITCHES_CANCELED = 4; /** + * Result for IActivityManaqer.startActivity: a new activity was attempted to be started + * while in Lock Task Mode. + * @hide + */ + public static final int START_RETURN_LOCK_TASK_MODE_VIOLATION = 5; + + /** * Flag for IActivityManaqer.startActivity: do special start mode where * a new activity is launched only if it is needed. * @hide @@ -176,13 +200,6 @@ public static final int START_FLAG_OPENGL_TRACES = 1<<2; /** - * Flag for IActivityManaqer.startActivity: if the app is being - * launched for profiling, automatically stop the profiler once done. - * @hide - */ - public static final int START_FLAG_AUTO_STOP_PROFILER = 1<<3; - - /** * Result for IActivityManaqer.broadcastIntent: success! * @hide */ @@ -282,6 +299,8 @@ /** @hide Process is being cached for later use and is empty. */ public static final int PROCESS_STATE_CACHED_EMPTY = 13; + Point mAppTaskThumbnailSize; + /*package*/ ActivityManager(Context context, Handler handler) { mContext = context; mHandler = handler; @@ -430,7 +449,7 @@ // Really brain dead right now -- just take this from the configured // vm heap size, and assume it is in megabytes and thus ends with "m". String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m"); - return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1)); + return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length() - 1)); } /** @@ -461,6 +480,274 @@ } /** + * Return the maximum number of recents entries that we will maintain and show. + * @hide + */ + static public int getMaxRecentTasksStatic() { + if (gMaxRecentTasks < 0) { + return gMaxRecentTasks = isLowRamDeviceStatic() ? 50 : 100; + } + return gMaxRecentTasks; + } + + /** + * Return the default limit on the number of recents that an app can make. + * @hide + */ + static public int getDefaultAppRecentsLimitStatic() { + return getMaxRecentTasksStatic() / 6; + } + + /** + * Return the maximum limit on the number of recents that an app can make. + * @hide + */ + static public int getMaxAppRecentsLimitStatic() { + return getMaxRecentTasksStatic() / 2; + } + + /** + * Information you can set and retrieve about the current activity within the recent task list. + */ + public static class TaskDescription implements Parcelable { + /** @hide */ + public static final String ATTR_TASKDESCRIPTION_PREFIX = "task_description_"; + private static final String ATTR_TASKDESCRIPTIONLABEL = + ATTR_TASKDESCRIPTION_PREFIX + "label"; + private static final String ATTR_TASKDESCRIPTIONCOLOR = + ATTR_TASKDESCRIPTION_PREFIX + "color"; + private static final String ATTR_TASKDESCRIPTIONICONFILENAME = + ATTR_TASKDESCRIPTION_PREFIX + "icon_filename"; + + private String mLabel; + private Bitmap mIcon; + private String mIconFilename; + private int mColorPrimary; + + /** + * Creates the TaskDescription to the specified values. + * + * @param label A label and description of the current state of this task. + * @param icon An icon that represents the current state of this task. + * @param colorPrimary A color to override the theme's primary color. This color must be opaque. + */ + public TaskDescription(String label, Bitmap icon, int colorPrimary) { + if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) { + throw new RuntimeException("A TaskDescription's primary color should be opaque"); + } + + mLabel = label; + mIcon = icon; + mColorPrimary = colorPrimary; + } + + /** @hide */ + public TaskDescription(String label, int colorPrimary, String iconFilename) { + this(label, null, colorPrimary); + mIconFilename = iconFilename; + } + + /** + * Creates the TaskDescription to the specified values. + * + * @param label A label and description of the current state of this activity. + * @param icon An icon that represents the current state of this activity. + */ + public TaskDescription(String label, Bitmap icon) { + this(label, icon, 0); + } + + /** + * Creates the TaskDescription to the specified values. + * + * @param label A label and description of the current state of this activity. + */ + public TaskDescription(String label) { + this(label, null, 0); + } + + /** + * Creates an empty TaskDescription. + */ + public TaskDescription() { + this(null, null, 0); + } + + /** + * Creates a copy of another TaskDescription. + */ + public TaskDescription(TaskDescription td) { + mLabel = td.mLabel; + mIcon = td.mIcon; + mColorPrimary = td.mColorPrimary; + mIconFilename = td.mIconFilename; + } + + private TaskDescription(Parcel source) { + readFromParcel(source); + } + + /** + * Sets the label for this task description. + * @hide + */ + public void setLabel(String label) { + mLabel = label; + } + + /** + * Sets the primary color for this task description. + * @hide + */ + public void setPrimaryColor(int primaryColor) { + // Ensure that the given color is valid + if ((primaryColor != 0) && (Color.alpha(primaryColor) != 255)) { + throw new RuntimeException("A TaskDescription's primary color should be opaque"); + } + mColorPrimary = primaryColor; + } + + /** + * Sets the icon for this task description. + * @hide + */ + public void setIcon(Bitmap icon) { + mIcon = icon; + } + + /** + * Moves the icon bitmap reference from an actual Bitmap to a file containing the + * bitmap. + * @hide + */ + public void setIconFilename(String iconFilename) { + mIconFilename = iconFilename; + mIcon = null; + } + + /** + * @return The label and description of the current state of this task. + */ + public String getLabel() { + return mLabel; + } + + /** + * @return The icon that represents the current state of this task. + */ + public Bitmap getIcon() { + if (mIcon != null) { + return mIcon; + } + return loadTaskDescriptionIcon(mIconFilename); + } + + /** @hide */ + public String getIconFilename() { + return mIconFilename; + } + + /** @hide */ + public Bitmap getInMemoryIcon() { + return mIcon; + } + + /** @hide */ + public static Bitmap loadTaskDescriptionIcon(String iconFilename) { + if (iconFilename != null) { + try { + return ActivityManagerNative.getDefault(). + getTaskDescriptionIcon(iconFilename); + } catch (RemoteException e) { + } + } + return null; + } + + /** + * @return The color override on the theme's primary color. + */ + public int getPrimaryColor() { + return mColorPrimary; + } + + /** @hide */ + public void saveToXml(XmlSerializer out) throws IOException { + if (mLabel != null) { + out.attribute(null, ATTR_TASKDESCRIPTIONLABEL, mLabel); + } + if (mColorPrimary != 0) { + out.attribute(null, ATTR_TASKDESCRIPTIONCOLOR, Integer.toHexString(mColorPrimary)); + } + if (mIconFilename != null) { + out.attribute(null, ATTR_TASKDESCRIPTIONICONFILENAME, mIconFilename); + } + } + + /** @hide */ + public void restoreFromXml(String attrName, String attrValue) { + if (ATTR_TASKDESCRIPTIONLABEL.equals(attrName)) { + setLabel(attrValue); + } else if (ATTR_TASKDESCRIPTIONCOLOR.equals(attrName)) { + setPrimaryColor((int) Long.parseLong(attrValue, 16)); + } else if (ATTR_TASKDESCRIPTIONICONFILENAME.equals(attrName)) { + setIconFilename(attrValue); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + if (mLabel == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + dest.writeString(mLabel); + } + if (mIcon == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + mIcon.writeToParcel(dest, 0); + } + dest.writeInt(mColorPrimary); + if (mIconFilename == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + dest.writeString(mIconFilename); + } + } + + public void readFromParcel(Parcel source) { + mLabel = source.readInt() > 0 ? source.readString() : null; + mIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null; + mColorPrimary = source.readInt(); + mIconFilename = source.readInt() > 0 ? source.readString() : null; + } + + public static final Creator<TaskDescription> CREATOR + = new Creator<TaskDescription>() { + public TaskDescription createFromParcel(Parcel source) { + return new TaskDescription(source); + } + public TaskDescription[] newArray(int size) { + return new TaskDescription[size]; + } + }; + + @Override + public String toString() { + return "TaskDescription Label: " + mLabel + " Icon: " + mIcon + + " colorPrimary: " + mColorPrimary; + } + } + + /** * Information you can retrieve about tasks that the user has most recently * started or visited. */ @@ -502,6 +789,42 @@ */ public int stackId; + /** + * The id of the user the task was running as. + * @hide + */ + public int userId; + + /** + * The first time this task was active. + * @hide + */ + public long firstActiveTime; + + /** + * The last time this task was active. + * @hide + */ + public long lastActiveTime; + + /** + * The recent activity values for the highest activity in the stack to have set the values. + * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}. + */ + public TaskDescription taskDescription; + + /** + * Task affiliation for grouping with other tasks. + */ + public int affiliatedTaskId; + + /** + * Task affiliation color of the source task with the affiliated task id. + * + * @hide + */ + public int affiliatedTaskColor; + public RecentTaskInfo() { } @@ -523,20 +846,34 @@ ComponentName.writeToParcel(origActivity, dest); TextUtils.writeToParcel(description, dest, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + if (taskDescription != null) { + dest.writeInt(1); + taskDescription.writeToParcel(dest, 0); + } else { + dest.writeInt(0); + } dest.writeInt(stackId); + dest.writeInt(userId); + dest.writeLong(firstActiveTime); + dest.writeLong(lastActiveTime); + dest.writeInt(affiliatedTaskId); + dest.writeInt(affiliatedTaskColor); } public void readFromParcel(Parcel source) { id = source.readInt(); persistentId = source.readInt(); - if (source.readInt() != 0) { - baseIntent = Intent.CREATOR.createFromParcel(source); - } else { - baseIntent = null; - } + baseIntent = source.readInt() > 0 ? Intent.CREATOR.createFromParcel(source) : null; origActivity = ComponentName.readFromParcel(source); description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + taskDescription = source.readInt() > 0 ? + TaskDescription.CREATOR.createFromParcel(source) : null; stackId = source.readInt(); + userId = source.readInt(); + firstActiveTime = source.readLong(); + lastActiveTime = source.readLong(); + affiliatedTaskId = source.readInt(); + affiliatedTaskColor = source.readInt(); } public static final Creator<RecentTaskInfo> CREATOR @@ -560,7 +897,7 @@ * {@link android.content.Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} flag. */ public static final int RECENT_WITH_EXCLUDED = 0x0001; - + /** * Provides a list that does not contain any * recent tasks that currently are not available to the user. @@ -568,7 +905,20 @@ public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002; /** - * Return a list of the tasks that the user has recently launched, with + * Provides a list that contains recent tasks for all + * profiles of a user. + * @hide + */ + public static final int RECENT_INCLUDE_PROFILES = 0x0004; + + /** + * Ignores all tasks that are on the home stack. + * @hide + */ + public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008; + + /** + * <p></p>Return a list of the tasks that the user has recently launched, with * the most recent being first and older ones after in order. * * <p><b>Note: this method is only intended for debugging and presenting @@ -580,6 +930,15 @@ * same time, assumptions made about the meaning of the data here for * purposes of control flow will be incorrect.</p> * + * @deprecated As of {@link android.os.Build.VERSION_CODES#L}, this method is + * no longer available to third party applications: as the introduction of + * document-centric recents means + * it can leak personal information to the caller. For backwards compatibility, + * it will still return a small subset of its data: at least the caller's + * own tasks (though see {@link #getAppTasks()} for the correct supported + * way to retrieve that information), and possibly some other tasks + * such as home that are known to not be sensitive. + * * @param maxNum The maximum number of entries to return in the list. The * actual number returned may be smaller, depending on how many tasks the * user has started and the maximum number the system can remember. @@ -592,6 +951,7 @@ * @throws SecurityException Throws SecurityException if the caller does * not hold the {@link android.Manifest.permission#GET_TASKS} permission. */ + @Deprecated public List<RecentTaskInfo> getRecentTasks(int maxNum, int flags) throws SecurityException { try { @@ -736,41 +1096,113 @@ readFromParcel(source); } } - + /** - * Return a list of the tasks that are currently running, with - * the most recent being first and older ones after in order. Note that - * "running" does not mean any of the task's code is currently loaded or - * activity -- the task may have been frozen by the system, so that it - * can be restarted in its previous state when next brought to the - * foreground. - * - * @param maxNum The maximum number of entries to return in the list. The - * actual number returned may be smaller, depending on how many tasks the - * user has started. + * Get the list of tasks associated with the calling application. * - * @param flags Optional flags - * @param receiver Optional receiver for delayed thumbnails - * - * @return Returns a list of RunningTaskInfo records describing each of - * the running tasks. - * - * Some thumbnails may not be available at the time of this call. The optional - * receiver may be used to receive those thumbnails. - * - * @throws SecurityException Throws SecurityException if the caller does - * not hold the {@link android.Manifest.permission#GET_TASKS} permission. - * - * @hide + * @return The list of tasks associated with the application making this call. + * @throws SecurityException */ - public List<RunningTaskInfo> getRunningTasks(int maxNum, int flags, IThumbnailReceiver receiver) - throws SecurityException { + public List<ActivityManager.AppTask> getAppTasks() { + ArrayList<AppTask> tasks = new ArrayList<AppTask>(); + List<IAppTask> appTasks; try { - return ActivityManagerNative.getDefault().getTasks(maxNum, flags, receiver); + appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName()); } catch (RemoteException e) { // System dead, we will be dead too soon! return null; } + int numAppTasks = appTasks.size(); + for (int i = 0; i < numAppTasks; i++) { + tasks.add(new AppTask(appTasks.get(i))); + } + return tasks; + } + + /** + * Return the current design dimensions for {@link AppTask} thumbnails, for use + * with {@link #addAppTask}. + */ + public Size getAppTaskThumbnailSize() { + synchronized (this) { + ensureAppTaskThumbnailSizeLocked(); + return new Size(mAppTaskThumbnailSize.x, mAppTaskThumbnailSize.y); + } + } + + private void ensureAppTaskThumbnailSizeLocked() { + if (mAppTaskThumbnailSize == null) { + try { + mAppTaskThumbnailSize = ActivityManagerNative.getDefault().getAppTaskThumbnailSize(); + } catch (RemoteException e) { + throw new IllegalStateException("System dead?", e); + } + } + } + + /** + * Add a new {@link AppTask} for the calling application. This will create a new + * recents entry that is added to the <b>end</b> of all existing recents. + * + * @param activity The activity that is adding the entry. This is used to help determine + * the context that the new recents entry will be in. + * @param intent The Intent that describes the recents entry. This is the same Intent that + * you would have used to launch the activity for it. In generally you will want to set + * both {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT} and + * {@link Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}; the latter is required since this recents + * entry will exist without an activity, so it doesn't make sense to not retain it when + * its activity disappears. The given Intent here also must have an explicit ComponentName + * set on it. + * @param description Optional additional description information. + * @param thumbnail Thumbnail to use for the recents entry. Should be the size given by + * {@link #getAppTaskThumbnailSize()}. If the bitmap is not that exact size, it will be + * recreated in your process, probably in a way you don't like, before the recents entry + * is added. + * + * @return Returns the task id of the newly added app task, or -1 if the add failed. The + * most likely cause of failure is that there is no more room for more tasks for your app. + */ + public int addAppTask(@NonNull Activity activity, @NonNull Intent intent, + @Nullable TaskDescription description, @NonNull Bitmap thumbnail) { + Point size; + synchronized (this) { + ensureAppTaskThumbnailSizeLocked(); + size = mAppTaskThumbnailSize; + } + final int tw = thumbnail.getWidth(); + final int th = thumbnail.getHeight(); + if (tw != size.x || th != size.y) { + Bitmap bm = Bitmap.createBitmap(size.x, size.y, thumbnail.getConfig()); + + // Use ScaleType.CENTER_CROP, except we leave the top edge at the top. + float scale; + float dx = 0, dy = 0; + if (tw * size.x > size.y * th) { + scale = (float) size.x / (float) th; + dx = (size.y - tw * scale) * 0.5f; + } else { + scale = (float) size.y / (float) tw; + dy = (size.x - th * scale) * 0.5f; + } + Matrix matrix = new Matrix(); + matrix.setScale(scale, scale); + matrix.postTranslate((int) (dx + 0.5f), 0); + + Canvas canvas = new Canvas(bm); + canvas.drawBitmap(thumbnail, matrix, null); + canvas.setBitmap(null); + + thumbnail = bm; + } + if (description == null) { + description = new TaskDescription(); + } + try { + return ActivityManagerNative.getDefault().addAppTask(activity.getActivityToken(), + intent, description, thumbnail); + } catch (RemoteException e) { + throw new IllegalStateException("System dead?", e); + } } /** @@ -790,6 +1222,14 @@ * same time, assumptions made about the meaning of the data here for * purposes of control flow will be incorrect.</p> * + * @deprecated As of {@link android.os.Build.VERSION_CODES#L}, this method + * is no longer available to third party + * applications: the introduction of document-centric recents means + * it can leak person information to the caller. For backwards compatibility, + * it will still retu rn a small subset of its data: at least the caller's + * own tasks, and possibly some other tasks + * such as home that are known to not be sensitive. + * * @param maxNum The maximum number of entries to return in the list. The * actual number returned may be smaller, depending on how many tasks the * user has started. @@ -800,30 +1240,14 @@ * @throws SecurityException Throws SecurityException if the caller does * not hold the {@link android.Manifest.permission#GET_TASKS} permission. */ + @Deprecated public List<RunningTaskInfo> getRunningTasks(int maxNum) throws SecurityException { - return getRunningTasks(maxNum, 0, null); - } - - /** - * Remove some end of a task's activity stack that is not part of - * the main application. The selected activities will be finished, so - * they are no longer part of the main task. - * - * @param taskId The identifier of the task. - * @param subTaskIndex The number of the sub-task; this corresponds - * to the index of the thumbnail returned by {@link #getTaskThumbnails(int)}. - * @return Returns true if the sub-task was found and was removed. - * - * @hide - */ - public boolean removeSubTask(int taskId, int subTaskIndex) - throws SecurityException { try { - return ActivityManagerNative.getDefault().removeSubTask(taskId, subTaskIndex); + return ActivityManagerNative.getDefault().getTasks(maxNum, 0); } catch (RemoteException e) { // System dead, we will be dead too soon! - return false; + return null; } } @@ -855,38 +1279,33 @@ } /** @hide */ - public static class TaskThumbnails implements Parcelable { + public static class TaskThumbnail implements Parcelable { public Bitmap mainThumbnail; + public ParcelFileDescriptor thumbnailFileDescriptor; - public int numSubThumbbails; - - /** @hide */ - public IThumbnailRetriever retriever; - - public TaskThumbnails() { - } - - public Bitmap getSubThumbnail(int index) { - try { - return retriever.getThumbnail(index); - } catch (RemoteException e) { - return null; - } + public TaskThumbnail() { } public int describeContents() { + if (thumbnailFileDescriptor != null) { + return thumbnailFileDescriptor.describeContents(); + } return 0; } public void writeToParcel(Parcel dest, int flags) { if (mainThumbnail != null) { dest.writeInt(1); - mainThumbnail.writeToParcel(dest, 0); + mainThumbnail.writeToParcel(dest, flags); } else { dest.writeInt(0); } - dest.writeInt(numSubThumbbails); - dest.writeStrongInterface(retriever); + if (thumbnailFileDescriptor != null) { + dest.writeInt(1); + thumbnailFileDescriptor.writeToParcel(dest, flags); + } else { + dest.writeInt(0); + } } public void readFromParcel(Parcel source) { @@ -895,28 +1314,31 @@ } else { mainThumbnail = null; } - numSubThumbbails = source.readInt(); - retriever = IThumbnailRetriever.Stub.asInterface(source.readStrongBinder()); + if (source.readInt() != 0) { + thumbnailFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(source); + } else { + thumbnailFileDescriptor = null; + } } - public static final Creator<TaskThumbnails> CREATOR = new Creator<TaskThumbnails>() { - public TaskThumbnails createFromParcel(Parcel source) { - return new TaskThumbnails(source); + public static final Creator<TaskThumbnail> CREATOR = new Creator<TaskThumbnail>() { + public TaskThumbnail createFromParcel(Parcel source) { + return new TaskThumbnail(source); } - public TaskThumbnails[] newArray(int size) { - return new TaskThumbnails[size]; + public TaskThumbnail[] newArray(int size) { + return new TaskThumbnail[size]; } }; - private TaskThumbnails(Parcel source) { + private TaskThumbnail(Parcel source) { readFromParcel(source); } } /** @hide */ - public TaskThumbnails getTaskThumbnails(int id) throws SecurityException { + public TaskThumbnail getTaskThumbnail(int id) throws SecurityException { try { - return ActivityManagerNative.getDefault().getTaskThumbnails(id); + return ActivityManagerNative.getDefault().getTaskThumbnail(id); } catch (RemoteException e) { // System dead, we will be dead too soon! return null; @@ -924,12 +1346,12 @@ } /** @hide */ - public Bitmap getTaskTopThumbnail(int id) throws SecurityException { + public boolean isInHomeStack(int taskId) { try { - return ActivityManagerNative.getDefault().getTaskTopThumbnail(id); + return ActivityManagerNative.getDefault().isInHomeStack(taskId); } catch (RemoteException e) { // System dead, we will be dead too soon! - return null; + return false; } } @@ -1570,13 +1992,6 @@ public int lastTrimLevel; /** - * Constant for {@link #importance}: this is a persistent process. - * Only used when reporting to process observers. - * @hide - */ - public static final int IMPORTANCE_PERSISTENT = 50; - - /** * Constant for {@link #importance}: this process is running the * foreground UI. */ @@ -1621,7 +2036,29 @@ * actively running code. */ public static final int IMPORTANCE_EMPTY = 500; - + + /** + * Constant for {@link #importance}: this process does not exist. + */ + public static final int IMPORTANCE_GONE = 1000; + + /** @hide */ + public static int procStateToImportance(int procState) { + if (procState >= ActivityManager.PROCESS_STATE_HOME) { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND; + } else if (procState >= ActivityManager.PROCESS_STATE_SERVICE) { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE; + } else if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE; + } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE; + } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; + } else { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; + } + } + /** * The relative importance level that the system places on this * process. May be one of {@link #IMPORTANCE_FOREGROUND}, @@ -1691,9 +2128,16 @@ */ public int importanceReasonImportance; + /** + * Current process state, as per PROCESS_STATE_* constants. + * @hide + */ + public int processState; + public RunningAppProcessInfo() { importance = IMPORTANCE_FOREGROUND; importanceReasonCode = REASON_UNKNOWN; + processState = PROCESS_STATE_IMPORTANT_FOREGROUND; } public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) { @@ -1719,6 +2163,7 @@ dest.writeInt(importanceReasonPid); ComponentName.writeToParcel(importanceReasonComponent, dest); dest.writeInt(importanceReasonImportance); + dest.writeInt(processState); } public void readFromParcel(Parcel source) { @@ -1734,6 +2179,7 @@ importanceReasonPid = source.readInt(); importanceReasonComponent = ComponentName.readFromParcel(source); importanceReasonImportance = source.readInt(); + processState = source.readInt(); } public static final Creator<RunningAppProcessInfo> CREATOR = @@ -1871,19 +2317,27 @@ * call this method. * * @param packageName The name of the package to be stopped. + * @param userId The user for which the running package is to be stopped. * * @hide This is not available to third party applications due to * it allowing them to break other applications by stopping their * services, removing their alarms, etc. */ - public void forceStopPackage(String packageName) { + public void forceStopPackageAsUser(String packageName, int userId) { try { - ActivityManagerNative.getDefault().forceStopPackage(packageName, - UserHandle.myUserId()); + ActivityManagerNative.getDefault().forceStopPackage(packageName, userId); } catch (RemoteException e) { } } - + + /** + * @see #forceStopPackageAsUser(String, int) + * @hide + */ + public void forceStopPackage(String packageName) { + forceStopPackageAsUser(packageName, UserHandle.myUserId()); + } + /** * Get the device configuration attributes. */ @@ -1938,7 +2392,11 @@ * @return dimensions of square icons in terms of pixels */ public int getLauncherLargeIconSize() { - final Resources res = mContext.getResources(); + return getLauncherLargeIconSizeInner(mContext); + } + + static int getLauncherLargeIconSizeInner(Context context) { + final Resources res = context.getResources(); final int size = res.getDimensionPixelSize(android.R.dimen.app_icon_size); final int sw = res.getConfiguration().smallestScreenWidthDp; @@ -1993,7 +2451,7 @@ * * @hide */ - public Map<String, Integer> getAllPackageLaunchCounts() { + /*public Map<String, Integer> getAllPackageLaunchCounts() { try { IUsageStats usageStatsService = IUsageStats.Stub.asInterface( ServiceManager.getService("usagestats")); @@ -2001,14 +2459,15 @@ return new HashMap<String, Integer>(); } - PkgUsageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats(); + UsageStats.PackageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats( + ActivityThread.currentPackageName()); if (allPkgUsageStats == null) { return new HashMap<String, Integer>(); } Map<String, Integer> launchCounts = new HashMap<String, Integer>(); - for (PkgUsageStats pkgUsageStats : allPkgUsageStats) { - launchCounts.put(pkgUsageStats.packageName, pkgUsageStats.launchCount); + for (UsageStats.PackageStats pkgUsageStats : allPkgUsageStats) { + launchCounts.put(pkgUsageStats.getPackageName(), pkgUsageStats.getLaunchCount()); } return launchCounts; @@ -2016,7 +2475,7 @@ Log.w(TAG, "Could not query launch counts", e); return new HashMap<String, Integer>(); } - } + }*/ /** @hide */ public static int checkComponentPermission(String permission, int uid, @@ -2106,7 +2565,11 @@ } } - /** @hide */ + /** + * Gets the userId of the current foreground user. Requires system permissions. + * @hide + */ + @SystemApi public static int getCurrentUser() { UserInfo ui; try { @@ -2118,24 +2581,6 @@ } /** - * Returns the usage statistics of each installed package. - * - * @hide - */ - public PkgUsageStats[] getAllPackageUsageStats() { - try { - IUsageStats usageStatsService = IUsageStats.Stub.asInterface( - ServiceManager.getService("usagestats")); - if (usageStatsService != null) { - return usageStatsService.getAllPkgUsageStats(); - } - } catch (RemoteException e) { - Log.w(TAG, "Could not query usage stats", e); - } - return new PkgUsageStats[0]; - } - - /** * @param userid the user's id. Zero indicates the default user * @hide */ @@ -2222,4 +2667,132 @@ e.printStackTrace(pw); } } + + /** + * @hide + */ + public void startLockTaskMode(int taskId) { + try { + ActivityManagerNative.getDefault().startLockTaskMode(taskId); + } catch (RemoteException e) { + } + } + + /** + * @hide + */ + public void stopLockTaskMode() { + try { + ActivityManagerNative.getDefault().stopLockTaskMode(); + } catch (RemoteException e) { + } + } + + /** + * Return whether currently in lock task mode. When in this mode + * no new tasks can be created or switched to. + * + * @see Activity#startLockTask() + */ + public boolean isInLockTaskMode() { + try { + return ActivityManagerNative.getDefault().isInLockTaskMode(); + } catch (RemoteException e) { + return false; + } + } + + /** + * The AppTask allows you to manage your own application's tasks. + * See {@link android.app.ActivityManager#getAppTasks()} + */ + public static class AppTask { + private IAppTask mAppTaskImpl; + + /** @hide */ + public AppTask(IAppTask task) { + mAppTaskImpl = task; + } + + /** + * Finishes all activities in this task and removes it from the recent tasks list. + */ + public void finishAndRemoveTask() { + try { + mAppTaskImpl.finishAndRemoveTask(); + } catch (RemoteException e) { + Slog.e(TAG, "Invalid AppTask", e); + } + } + + /** + * Get the RecentTaskInfo associated with this task. + * + * @return The RecentTaskInfo for this task, or null if the task no longer exists. + */ + public RecentTaskInfo getTaskInfo() { + try { + return mAppTaskImpl.getTaskInfo(); + } catch (RemoteException e) { + Slog.e(TAG, "Invalid AppTask", e); + return null; + } + } + + /** + * Bring this task to the foreground. If it contains activities, they will be + * brought to the foreground with it and their instances re-created if needed. + * If it doesn't contain activities, the root activity of the task will be + * re-launched. + */ + public void moveToFront() { + try { + mAppTaskImpl.moveToFront(); + } catch (RemoteException e) { + Slog.e(TAG, "Invalid AppTask", e); + } + } + + /** + * Start an activity in this task. Brings the task to the foreground. If this task + * is not currently active (that is, its id < 0), then a new activity for the given + * Intent will be launched as the root of the task and the task brought to the + * foreground. Otherwise, if this task is currently active and the Intent does not specify + * an activity to launch in a new task, then a new activity for the given Intent will + * be launched on top of the task and the task brought to the foreground. If this + * task is currently active and the Intent specifies {@link Intent#FLAG_ACTIVITY_NEW_TASK} + * or would otherwise be launched in to a new task, then the activity not launched but + * this task be brought to the foreground and a new intent delivered to the top + * activity if appropriate. + * + * <p>In other words, you generally want to use an Intent here that does not specify + * {@link Intent#FLAG_ACTIVITY_NEW_TASK} or {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT}, + * and let the system do the right thing.</p> + * + * @param intent The Intent describing the new activity to be launched on the task. + * @param options Optional launch options. + * + * @see Activity#startActivity(android.content.Intent, android.os.Bundle) + */ + public void startActivity(Context context, Intent intent, Bundle options) { + ActivityThread thread = ActivityThread.currentActivityThread(); + thread.getInstrumentation().execStartActivityFromAppTask(context, + thread.getApplicationThread(), mAppTaskImpl, intent, options); + } + + /** + * Modify the {@link Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} flag in the root + * Intent of this AppTask. + * + * @param exclude If true, {@link Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} will + * be set; otherwise, it will be cleared. + */ + public void setExcludeFromRecents(boolean exclude) { + try { + mAppTaskImpl.setExcludeFromRecents(exclude); + } catch (RemoteException e) { + Slog.e(TAG, "Invalid AppTask", e); + } + } + } }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 5262a5f..2a17fa6 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java
@@ -25,4 +25,6 @@ // Called by the power manager. public abstract void goingToSleep(); public abstract void wakingUp(); + public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs, + String processName, String abiOverride, int uid, Runnable crashHandler); }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index e5ee1fa..11470e3 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java
@@ -17,6 +17,7 @@ package android.app; import android.app.ActivityManager.StackInfo; +import android.app.ProfilerInfo; import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.IIntentSender; @@ -31,6 +32,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.Point; import android.graphics.Rect; import android.net.Uri; import android.os.Binder; @@ -40,12 +42,15 @@ import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StrictMode; +import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; import android.util.Log; import android.util.Singleton; +import com.android.internal.app.IVoiceInteractor; import java.util.ArrayList; import java.util.List; @@ -101,9 +106,9 @@ } } - static public void noteWakeupAlarm(PendingIntent ps) { + static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg) { try { - getDefault().noteWakeupAlarm(ps.getTarget()); + getDefault().noteWakeupAlarm(ps.getTarget(), sourceUid, sourcePkg); } catch (RemoteException ex) { } } @@ -128,14 +133,12 @@ String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? data.readFileDescriptor() : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int result = startActivity(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; @@ -153,15 +156,36 @@ String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int userId = data.readInt(); int result = startActivityAsUser(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options, userId); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId); + reply.writeNoException(); + reply.writeInt(result); + return true; + } + + case START_ACTIVITY_AS_CALLER_TRANSACTION: + { + data.enforceInterface(IActivityManager.descriptor); + IBinder b = data.readStrongBinder(); + IApplicationThread app = ApplicationThreadNative.asInterface(b); + String callingPackage = data.readString(); + Intent intent = Intent.CREATOR.createFromParcel(data); + String resolvedType = data.readString(); + IBinder resultTo = data.readStrongBinder(); + String resultWho = data.readString(); + int requestCode = data.readInt(); + int startFlags = data.readInt(); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + Bundle options = data.readInt() != 0 + ? Bundle.CREATOR.createFromParcel(data) : null; + int result = startActivityAsCaller(app, callingPackage, intent, resolvedType, + resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; @@ -179,15 +203,13 @@ String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int userId = data.readInt(); WaitResult result = startActivityAndWait(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options, userId); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId); reply.writeNoException(); result.writeToParcel(reply, 0); return true; @@ -242,6 +264,31 @@ return true; } + case START_VOICE_ACTIVITY_TRANSACTION: + { + data.enforceInterface(IActivityManager.descriptor); + String callingPackage = data.readString(); + int callingPid = data.readInt(); + int callingUid = data.readInt(); + Intent intent = Intent.CREATOR.createFromParcel(data); + String resolvedType = data.readString(); + IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface( + data.readStrongBinder()); + IVoiceInteractor interactor = IVoiceInteractor.Stub.asInterface( + data.readStrongBinder()); + int startFlags = data.readInt(); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + Bundle options = data.readInt() != 0 + ? Bundle.CREATOR.createFromParcel(data) : null; + int userId = data.readInt(); + int result = startVoiceActivity(callingPackage, callingPid, callingUid, intent, + resolvedType, session, interactor, startFlags, profilerInfo, options, userId); + reply.writeNoException(); + reply.writeInt(result); + return true; + } + case START_NEXT_MATCHING_ACTIVITY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); @@ -255,6 +302,17 @@ return true; } + case START_ACTIVITY_FROM_RECENTS_TRANSACTION: + { + data.enforceInterface(IActivityManager.descriptor); + int taskId = data.readInt(); + Bundle options = data.readInt() == 0 ? null : Bundle.CREATOR.createFromParcel(data); + int result = startActivityFromRecents(taskId, options); + reply.writeNoException(); + reply.writeInt(result); + return true; + } + case FINISH_ACTIVITY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -263,7 +321,8 @@ if (data.readInt() != 0) { resultData = Intent.CREATOR.createFromParcel(data); } - boolean res = finishActivity(token, resultCode, resultData); + boolean finishTask = (data.readInt() != 0); + boolean res = finishActivity(token, resultCode, resultData, finishTask); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -288,6 +347,32 @@ return true; } + case FINISH_VOICE_TASK_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface( + data.readStrongBinder()); + finishVoiceTask(session); + reply.writeNoException(); + return true; + } + + case RELEASE_ACTIVITY_INSTANCE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + boolean res = releaseActivityInstance(token); + reply.writeNoException(); + reply.writeInt(res ? 1 : 0); + return true; + } + + case RELEASE_SOME_ACTIVITIES_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IApplicationThread app = ApplicationThreadNative.asInterface(data.readStrongBinder()); + releaseSomeActivities(app); + reply.writeNoException(); + return true; + } + case WILL_ACTIVITY_BE_VISIBLE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -433,10 +518,9 @@ data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); Bundle map = data.readBundle(); - Bitmap thumbnail = data.readInt() != 0 - ? Bitmap.CREATOR.createFromParcel(data) : null; + PersistableBundle persistentState = data.readPersistableBundle(); CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); - activityStopped(token, map, thumbnail, description); + activityStopped(token, map, persistentState, description); reply.writeNoException(); return true; } @@ -475,15 +559,47 @@ return true; } + case GET_APP_TASKS_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String callingPackage = data.readString(); + List<IAppTask> list = getAppTasks(callingPackage); + reply.writeNoException(); + int N = list != null ? list.size() : -1; + reply.writeInt(N); + int i; + for (i=0; i<N; i++) { + IAppTask task = list.get(i); + reply.writeStrongBinder(task.asBinder()); + } + return true; + } + + case ADD_APP_TASK_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder activityToken = data.readStrongBinder(); + Intent intent = Intent.CREATOR.createFromParcel(data); + ActivityManager.TaskDescription descr + = ActivityManager.TaskDescription.CREATOR.createFromParcel(data); + Bitmap thumbnail = Bitmap.CREATOR.createFromParcel(data); + int res = addAppTask(activityToken, intent, descr, thumbnail); + reply.writeNoException(); + reply.writeInt(res); + return true; + } + + case GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + Point size = getAppTaskThumbnailSize(); + reply.writeNoException(); + size.writeToParcel(reply, 0); + return true; + } + case GET_TASKS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int maxNum = data.readInt(); int fl = data.readInt(); - IBinder receiverBinder = data.readStrongBinder(); - IThumbnailReceiver receiver = receiverBinder != null - ? IThumbnailReceiver.Stub.asInterface(receiverBinder) - : null; - List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl, receiver); + List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl); reply.writeNoException(); int N = list != null ? list.size() : -1; reply.writeInt(N); @@ -507,28 +623,14 @@ return true; } - case GET_TASK_THUMBNAILS_TRANSACTION: { + case GET_TASK_THUMBNAIL_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int id = data.readInt(); - ActivityManager.TaskThumbnails bm = getTaskThumbnails(id); + ActivityManager.TaskThumbnail taskThumbnail = getTaskThumbnail(id); reply.writeNoException(); - if (bm != null) { + if (taskThumbnail != null) { reply.writeInt(1); - bm.writeToParcel(reply, 0); - } else { - reply.writeInt(0); - } - return true; - } - - case GET_TASK_TOP_THUMBNAIL_TRANSACTION: { - data.enforceInterface(IActivityManager.descriptor); - int id = data.readInt(); - Bitmap bm = getTaskTopThumbnail(id); - reply.writeNoException(); - if (bm != null) { - reply.writeInt(1); - bm.writeToParcel(reply, 0); + taskThumbnail.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } @@ -654,6 +756,15 @@ return true; } + case IS_IN_HOME_STACK_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int taskId = data.readInt(); + boolean isInHomeStack = isInHomeStack(taskId); + reply.writeNoException(); + reply.writeInt(isInHomeStack ? 1 : 0); + return true; + } + case SET_FOCUSED_STACK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int stackId = data.readInt(); @@ -673,17 +784,6 @@ return true; } - case REPORT_THUMBNAIL_TRANSACTION: { - data.enforceInterface(IActivityManager.descriptor); - IBinder token = data.readStrongBinder(); - Bitmap thumbnail = data.readInt() != 0 - ? Bitmap.CREATOR.createFromParcel(data) : null; - CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); - reportThumbnail(token, thumbnail, description); - reply.writeNoException(); - return true; - } - case GET_CONTENT_PROVIDER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); @@ -1091,7 +1191,8 @@ int pid = data.readInt(); int uid = data.readInt(); int mode = data.readInt(); - int res = checkUriPermission(uri, pid, uid, mode); + int userId = data.readInt(); + int res = checkUriPermission(uri, pid, uid, mode, userId); reply.writeNoException(); reply.writeInt(res); return true; @@ -1116,7 +1217,8 @@ String targetPkg = data.readString(); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); - grantUriPermission(app, targetPkg, uri, mode); + int userId = data.readInt(); + grantUriPermission(app, targetPkg, uri, mode, userId); reply.writeNoException(); return true; } @@ -1127,7 +1229,8 @@ IApplicationThread app = ApplicationThreadNative.asInterface(b); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); - revokeUriPermission(app, uri, mode); + int userId = data.readInt(); + revokeUriPermission(app, uri, mode, userId); reply.writeNoException(); return true; } @@ -1136,7 +1239,8 @@ data.enforceInterface(IActivityManager.descriptor); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); - takePersistableUriPermission(uri, mode); + int userId = data.readInt(); + takePersistableUriPermission(uri, mode, userId); reply.writeNoException(); return true; } @@ -1145,7 +1249,8 @@ data.enforceInterface(IActivityManager.descriptor); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); - releasePersistableUriPermission(uri, mode); + int userId = data.readInt(); + releasePersistableUriPermission(uri, mode, userId); reply.writeNoException(); return true; } @@ -1246,7 +1351,9 @@ data.enforceInterface(IActivityManager.descriptor); IIntentSender is = IIntentSender.Stub.asInterface( data.readStrongBinder()); - noteWakeupAlarm(is); + int sourceUid = data.readInt(); + String sourcePkg = data.readString(); + noteWakeupAlarm(is, sourceUid, sourcePkg); reply.writeNoException(); return true; } @@ -1284,8 +1391,9 @@ data.enforceInterface(IActivityManager.descriptor); IBinder app = data.readStrongBinder(); String tag = data.readString(); + boolean system = data.readInt() != 0; ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data); - boolean res = handleApplicationWtf(app, tag, ci); + boolean res = handleApplicationWtf(app, tag, system, ci); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -1351,22 +1459,21 @@ config.writeToParcel(reply, 0); return true; } - + case PROFILE_CONTROL_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String process = data.readString(); int userId = data.readInt(); boolean start = data.readInt() != 0; int profileType = data.readInt(); - String path = data.readString(); - ParcelFileDescriptor fd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - boolean res = profileControl(process, userId, start, path, fd, profileType); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + boolean res = profileControl(process, userId, start, profilerInfo, profileType); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; } - + case SHUTDOWN_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); boolean res = shutdown(data.readInt()); @@ -1425,7 +1532,15 @@ reply.writeNoException(); return true; } - + + case ADD_PACKAGE_DEPENDENCY_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String packageName = data.readString(); + addPackageDependency(packageName); + reply.writeNoException(); + return true; + } + case KILL_APPLICATION_WITH_APPID_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String pkg = data.readString(); @@ -1435,7 +1550,7 @@ reply.writeNoException(); return true; } - + case CLOSE_SYSTEM_DIALOGS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String reason = data.readString(); @@ -1505,6 +1620,15 @@ return true; } + case IS_TOP_OF_TASK_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + final boolean isTopOfTask = isTopOfTask(token); + reply.writeNoException(); + reply.writeInt(isTopOfTask ? 1 : 0); + return true; + } + case CONVERT_FROM_TRANSLUCENT_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -1517,12 +1641,28 @@ case CONVERT_TO_TRANSLUCENT_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); - boolean converted = convertToTranslucent(token); + final Bundle bundle; + if (data.readInt() == 0) { + bundle = null; + } else { + bundle = data.readBundle(); + } + final ActivityOptions options = bundle == null ? null : new ActivityOptions(bundle); + boolean converted = convertToTranslucent(token, options); reply.writeNoException(); reply.writeInt(converted ? 1 : 0); return true; } + case GET_ACTIVITY_OPTIONS_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + final ActivityOptions options = getActivityOptions(token); + reply.writeNoException(); + reply.writeBundle(options == null ? null : options.toBundle()); + return true; + } + case SET_IMMERSIVE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -1577,7 +1717,10 @@ String targetPkg = data.readString(); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); - grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode); + int sourceUserId = data.readInt(); + int targetUserId = data.readInt(); + grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode, sourceUserId, + targetUserId); reply.writeNoException(); return true; } @@ -1587,10 +1730,11 @@ IBinder owner = data.readStrongBinder(); Uri uri = null; if (data.readInt() != 0) { - Uri.CREATOR.createFromParcel(data); + uri = Uri.CREATOR.createFromParcel(data); } int mode = data.readInt(); - revokeUriPermissionFromOwner(owner, uri, mode); + int userId = data.readInt(); + revokeUriPermissionFromOwner(owner, uri, mode, userId); reply.writeNoException(); return true; } @@ -1601,7 +1745,8 @@ String targetPkg = data.readString(); Uri uri = Uri.CREATOR.createFromParcel(data); int modeFlags = data.readInt(); - int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags); + int userId = data.readInt(); + int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags, userId); reply.writeNoException(); reply.writeInt(res); return true; @@ -1688,6 +1833,15 @@ return true; } + case START_USER_IN_BACKGROUND_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int userid = data.readInt(); + boolean result = startUserInBackground(userid); + reply.writeNoException(); + reply.writeInt(result ? 1 : 0); + return true; + } + case STOP_USER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int userid = data.readInt(); @@ -1725,17 +1879,6 @@ return true; } - case REMOVE_SUB_TASK_TRANSACTION: - { - data.enforceInterface(IActivityManager.descriptor); - int taskId = data.readInt(); - int subTaskIndex = data.readInt(); - boolean result = removeSubTask(taskId, subTaskIndex); - reply.writeNoException(); - reply.writeInt(result ? 1 : 0); - return true; - } - case REMOVE_TASK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); @@ -1818,6 +1961,17 @@ return true; } + case GET_TAG_FOR_INTENT_SENDER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IIntentSender r = IIntentSender.Stub.asInterface( + data.readStrongBinder()); + String prefix = data.readString(); + String tag = getTagForIntentSender(r, prefix); + reply.writeNoException(); + reply.writeString(tag); + return true; + } + case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); Configuration config = Configuration.CREATOR.createFromParcel(data); @@ -1844,18 +1998,18 @@ return true; } - case DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION: { + case KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - dismissKeyguardOnNextActivity(); + keyguardWaitingForActivityDrawn(); reply.writeNoException(); return true; } - case TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION: { + case SHOULD_UP_RECREATE_TASK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); String destAffinity = data.readString(); - boolean res = targetTaskAffinityMatchesActivity(token, destAffinity); + boolean res = shouldUpRecreateTask(token, destAffinity); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -2043,6 +2197,125 @@ reply.writeStrongBinder(homeActivityToken); return true; } + + case START_LOCK_TASK_BY_TASK_ID_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + final int taskId = data.readInt(); + startLockTaskMode(taskId); + reply.writeNoException(); + return true; + } + + case START_LOCK_TASK_BY_TOKEN_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + startLockTaskMode(token); + reply.writeNoException(); + return true; + } + + case START_LOCK_TASK_BY_CURRENT_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + startLockTaskModeOnCurrent(); + reply.writeNoException(); + return true; + } + + case STOP_LOCK_TASK_MODE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + stopLockTaskMode(); + reply.writeNoException(); + return true; + } + + case STOP_LOCK_TASK_BY_CURRENT_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + stopLockTaskModeOnCurrent(); + reply.writeNoException(); + return true; + } + + case IS_IN_LOCK_TASK_MODE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + final boolean isInLockTaskMode = isInLockTaskMode(); + reply.writeNoException(); + reply.writeInt(isInLockTaskMode ? 1 : 0); + return true; + } + + case SET_TASK_DESCRIPTION_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + ActivityManager.TaskDescription values = + ActivityManager.TaskDescription.CREATOR.createFromParcel(data); + setTaskDescription(token, values); + reply.writeNoException(); + return true; + } + + case GET_TASK_DESCRIPTION_ICON_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String filename = data.readString(); + Bitmap icon = getTaskDescriptionIcon(filename); + reply.writeNoException(); + if (icon == null) { + reply.writeInt(0); + } else { + reply.writeInt(1); + icon.writeToParcel(reply, 0); + } + return true; + } + + case REQUEST_VISIBLE_BEHIND_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + boolean enable = data.readInt() > 0; + boolean success = requestVisibleBehind(token, enable); + reply.writeNoException(); + reply.writeInt(success ? 1 : 0); + return true; + } + + case IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + final boolean enabled = isBackgroundVisibleBehind(token); + reply.writeNoException(); + reply.writeInt(enabled ? 1 : 0); + return true; + } + + case BACKGROUND_RESOURCES_RELEASED_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + backgroundResourcesReleased(token); + reply.writeNoException(); + return true; + } + + case NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + notifyLaunchTaskBehindComplete(token); + reply.writeNoException(); + return true; + } + + case NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + notifyEnterAnimationComplete(token); + reply.writeNoException(); + return true; + } + + case BOOT_ANIMATION_COMPLETE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + bootAnimationComplete(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -2081,8 +2354,7 @@ public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2094,10 +2366,9 @@ data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2117,8 +2388,8 @@ public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2130,10 +2401,9 @@ data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2151,10 +2421,9 @@ data.recycle(); return result; } - public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException { + public int startActivityAsCaller(IApplicationThread caller, String callingPackage, + Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, + int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2166,10 +2435,43 @@ data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + } else { + data.writeInt(0); + } + if (options != null) { + data.writeInt(1); + options.writeToParcel(data, 0); + } else { + data.writeInt(0); + } + mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0); + reply.readException(); + int result = reply.readInt(); + reply.recycle(); + data.recycle(); + return result; + } + public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, + Intent intent, String resolvedType, IBinder resultTo, String resultWho, + int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(caller != null ? caller.asBinder() : null); + data.writeString(callingPackage); + intent.writeToParcel(data, 0); + data.writeString(resolvedType); + data.writeStrongBinder(resultTo); + data.writeString(resultWho); + data.writeInt(requestCode); + data.writeInt(startFlags); + if (profilerInfo != null) { + data.writeInt(1); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2251,6 +2553,41 @@ data.recycle(); return result; } + public int startVoiceActivity(String callingPackage, int callingPid, int callingUid, + Intent intent, String resolvedType, IVoiceInteractionSession session, + IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo, + Bundle options, int userId) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(callingPackage); + data.writeInt(callingPid); + data.writeInt(callingUid); + intent.writeToParcel(data, 0); + data.writeString(resolvedType); + data.writeStrongBinder(session.asBinder()); + data.writeStrongBinder(interactor.asBinder()); + data.writeInt(startFlags); + if (profilerInfo != null) { + data.writeInt(1); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + } else { + data.writeInt(0); + } + if (options != null) { + data.writeInt(1); + options.writeToParcel(data, 0); + } else { + data.writeInt(0); + } + data.writeInt(userId); + mRemote.transact(START_VOICE_ACTIVITY_TRANSACTION, data, reply, 0); + reply.readException(); + int result = reply.readInt(); + reply.recycle(); + data.recycle(); + return result; + } public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); @@ -2271,7 +2608,25 @@ data.recycle(); return result != 0; } - public boolean finishActivity(IBinder token, int resultCode, Intent resultData) + public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(taskId); + if (options == null) { + data.writeInt(0); + } else { + data.writeInt(1); + options.writeToParcel(data, 0); + } + mRemote.transact(START_ACTIVITY_FROM_RECENTS_TRANSACTION, data, reply, 0); + reply.readException(); + int result = reply.readInt(); + reply.recycle(); + data.recycle(); + return result; + } + public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2284,6 +2639,7 @@ } else { data.writeInt(0); } + data.writeInt(finishTask ? 1 : 0); mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); boolean res = reply.readInt() != 0; @@ -2316,6 +2672,38 @@ reply.recycle(); return res; } + public void finishVoiceTask(IVoiceInteractionSession session) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(session.asBinder()); + mRemote.transact(FINISH_VOICE_TASK_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public boolean releaseActivityInstance(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(RELEASE_ACTIVITY_INSTANCE_TRANSACTION, data, reply, 0); + reply.readException(); + boolean res = reply.readInt() != 0; + data.recycle(); + reply.recycle(); + return res; + } + public void releaseSomeActivities(IApplicationThread app) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(app.asBinder()); + mRemote.transact(RELEASE_SOME_ACTIVITIES_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } public boolean willActivityBeVisible(IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2473,19 +2861,14 @@ reply.recycle(); } public void activityStopped(IBinder token, Bundle state, - Bitmap thumbnail, CharSequence description) throws RemoteException + PersistableBundle persistentState, CharSequence description) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeBundle(state); - if (thumbnail != null) { - data.writeInt(1); - thumbnail.writeToParcel(data, 0); - } else { - data.writeInt(0); - } + data.writePersistableBundle(persistentState); TextUtils.writeToParcel(description, data, 0); mRemote.transact(ACTIVITY_STOPPED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); reply.readException(); @@ -2540,14 +2923,60 @@ reply.recycle(); return res; } - public List getTasks(int maxNum, int flags, - IThumbnailReceiver receiver) throws RemoteException { + public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(callingPackage); + mRemote.transact(GET_APP_TASKS_TRANSACTION, data, reply, 0); + reply.readException(); + ArrayList<IAppTask> list = null; + int N = reply.readInt(); + if (N >= 0) { + list = new ArrayList<IAppTask>(); + while (N > 0) { + IAppTask task = IAppTask.Stub.asInterface(reply.readStrongBinder()); + list.add(task); + N--; + } + } + data.recycle(); + reply.recycle(); + return list; + } + public int addAppTask(IBinder activityToken, Intent intent, + ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(activityToken); + intent.writeToParcel(data, 0); + description.writeToParcel(data, 0); + thumbnail.writeToParcel(data, 0); + mRemote.transact(ADD_APP_TASK_TRANSACTION, data, reply, 0); + reply.readException(); + int res = reply.readInt(); + data.recycle(); + reply.recycle(); + return res; + } + public Point getAppTaskThumbnailSize() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION, data, reply, 0); + reply.readException(); + Point size = Point.CREATOR.createFromParcel(reply); + data.recycle(); + reply.recycle(); + return size; + } + public List getTasks(int maxNum, int flags) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(maxNum); data.writeInt(flags); - data.writeStrongBinder(receiver != null ? receiver.asBinder() : null); mRemote.transact(GET_TASKS_TRANSACTION, data, reply, 0); reply.readException(); ArrayList list = null; @@ -2557,7 +2986,7 @@ while (N > 0) { ActivityManager.RunningTaskInfo info = ActivityManager.RunningTaskInfo.CREATOR - .createFromParcel(reply); + .createFromParcel(reply); list.add(info); N--; } @@ -2582,35 +3011,20 @@ reply.recycle(); return list; } - public ActivityManager.TaskThumbnails getTaskThumbnails(int id) throws RemoteException { + public ActivityManager.TaskThumbnail getTaskThumbnail(int id) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(id); - mRemote.transact(GET_TASK_THUMBNAILS_TRANSACTION, data, reply, 0); + mRemote.transact(GET_TASK_THUMBNAIL_TRANSACTION, data, reply, 0); reply.readException(); - ActivityManager.TaskThumbnails bm = null; + ActivityManager.TaskThumbnail taskThumbnail = null; if (reply.readInt() != 0) { - bm = ActivityManager.TaskThumbnails.CREATOR.createFromParcel(reply); + taskThumbnail = ActivityManager.TaskThumbnail.CREATOR.createFromParcel(reply); } data.recycle(); reply.recycle(); - return bm; - } - public Bitmap getTaskTopThumbnail(int id) throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(IActivityManager.descriptor); - data.writeInt(id); - mRemote.transact(GET_TASK_TOP_THUMBNAIL_TRANSACTION, data, reply, 0); - reply.readException(); - Bitmap bm = null; - if (reply.readInt() != 0) { - bm = Bitmap.CREATOR.createFromParcel(reply); - } - data.recycle(); - reply.recycle(); - return bm; + return taskThumbnail; } public List getServices(int maxNum, int flags) throws RemoteException { Parcel data = Parcel.obtain(); @@ -2788,6 +3202,19 @@ return info; } @Override + public boolean isInHomeStack(int taskId) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(taskId); + mRemote.transact(IS_IN_HOME_STACK_TRANSACTION, data, reply, 0); + reply.readException(); + boolean isInHomeStack = reply.readInt() > 0; + data.recycle(); + reply.recycle(); + return isInHomeStack; + } + @Override public void setFocusedStack(int stackId) throws RemoteException { Parcel data = Parcel.obtain(); @@ -2813,25 +3240,6 @@ reply.recycle(); return res; } - public void reportThumbnail(IBinder token, - Bitmap thumbnail, CharSequence description) throws RemoteException - { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(IActivityManager.descriptor); - data.writeStrongBinder(token); - if (thumbnail != null) { - data.writeInt(1); - thumbnail.writeToParcel(data, 0); - } else { - data.writeInt(0); - } - TextUtils.writeToParcel(description, data, 0); - mRemote.transact(REPORT_THUMBNAIL_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); - reply.readException(); - data.recycle(); - reply.recycle(); - } public ContentProviderHolder getContentProvider(IApplicationThread caller, String name, int userId, boolean stable) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3431,7 +3839,7 @@ reply.recycle(); return res; } - public int checkUriPermission(Uri uri, int pid, int uid, int mode) + public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -3440,6 +3848,7 @@ data.writeInt(pid); data.writeInt(uid); data.writeInt(mode); + data.writeInt(userId); mRemote.transact(CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); int res = reply.readInt(); @@ -3448,7 +3857,7 @@ return res; } public void grantUriPermission(IApplicationThread caller, String targetPkg, - Uri uri, int mode) throws RemoteException { + Uri uri, int mode, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -3456,19 +3865,21 @@ data.writeString(targetPkg); uri.writeToParcel(data, 0); data.writeInt(mode); + data.writeInt(userId); mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); } public void revokeUriPermission(IApplicationThread caller, Uri uri, - int mode) throws RemoteException { + int mode, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller.asBinder()); uri.writeToParcel(data, 0); data.writeInt(mode); + data.writeInt(userId); mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -3476,12 +3887,14 @@ } @Override - public void takePersistableUriPermission(Uri uri, int mode) throws RemoteException { + public void takePersistableUriPermission(Uri uri, int mode, int userId) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); uri.writeToParcel(data, 0); data.writeInt(mode); + data.writeInt(userId); mRemote.transact(TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -3489,12 +3902,14 @@ } @Override - public void releasePersistableUriPermission(Uri uri, int mode) throws RemoteException { + public void releasePersistableUriPermission(Uri uri, int mode, int userId) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); uri.writeToParcel(data, 0); data.writeInt(mode); + data.writeInt(userId); mRemote.transact(RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -3619,10 +4034,13 @@ mRemote.transact(ENTER_SAFE_MODE_TRANSACTION, data, null, 0); data.recycle(); } - public void noteWakeupAlarm(IIntentSender sender) throws RemoteException { + public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg) + throws RemoteException { Parcel data = Parcel.obtain(); - data.writeStrongBinder(sender.asBinder()); data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(sender.asBinder()); + data.writeInt(sourceUid); + data.writeString(sourcePkg); mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0); data.recycle(); } @@ -3671,7 +4089,7 @@ data.recycle(); } - public boolean handleApplicationWtf(IBinder app, String tag, + public boolean handleApplicationWtf(IBinder app, String tag, boolean system, ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3679,6 +4097,7 @@ data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(app); data.writeString(tag); + data.writeInt(system ? 1 : 0); crashInfo.writeToParcel(data, 0); mRemote.transact(HANDLE_APPLICATION_WTF_TRANSACTION, data, reply, 0); reply.readException(); @@ -3774,9 +4193,9 @@ data.recycle(); return res; } - + public boolean profileControl(String process, int userId, boolean start, - String path, ParcelFileDescriptor fd, int profileType) throws RemoteException + ProfilerInfo profilerInfo, int profileType) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -3785,10 +4204,9 @@ data.writeInt(userId); data.writeInt(start ? 1 : 0); data.writeInt(profileType); - data.writeString(path); - if (fd != null) { + if (profilerInfo != null) { data.writeInt(1); - fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -3799,7 +4217,7 @@ data.recycle(); return res; } - + public boolean shutdown(int timeout) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3833,7 +4251,18 @@ reply.recycle(); data.recycle(); } - + + public void addPackageDependency(String packageName) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + mRemote.transact(ADD_PACKAGE_DEPENDENCY_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public void killApplicationWithAppId(String pkg, int appid, String reason) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3947,12 +4376,18 @@ return res; } - public boolean convertToTranslucent(IBinder token) + public boolean convertToTranslucent(IBinder token, ActivityOptions options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); + if (options == null) { + data.writeInt(0); + } else { + data.writeInt(1); + data.writeBundle(options.toBundle()); + } mRemote.transact(CONVERT_TO_TRANSLUCENT_TRANSACTION, data, reply, 0); reply.readException(); boolean res = reply.readInt() != 0; @@ -3961,6 +4396,20 @@ return res; } + public ActivityOptions getActivityOptions(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(GET_ACTIVITY_OPTIONS_TRANSACTION, data, reply, 0); + reply.readException(); + Bundle bundle = reply.readBundle(); + ActivityOptions options = bundle == null ? null : new ActivityOptions(bundle); + data.recycle(); + reply.recycle(); + return options; + } + public void setImmersive(IBinder token, boolean immersive) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3988,6 +4437,19 @@ return res; } + public boolean isTopOfTask(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(IS_TOP_OF_TASK_TRANSACTION, data, reply, 0); + reply.readException(); + boolean res = reply.readInt() == 1; + data.recycle(); + reply.recycle(); + return res; + } + public boolean isTopActivityImmersive() throws RemoteException { Parcel data = Parcel.obtain(); @@ -4045,7 +4507,7 @@ } public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg, - Uri uri, int mode) throws RemoteException { + Uri uri, int mode, int sourceUserId, int targetUserId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -4054,6 +4516,8 @@ data.writeString(targetPkg); uri.writeToParcel(data, 0); data.writeInt(mode); + data.writeInt(sourceUserId); + data.writeInt(targetUserId); mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -4061,7 +4525,7 @@ } public void revokeUriPermissionFromOwner(IBinder owner, Uri uri, - int mode) throws RemoteException { + int mode, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -4073,6 +4537,7 @@ data.writeInt(0); } data.writeInt(mode); + data.writeInt(userId); mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -4080,7 +4545,7 @@ } public int checkGrantUriPermission(int callingUid, String targetPkg, - Uri uri, int modeFlags) throws RemoteException { + Uri uri, int modeFlags, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -4088,6 +4553,7 @@ data.writeString(targetPkg); uri.writeToParcel(data, 0); data.writeInt(modeFlags); + data.writeInt(userId); mRemote.transact(CHECK_GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0); reply.readException(); int res = reply.readInt(); @@ -4233,6 +4699,19 @@ return result; } + public boolean startUserInBackground(int userid) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(userid); + mRemote.transact(START_USER_IN_BACKGROUND_TRANSACTION, data, reply, 0); + reply.readException(); + boolean result = reply.readInt() != 0; + reply.recycle(); + data.recycle(); + return result; + } + public int stopUser(int userid, IStopUserCallback callback) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -4285,20 +4764,6 @@ return result; } - public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(IActivityManager.descriptor); - data.writeInt(taskId); - data.writeInt(subTaskIndex); - mRemote.transact(REMOVE_SUB_TASK_TRANSACTION, data, reply, 0); - reply.readException(); - boolean result = reply.readInt() != 0; - reply.recycle(); - data.recycle(); - return result; - } - public boolean removeTask(int taskId, int flags) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -4375,6 +4840,21 @@ return res; } + public String getTagForIntentSender(IIntentSender sender, String prefix) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(sender.asBinder()); + data.writeString(prefix); + mRemote.transact(GET_TAG_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0); + reply.readException(); + String res = reply.readString(); + data.recycle(); + reply.recycle(); + return res; + } + public void updatePersistentConfiguration(Configuration values) throws RemoteException { Parcel data = Parcel.obtain(); @@ -4412,24 +4892,24 @@ reply.recycle(); } - public void dismissKeyguardOnNextActivity() throws RemoteException { + public void keyguardWaitingForActivityDrawn() throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); - mRemote.transact(DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION, data, reply, 0); + mRemote.transact(KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); } - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeString(destAffinity); - mRemote.transact(TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION, data, reply, 0); + mRemote.transact(SHOULD_UP_RECREATE_TASK_TRANSACTION, data, reply, 0); reply.readException(); boolean result = reply.readInt() != 0; data.recycle(); @@ -4690,5 +5170,182 @@ return res; } + @Override + public void startLockTaskMode(int taskId) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(taskId); + mRemote.transact(START_LOCK_TASK_BY_TASK_ID_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void startLockTaskMode(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(START_LOCK_TASK_BY_TOKEN_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void startLockTaskModeOnCurrent() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(START_LOCK_TASK_BY_CURRENT_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void stopLockTaskMode() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(STOP_LOCK_TASK_MODE_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void stopLockTaskModeOnCurrent() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(STOP_LOCK_TASK_BY_CURRENT_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public boolean isInLockTaskMode() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(IS_IN_LOCK_TASK_MODE_TRANSACTION, data, reply, 0); + reply.readException(); + boolean isInLockTaskMode = reply.readInt() == 1; + data.recycle(); + reply.recycle(); + return isInLockTaskMode; + } + + @Override + public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + values.writeToParcel(data, 0); + mRemote.transact(SET_TASK_DESCRIPTION_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(filename); + mRemote.transact(GET_TASK_DESCRIPTION_ICON_TRANSACTION, data, reply, 0); + reply.readException(); + final Bitmap icon = reply.readInt() == 0 ? null : Bitmap.CREATOR.createFromParcel(reply); + data.recycle(); + reply.recycle(); + return icon; + } + + @Override + public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + data.writeInt(visible ? 1 : 0); + mRemote.transact(REQUEST_VISIBLE_BEHIND_TRANSACTION, data, reply, 0); + reply.readException(); + boolean success = reply.readInt() > 0; + data.recycle(); + reply.recycle(); + return success; + } + + @Override + public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION, data, reply, 0); + reply.readException(); + final boolean visible = reply.readInt() > 0; + data.recycle(); + reply.recycle(); + return visible; + } + + @Override + public void backgroundResourcesReleased(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(BACKGROUND_RESOURCES_RELEASED_TRANSACTION, data, reply, + IBinder.FLAG_ONEWAY); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION, data, reply, + IBinder.FLAG_ONEWAY); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void notifyEnterAnimationComplete(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION, data, reply, + IBinder.FLAG_ONEWAY); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public void bootAnimationComplete() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(BOOT_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 87b1e24..cd6a4f5 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java
@@ -17,12 +17,18 @@ package android.app; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.IRemoteCallback; import android.os.RemoteException; +import android.os.ResultReceiver; +import android.util.Pair; import android.view.View; +import android.view.Window; + +import java.util.ArrayList; /** * Helper class for building an options Bundle that can be used with @@ -30,6 +36,8 @@ * Context.startActivity(Intent, Bundle)} and related methods. */ public class ActivityOptions { + private static final String TAG = "ActivityOptions"; + /** * The package name that created the options. * @hide @@ -76,13 +84,13 @@ * Initial width of the animation. * @hide */ - public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth"; + public static final String KEY_ANIM_WIDTH = "android:animWidth"; /** * Initial height of the animation. * @hide */ - public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight"; + public static final String KEY_ANIM_HEIGHT = "android:animHeight"; /** * Callback for when animation is started. @@ -90,6 +98,20 @@ */ public static final String KEY_ANIM_START_LISTENER = "android:animStartListener"; + /** + * For Activity transitions, the calling Activity's TransitionListener used to + * notify the called Activity when the shared element and the exit transitions + * complete. + */ + private static final String KEY_TRANSITION_COMPLETE_LISTENER + = "android:transitionCompleteListener"; + + private static final String KEY_TRANSITION_IS_RETURNING = "android:transitionIsReturning"; + private static final String KEY_TRANSITION_SHARED_ELEMENTS = "android:sharedElementNames"; + private static final String KEY_RESULT_DATA = "android:resultData"; + private static final String KEY_RESULT_CODE = "android:resultCode"; + private static final String KEY_EXIT_COORDINATOR_INDEX = "android:exitCoordinatorIndex"; + /** @hide */ public static final int ANIM_NONE = 0; /** @hide */ @@ -100,6 +122,16 @@ public static final int ANIM_THUMBNAIL_SCALE_UP = 3; /** @hide */ public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4; + /** @hide */ + public static final int ANIM_SCENE_TRANSITION = 5; + /** @hide */ + public static final int ANIM_DEFAULT = 6; + /** @hide */ + public static final int ANIM_LAUNCH_TASK_BEHIND = 7; + /** @hide */ + public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8; + /** @hide */ + public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9; private String mPackageName; private int mAnimationType = ANIM_NONE; @@ -108,9 +140,15 @@ private Bitmap mThumbnail; private int mStartX; private int mStartY; - private int mStartWidth; - private int mStartHeight; + private int mWidth; + private int mHeight; private IRemoteCallback mAnimationStartedListener; + private ResultReceiver mTransitionReceiver; + private boolean mIsReturning; + private ArrayList<String> mSharedElementNames; + private Intent mResultData; + private int mResultCode; + private int mExitCoordinatorIndex; /** * Create an ActivityOptions specifying a custom animation to run when @@ -156,11 +194,12 @@ opts.mAnimationType = ANIM_CUSTOM; opts.mCustomEnterResId = enterResId; opts.mCustomExitResId = exitResId; - opts.setListener(handler, listener); + opts.setOnAnimationStartedListener(handler, listener); return opts; } - private void setListener(Handler handler, OnAnimationStartedListener listener) { + private void setOnAnimationStartedListener(Handler handler, + OnAnimationStartedListener listener) { if (listener != null) { final Handler h = handler; final OnAnimationStartedListener finalListener = listener; @@ -199,13 +238,13 @@ * defines the coordinate space for <var>startX</var> and <var>startY</var>. * @param startX The x starting location of the new activity, relative to <var>source</var>. * @param startY The y starting location of the activity, relative to <var>source</var>. - * @param startWidth The initial width of the new activity. - * @param startHeight The initial height of the new activity. + * @param width The initial width of the new activity. + * @param height The initial height of the new activity. * @return Returns a new ActivityOptions object that you can use to * supply these options as the options Bundle when starting an activity. */ public static ActivityOptions makeScaleUpAnimation(View source, - int startX, int startY, int startWidth, int startHeight) { + int startX, int startY, int width, int height) { ActivityOptions opts = new ActivityOptions(); opts.mPackageName = source.getContext().getPackageName(); opts.mAnimationType = ANIM_SCALE_UP; @@ -213,8 +252,8 @@ source.getLocationOnScreen(pts); opts.mStartX = pts[0] + startX; opts.mStartY = pts[1] + startY; - opts.mStartWidth = startWidth; - opts.mStartHeight = startHeight; + opts.mWidth = width; + opts.mHeight = height; return opts; } @@ -298,10 +337,194 @@ source.getLocationOnScreen(pts); opts.mStartX = pts[0] + startX; opts.mStartY = pts[1] + startY; - opts.setListener(source.getHandler(), listener); + opts.setOnAnimationStartedListener(source.getHandler(), listener); return opts; } + /** + * Create an ActivityOptions specifying an animation where the new activity + * window and a thumbnail is aspect-scaled to a new location. + * + * @param source The View that this thumbnail is animating from. This + * defines the coordinate space for <var>startX</var> and <var>startY</var>. + * @param thumbnail The bitmap that will be shown as the initial thumbnail + * of the animation. + * @param startX The x starting location of the bitmap, relative to <var>source</var>. + * @param startY The y starting location of the bitmap, relative to <var>source</var>. + * @param listener Optional OnAnimationStartedListener to find out when the + * requested animation has started running. If for some reason the animation + * is not executed, the callback will happen immediately. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + * @hide + */ + public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source, + Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, + OnAnimationStartedListener listener) { + return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, + targetWidth, targetHeight, listener, true); + } + + /** + * Create an ActivityOptions specifying an animation where the new activity + * window and a thumbnail is aspect-scaled to a new location. + * + * @param source The View that this thumbnail is animating to. This + * defines the coordinate space for <var>startX</var> and <var>startY</var>. + * @param thumbnail The bitmap that will be shown as the final thumbnail + * of the animation. + * @param startX The x end location of the bitmap, relative to <var>source</var>. + * @param startY The y end location of the bitmap, relative to <var>source</var>. + * @param listener Optional OnAnimationStartedListener to find out when the + * requested animation has started running. If for some reason the animation + * is not executed, the callback will happen immediately. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + * @hide + */ + public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source, + Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, + OnAnimationStartedListener listener) { + return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, + targetWidth, targetHeight, listener, false); + } + + private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, + int startX, int startY, int targetWidth, int targetHeight, + OnAnimationStartedListener listener, boolean scaleUp) { + ActivityOptions opts = new ActivityOptions(); + opts.mPackageName = source.getContext().getPackageName(); + opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP : + ANIM_THUMBNAIL_ASPECT_SCALE_DOWN; + opts.mThumbnail = thumbnail; + int[] pts = new int[2]; + source.getLocationOnScreen(pts); + opts.mStartX = pts[0] + startX; + opts.mStartY = pts[1] + startY; + opts.mWidth = targetWidth; + opts.mHeight = targetHeight; + opts.setOnAnimationStartedListener(source.getHandler(), listener); + return opts; + } + + /** + * Create an ActivityOptions to transition between Activities using cross-Activity scene + * animations. This method carries the position of one shared element to the started Activity. + * The position of <code>sharedElement</code> will be used as the epicenter for the + * exit Transition. The position of the shared element in the launched Activity will be the + * epicenter of its entering Transition. + * + * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be + * enabled on the calling Activity to cause an exit transition. The same must be in + * the called Activity to get an entering transition.</p> + * @param activity The Activity whose window contains the shared elements. + * @param sharedElement The View to transition to the started Activity. + * @param sharedElementName The shared element name as used in the target Activity. This + * must not be null. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + * @see android.transition.Transition#setEpicenterCallback( + * android.transition.Transition.EpicenterCallback) + */ + public static ActivityOptions makeSceneTransitionAnimation(Activity activity, + View sharedElement, String sharedElementName) { + return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName)); + } + + /** + * Create an ActivityOptions to transition between Activities using cross-Activity scene + * animations. This method carries the position of multiple shared elements to the started + * Activity. The position of the first element in sharedElements + * will be used as the epicenter for the exit Transition. The position of the associated + * shared element in the launched Activity will be the epicenter of its entering Transition. + * + * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be + * enabled on the calling Activity to cause an exit transition. The same must be in + * the called Activity to get an entering transition.</p> + * @param activity The Activity whose window contains the shared elements. + * @param sharedElements The names of the shared elements to transfer to the called + * Activity and their associated Views. The Views must each have + * a unique shared element name. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + * @see android.transition.Transition#setEpicenterCallback( + * android.transition.Transition.EpicenterCallback) + */ + public static ActivityOptions makeSceneTransitionAnimation(Activity activity, + Pair<View, String>... sharedElements) { + ActivityOptions opts = new ActivityOptions(); + if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { + opts.mAnimationType = ANIM_DEFAULT; + return opts; + } + opts.mAnimationType = ANIM_SCENE_TRANSITION; + + ArrayList<String> names = new ArrayList<String>(); + ArrayList<View> views = new ArrayList<View>(); + + if (sharedElements != null) { + for (int i = 0; i < sharedElements.length; i++) { + Pair<View, String> sharedElement = sharedElements[i]; + String sharedElementName = sharedElement.second; + if (sharedElementName == null) { + throw new IllegalArgumentException("Shared element name must not be null"); + } + names.add(sharedElementName); + View view = sharedElement.first; + if (view == null) { + throw new IllegalArgumentException("Shared element must not be null"); + } + views.add(sharedElement.first); + } + } + + ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names, + views, false); + opts.mTransitionReceiver = exit; + opts.mSharedElementNames = names; + opts.mIsReturning = false; + opts.mExitCoordinatorIndex = + activity.mActivityTransitionState.addExitTransitionCoordinator(exit); + return opts; + } + + /** @hide */ + public static ActivityOptions makeSceneTransitionAnimation(Activity activity, + ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames, + int resultCode, Intent resultData) { + ActivityOptions opts = new ActivityOptions(); + opts.mAnimationType = ANIM_SCENE_TRANSITION; + opts.mSharedElementNames = sharedElementNames; + opts.mTransitionReceiver = exitCoordinator; + opts.mIsReturning = true; + opts.mResultCode = resultCode; + opts.mResultData = resultData; + opts.mExitCoordinatorIndex = + activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator); + return opts; + } + + /** + * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be + * presented to the user but will instead be only available through the recents task list. + * In addition, the new task wil be affiliated with the launching activity's task. + * Affiliated tasks are grouped together in the recents task list. + * + * <p>This behavior is not supported for activities with {@link + * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of + * <code>singleInstance</code> or <code>singleTask</code>. + */ + public static ActivityOptions makeTaskLaunchBehind() { + final ActivityOptions opts = new ActivityOptions(); + opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND; + return opts; + } + + /** @hide */ + public boolean getLaunchTaskBehind() { + return mAnimationType == ANIM_LAUNCH_TASK_BEHIND; + } + private ActivityOptions() { } @@ -309,23 +532,42 @@ public ActivityOptions(Bundle opts) { mPackageName = opts.getString(KEY_PACKAGE_NAME); mAnimationType = opts.getInt(KEY_ANIM_TYPE); - if (mAnimationType == ANIM_CUSTOM) { - mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0); - mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0); - mAnimationStartedListener = IRemoteCallback.Stub.asInterface( - opts.getIBinder(KEY_ANIM_START_LISTENER)); - } else if (mAnimationType == ANIM_SCALE_UP) { - mStartX = opts.getInt(KEY_ANIM_START_X, 0); - mStartY = opts.getInt(KEY_ANIM_START_Y, 0); - mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0); - mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0); - } else if (mAnimationType == ANIM_THUMBNAIL_SCALE_UP || - mAnimationType == ANIM_THUMBNAIL_SCALE_DOWN) { - mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL); - mStartX = opts.getInt(KEY_ANIM_START_X, 0); - mStartY = opts.getInt(KEY_ANIM_START_Y, 0); - mAnimationStartedListener = IRemoteCallback.Stub.asInterface( - opts.getIBinder(KEY_ANIM_START_LISTENER)); + switch (mAnimationType) { + case ANIM_CUSTOM: + mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0); + mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0); + mAnimationStartedListener = IRemoteCallback.Stub.asInterface( + opts.getBinder(KEY_ANIM_START_LISTENER)); + break; + + case ANIM_SCALE_UP: + mStartX = opts.getInt(KEY_ANIM_START_X, 0); + mStartY = opts.getInt(KEY_ANIM_START_Y, 0); + mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); + mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0); + break; + + case ANIM_THUMBNAIL_SCALE_UP: + case ANIM_THUMBNAIL_SCALE_DOWN: + case ANIM_THUMBNAIL_ASPECT_SCALE_UP: + case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: + mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL); + mStartX = opts.getInt(KEY_ANIM_START_X, 0); + mStartY = opts.getInt(KEY_ANIM_START_Y, 0); + mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); + mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0); + mAnimationStartedListener = IRemoteCallback.Stub.asInterface( + opts.getBinder(KEY_ANIM_START_LISTENER)); + break; + + case ANIM_SCENE_TRANSITION: + mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER); + mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false); + mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS); + mResultData = opts.getParcelable(KEY_RESULT_DATA); + mResultCode = opts.getInt(KEY_RESULT_CODE); + mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX); + break; } } @@ -365,13 +607,13 @@ } /** @hide */ - public int getStartWidth() { - return mStartWidth; + public int getWidth() { + return mWidth; } /** @hide */ - public int getStartHeight() { - return mStartHeight; + public int getHeight() { + return mHeight; } /** @hide */ @@ -380,6 +622,9 @@ } /** @hide */ + public int getExitCoordinatorKey() { return mExitCoordinatorIndex; } + + /** @hide */ public void abort() { if (mAnimationStartedListener != null) { try { @@ -390,6 +635,25 @@ } /** @hide */ + public boolean isReturning() { + return mIsReturning; + } + + /** @hide */ + public ArrayList<String> getSharedElementNames() { + return mSharedElementNames; + } + + /** @hide */ + public ResultReceiver getResultReceiver() { return mTransitionReceiver; } + + /** @hide */ + public int getResultCode() { return mResultCode; } + + /** @hide */ + public Intent getResultData() { return mResultData; } + + /** @hide */ public static void abort(Bundle options) { if (options != null) { (new ActivityOptions(options)).abort(); @@ -405,29 +669,34 @@ if (otherOptions.mPackageName != null) { mPackageName = otherOptions.mPackageName; } + mTransitionReceiver = null; + mSharedElementNames = null; + mIsReturning = false; + mResultData = null; + mResultCode = 0; + mExitCoordinatorIndex = 0; + mAnimationType = otherOptions.mAnimationType; switch (otherOptions.mAnimationType) { case ANIM_CUSTOM: - mAnimationType = otherOptions.mAnimationType; mCustomEnterResId = otherOptions.mCustomEnterResId; mCustomExitResId = otherOptions.mCustomExitResId; mThumbnail = null; - if (otherOptions.mAnimationStartedListener != null) { + if (mAnimationStartedListener != null) { try { - otherOptions.mAnimationStartedListener.sendResult(null); + mAnimationStartedListener.sendResult(null); } catch (RemoteException e) { } } mAnimationStartedListener = otherOptions.mAnimationStartedListener; break; case ANIM_SCALE_UP: - mAnimationType = otherOptions.mAnimationType; mStartX = otherOptions.mStartX; mStartY = otherOptions.mStartY; - mStartWidth = otherOptions.mStartWidth; - mStartHeight = otherOptions.mStartHeight; - if (otherOptions.mAnimationStartedListener != null) { + mWidth = otherOptions.mWidth; + mHeight = otherOptions.mHeight; + if (mAnimationStartedListener != null) { try { - otherOptions.mAnimationStartedListener.sendResult(null); + mAnimationStartedListener.sendResult(null); } catch (RemoteException e) { } } @@ -435,18 +704,31 @@ break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: - mAnimationType = otherOptions.mAnimationType; + case ANIM_THUMBNAIL_ASPECT_SCALE_UP: + case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: mThumbnail = otherOptions.mThumbnail; mStartX = otherOptions.mStartX; mStartY = otherOptions.mStartY; - if (otherOptions.mAnimationStartedListener != null) { + mWidth = otherOptions.mWidth; + mHeight = otherOptions.mHeight; + if (mAnimationStartedListener != null) { try { - otherOptions.mAnimationStartedListener.sendResult(null); + mAnimationStartedListener.sendResult(null); } catch (RemoteException e) { } } mAnimationStartedListener = otherOptions.mAnimationStartedListener; break; + case ANIM_SCENE_TRANSITION: + mTransitionReceiver = otherOptions.mTransitionReceiver; + mSharedElementNames = otherOptions.mSharedElementNames; + mIsReturning = otherOptions.mIsReturning; + mThumbnail = null; + mAnimationStartedListener = null; + mResultData = otherOptions.mResultData; + mResultCode = otherOptions.mResultCode; + mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex; + break; } } @@ -459,35 +741,66 @@ * methods that take an options Bundle. */ public Bundle toBundle() { + if (mAnimationType == ANIM_DEFAULT) { + return null; + } Bundle b = new Bundle(); if (mPackageName != null) { b.putString(KEY_PACKAGE_NAME, mPackageName); } + b.putInt(KEY_ANIM_TYPE, mAnimationType); switch (mAnimationType) { case ANIM_CUSTOM: - b.putInt(KEY_ANIM_TYPE, mAnimationType); b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId); b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId); - b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener + b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener != null ? mAnimationStartedListener.asBinder() : null); break; case ANIM_SCALE_UP: - b.putInt(KEY_ANIM_TYPE, mAnimationType); b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); - b.putInt(KEY_ANIM_START_WIDTH, mStartWidth); - b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight); + b.putInt(KEY_ANIM_WIDTH, mWidth); + b.putInt(KEY_ANIM_HEIGHT, mHeight); break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: - b.putInt(KEY_ANIM_TYPE, mAnimationType); + case ANIM_THUMBNAIL_ASPECT_SCALE_UP: + case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail); b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); - b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener + b.putInt(KEY_ANIM_WIDTH, mWidth); + b.putInt(KEY_ANIM_HEIGHT, mHeight); + b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener != null ? mAnimationStartedListener.asBinder() : null); break; + case ANIM_SCENE_TRANSITION: + if (mTransitionReceiver != null) { + b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver); + } + b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning); + b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames); + b.putParcelable(KEY_RESULT_DATA, mResultData); + b.putInt(KEY_RESULT_CODE, mResultCode); + b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex); + break; } + return b; } + + /** + * Return the filtered options only meant to be seen by the target activity itself + * @hide + */ + public ActivityOptions forTargetActivity() { + if (mAnimationType == ANIM_SCENE_TRANSITION) { + final ActivityOptions result = new ActivityOptions(); + result.update(this); + return result; + } + + return null; + } + }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 156eadb..dd49009 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java
@@ -46,7 +46,8 @@ import android.hardware.display.DisplayManagerGlobal; import android.net.IConnectivityManager; import android.net.Proxy; -import android.net.ProxyProperties; +import android.net.ProxyInfo; +import android.net.Uri; import android.opengl.GLUtils; import android.os.AsyncTask; import android.os.Binder; @@ -60,6 +61,7 @@ import android.os.Message; import android.os.MessageQueue; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -75,6 +77,7 @@ import android.util.EventLog; import android.util.Log; import android.util.LogPrinter; +import android.util.Pair; import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SuperNotCalledException; @@ -90,6 +93,7 @@ import android.renderscript.RenderScript; import android.security.AndroidKeyStoreProvider; +import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.BinderInternal; import com.android.internal.os.RuntimeInit; import com.android.internal.os.SamplingProfilerIntegration; @@ -98,8 +102,6 @@ import com.android.org.conscrypt.TrustedCertificateStore; import com.google.android.collect.Lists; -import dalvik.system.VMRuntime; - import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -120,8 +122,9 @@ import libcore.io.DropBox; import libcore.io.EventLogger; import libcore.io.IoUtils; - +import libcore.net.event.NetworkEventDispatcher; import dalvik.system.CloseGuard; +import dalvik.system.VMDebug; import dalvik.system.VMRuntime; final class RemoteServiceException extends AndroidRuntimeException { @@ -188,13 +191,16 @@ /** Reference to singleton {@link ActivityThread} */ private static ActivityThread sCurrentActivityThread; Instrumentation mInstrumentation; + String mInstrumentationPackageName = null; String mInstrumentationAppDir = null; - String mInstrumentationAppLibraryDir = null; - String mInstrumentationAppPackage = null; + String[] mInstrumentationSplitAppDirs = null; + String mInstrumentationLibDir = null; String mInstrumentedAppDir = null; - String mInstrumentedAppLibraryDir = null; + String[] mInstrumentedSplitAppDirs = null; + String mInstrumentedLibDir = null; boolean mSystemThread = false; boolean mJitEnabled = false; + boolean mSomeActivitiesChanged = false; // These can be accessed by multiple threads; mPackages is the lock. // XXX For now we keep around information about all packages we have @@ -262,7 +268,9 @@ IBinder token; int ident; Intent intent; + IVoiceInteractor voiceInteractor; Bundle state; + PersistableBundle persistentState; Activity activity; Window window; Activity parent; @@ -275,9 +283,7 @@ Configuration createdConfig; ActivityClientRecord nextIdle; - String profileFile; - ParcelFileDescriptor profileFd; - boolean autoStopProfiler; + ProfilerInfo profilerInfo; ActivityInfo activityInfo; CompatibilityInfo compatInfo; @@ -311,6 +317,10 @@ return false; } + public boolean isPersistable() { + return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS; + } + public String toString() { ComponentName componentName = intent != null ? intent.getComponent() : null; return "ActivityRecord{" @@ -425,9 +435,7 @@ CompatibilityInfo compatInfo; /** Initial values for {@link Profiler}. */ - String initProfileFile; - ParcelFileDescriptor initProfileFd; - boolean initAutoStopProfiler; + ProfilerInfo initProfilerInfo; public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; @@ -437,10 +445,12 @@ static final class Profiler { String profileFile; ParcelFileDescriptor profileFd; + int samplingInterval; boolean autoStopProfiler; boolean profiling; boolean handlingProfiling; - public void setProfiler(String file, ParcelFileDescriptor fd) { + public void setProfiler(ProfilerInfo profilerInfo) { + ParcelFileDescriptor fd = profilerInfo.profileFd; if (profiling) { if (fd != null) { try { @@ -458,16 +468,18 @@ // Ignore } } - profileFile = file; + profileFile = profilerInfo.profileFile; profileFd = fd; + samplingInterval = profilerInfo.samplingInterval; + autoStopProfiler = profilerInfo.autoStopProfiler; } public void startProfiling() { if (profileFd == null || profiling) { return; } try { - Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), - 8 * 1024 * 1024, 0); + VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), + 8 * 1024 * 1024, 0, samplingInterval != 0, samplingInterval); profiling = true; } catch (RuntimeException e) { Slog.w(TAG, "Profiling failed on path " + profileFile); @@ -516,11 +528,6 @@ String who; } - static final class ProfilerControlData { - String path; - ParcelFileDescriptor fd; - } - static final class DumpHeapData { String path; ParcelFileDescriptor fd; @@ -556,11 +563,11 @@ } public final void schedulePauseActivity(IBinder token, boolean finished, - boolean userLeaving, int configChanges) { + boolean userLeaving, int configChanges, boolean dontReport) { sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token, - (userLeaving ? 1 : 0), + (userLeaving ? 1 : 0) | (dontReport ? 2 : 0), configChanges); } @@ -582,7 +589,7 @@ } public final void scheduleResumeActivity(IBinder token, int processState, - boolean isForward) { + boolean isForward, Bundle resumeArgs) { updateProcessState(processState, false); sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0); } @@ -598,9 +605,10 @@ // activity itself back to the activity manager. (matters more with ipc) public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, - int procState, Bundle state, List<ResultInfo> pendingResults, + IVoiceInteractor voiceInteractor, int procState, Bundle state, + PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { + ProfilerInfo profilerInfo) { updateProcessState(procState, false); @@ -609,9 +617,11 @@ r.token = token; r.ident = ident; r.intent = intent; + r.voiceInteractor = voiceInteractor; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; + r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; @@ -619,9 +629,7 @@ r.startsNotResumed = notResumed; r.isForward = isForward; - r.profileFile = profileName; - r.profileFd = profileFd; - r.autoStopProfiler = autoStopProfiler; + r.profilerInfo = profilerInfo; updatePendingConfiguration(curConfig); @@ -728,11 +736,10 @@ sendMessage(H.STOP_SERVICE, token); } - public final void bindApplication(String processName, - ApplicationInfo appInfo, List<ProviderInfo> providers, - ComponentName instrumentationName, String profileFile, - ParcelFileDescriptor profileFd, boolean autoStopProfiler, - Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, + public final void bindApplication(String processName, ApplicationInfo appInfo, + List<ProviderInfo> providers, ComponentName instrumentationName, + ProfilerInfo profilerInfo, Bundle instrumentationArgs, + IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, @@ -796,9 +803,7 @@ data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; - data.initProfileFile = profileFile; - data.initProfileFd = profileFd; - data.initAutoStopProfiler = false; + data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data); } @@ -810,10 +815,6 @@ sendMessage(H.SUICIDE, null); } - public void requestThumbnail(IBinder token) { - sendMessage(H.REQUEST_THUMBNAIL, token); - } - public void scheduleConfigurationChanged(Configuration config) { updatePendingConfiguration(config); sendMessage(H.CONFIGURATION_CHANGED, config); @@ -826,9 +827,12 @@ public void clearDnsCache() { // a non-standard API to get this to libcore InetAddress.clearDnsCache(); + // Allow libcore to perform the necessary actions as it sees fit upon a network + // configuration change. + NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); } - public void setHttpProxy(String host, String port, String exclList, String pacFileUrl) { + public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) { Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl); } @@ -868,12 +872,8 @@ sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); } - public void profilerControl(boolean start, String path, ParcelFileDescriptor fd, - int profileType) { - ProfilerControlData pcd = new ProfilerControlData(); - pcd.path = path; - pcd.fd = fd; - sendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType); + public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { + sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType); } public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) { @@ -1103,6 +1103,11 @@ sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0); } + public void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options) { + sendMessage(H.ON_NEW_ACTIVITY_OPTIONS, + new Pair<IBinder, ActivityOptions>(token, options)); + } + public void setProcessState(int state) { updateProcessState(state, true); } @@ -1137,6 +1142,20 @@ public final void updateTimePrefs(boolean is24Hour) { DateFormat.set24HourTimePref(is24Hour); } + + @Override + public void scheduleCancelVisibleBehind(IBinder token) { + sendMessage(H.CANCEL_VISIBLE_BEHIND, token); + } + + @Override + public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean visible) { + sendMessage(H.BACKGROUND_VISIBLE_BEHIND_CHANGED, token, visible ? 1 : 0); + } + + public void scheduleEnterAnimationComplete(IBinder token) { + sendMessage(H.ENTER_ANIMATION_COMPLETE, token); + } } private class H extends Handler { @@ -1157,7 +1176,7 @@ public static final int CREATE_SERVICE = 114; public static final int SERVICE_ARGS = 115; public static final int STOP_SERVICE = 116; - public static final int REQUEST_THUMBNAIL = 117; + public static final int CONFIGURATION_CHANGED = 118; public static final int CLEAN_UP_CONTEXT = 119; public static final int GC_WHEN_IDLE = 120; @@ -1186,6 +1205,10 @@ public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; public static final int INSTALL_PROVIDER = 145; + public static final int ON_NEW_ACTIVITY_OPTIONS = 146; + public static final int CANCEL_VISIBLE_BEHIND = 147; + public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148; + public static final int ENTER_ANIMATION_COMPLETE = 149; String codeToString(int code) { if (DEBUG_MESSAGES) { @@ -1207,7 +1230,6 @@ case CREATE_SERVICE: return "CREATE_SERVICE"; case SERVICE_ARGS: return "SERVICE_ARGS"; case STOP_SERVICE: return "STOP_SERVICE"; - case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL"; case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED"; case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT"; case GC_WHEN_IDLE: return "GC_WHEN_IDLE"; @@ -1236,6 +1258,10 @@ case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS"; case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE"; case INSTALL_PROVIDER: return "INSTALL_PROVIDER"; + case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS"; + case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND"; + case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED"; + case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE"; } } return Integer.toString(code); @@ -1245,7 +1271,7 @@ switch (msg.what) { case LAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); - ActivityClientRecord r = (ActivityClientRecord)msg.obj; + final ActivityClientRecord r = (ActivityClientRecord) msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); @@ -1260,13 +1286,15 @@ } break; case PAUSE_ACTIVITY: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); - handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); + handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2, + (msg.arg1&2) != 0); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case PAUSE_ACTIVITY_FINISHING: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); - handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); + handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2, + (msg.arg1&1) != 0); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case STOP_ACTIVITY_SHOW: @@ -1291,8 +1319,7 @@ break; case RESUME_ACTIVITY: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume"); - handleResumeActivity((IBinder)msg.obj, true, - msg.arg1 != 0, true); + handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case SEND_RESULT: @@ -1355,11 +1382,6 @@ maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; - case REQUEST_THUMBNAIL: - Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail"); - handleRequestThumbnail((IBinder)msg.obj); - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - break; case CONFIGURATION_CHANGED: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged"); mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi; @@ -1387,7 +1409,7 @@ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case PROFILER_CONTROL: - handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2); + handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2); break; case CREATE_BACKUP_AGENT: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent"); @@ -1456,6 +1478,19 @@ case INSTALL_PROVIDER: handleInstallProvider((ProviderInfo) msg.obj); break; + case ON_NEW_ACTIVITY_OPTIONS: + Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj; + onNewActivityOptions(pair.first, pair.second); + break; + case CANCEL_VISIBLE_BEHIND: + handleCancelVisibleBehind((IBinder) msg.obj); + break; + case BACKGROUND_VISIBLE_BEHIND_CHANGED: + handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0); + break; + case ENTER_ANIMATION_COMPLETE: + handleEnterAnimationComplete((IBinder) msg.obj); + break; } if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what)); } @@ -1584,11 +1619,11 @@ /** * Creates the top level resources for the given package. */ - Resources getTopLevelResources(String resDir, String[] overlayDirs, - int displayId, Configuration overrideConfiguration, + Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs, + String[] libDirs, int displayId, Configuration overrideConfiguration, LoadedApk pkgInfo) { - return mResourcesManager.getTopLevelResources(resDir, overlayDirs, displayId, - overrideConfiguration, pkgInfo.getCompatibilityInfo(), null); + return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs, + displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null); } final Handler getHandler() { @@ -1649,6 +1684,7 @@ && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid) : true); + boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0; if ((flags&(Context.CONTEXT_INCLUDE_CODE |Context.CONTEXT_IGNORE_SECURITY)) == Context.CONTEXT_INCLUDE_CODE) { @@ -1663,12 +1699,13 @@ throw new SecurityException(msg); } } - return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode); + return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode, + registerPackage); } public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) { - return getPackageInfo(ai, compatInfo, null, false, true); + return getPackageInfo(ai, compatInfo, null, false, true, false); } public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) { @@ -1684,7 +1721,8 @@ } private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { + ClassLoader baseLoader, boolean securityViolation, boolean includeCode, + boolean registerPackage) { synchronized (mResourcesManager) { WeakReference<LoadedApk> ref; if (includeCode) { @@ -1703,7 +1741,7 @@ packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader, securityViolation, includeCode && - (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0); + (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); if (includeCode) { mPackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo)); @@ -1760,9 +1798,13 @@ } } - public void installSystemApplicationInfo(ApplicationInfo info) { + public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { synchronized (this) { - getSystemContext().installSystemApplicationInfo(info); + getSystemContext().installSystemApplicationInfo(info, classLoader); + + // The code package for "android" in the system server needs + // to be the system context's package. + mPackages.put("android", new WeakReference<LoadedApk>(getSystemContext().mPackageInfo)); // give ourselves a default profiler mProfiler = new Profiler(); @@ -1901,7 +1943,7 @@ if (dumpFullInfo) { printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private", "Shared", "Private", "Swapped", "Heap", "Heap", "Heap"); - printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty", + printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "", "Clean", "Clean", "Dirty", "Size", "Alloc", "Free"); printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------", "------", "------", "------", "------", "------", "------"); @@ -2158,6 +2200,7 @@ cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); + r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } @@ -2188,7 +2231,8 @@ + r.activityInfo.name + " with config " + config); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, - r.embeddedID, r.lastNonConfigurationInstances, config); + r.embeddedID, r.lastNonConfigurationInstances, config, + r.voiceInteractor); if (customIntent != null) { activity.mIntent = customIntent; @@ -2201,7 +2245,11 @@ } activity.mCalled = false; - mInstrumentation.callActivityOnCreate(activity, r.state); + if (r.isPersistable()) { + mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); + } else { + mInstrumentation.callActivityOnCreate(activity, r.state); + } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + @@ -2214,13 +2262,23 @@ r.stopped = false; } if (!r.activity.mFinished) { - if (r.state != null) { + if (r.isPersistable()) { + if (r.state != null || r.persistentState != null) { + mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, + r.persistentState); + } + } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } if (!r.activity.mFinished) { activity.mCalled = false; - mInstrumentation.callActivityOnPostCreate(activity, r.state); + if (r.isPersistable()) { + mInstrumentation.callActivityOnPostCreate(activity, r.state, + r.persistentState); + } else { + mInstrumentation.callActivityOnPostCreate(activity, r.state); + } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + @@ -2286,11 +2344,11 @@ // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); + mSomeActivitiesChanged = true; - if (r.profileFd != null) { - mProfiler.setProfiler(r.profileFile, r.profileFd); + if (r.profilerInfo != null) { + mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); - mProfiler.autoStopProfiler = r.autoStopProfiler; } // Make sure we are running with the most recent config. @@ -2298,6 +2356,7 @@ if (localLOGV) Slog.v( TAG, "Handling launch of " + r); + Activity a = performLaunchActivity(r, customIntent); if (a != null) { @@ -2353,7 +2412,7 @@ // manager to stop us. try { ActivityManagerNative.getDefault() - .finishActivity(r.token, Activity.RESULT_CANCELED, null); + .finishActivity(r.token, Activity.RESULT_CANCELED, null, false); } catch (RemoteException ex) { // Ignore } @@ -2366,6 +2425,7 @@ for (int i=0; i<N; i++) { Intent intent = intents.get(i); intent.setExtrasClassLoader(r.activity.getClassLoader()); + intent.prepareToEnterProcess(); r.activity.mFragments.noteStateNotSaved(); mInstrumentation.callActivityOnNewIntent(r.activity, intent); } @@ -2416,10 +2476,53 @@ } } + public void onNewActivityOptions(IBinder token, ActivityOptions options) { + ActivityClientRecord r = mActivities.get(token); + if (r != null) { + r.activity.onNewActivityOptions(options); + } + } + + public void handleCancelVisibleBehind(IBinder token) { + ActivityClientRecord r = mActivities.get(token); + if (r != null) { + mSomeActivitiesChanged = true; + final Activity activity = r.activity; + if (activity.mVisibleBehind) { + activity.mCalled = false; + activity.onVisibleBehindCanceled(); + // Tick, tick, tick. The activity has 500 msec to return or it will be destroyed. + if (!activity.mCalled) { + throw new SuperNotCalledException("Activity " + activity.getLocalClassName() + + " did not call through to super.onVisibleBehindCanceled()"); + } + activity.mVisibleBehind = false; + } + } + try { + ActivityManagerNative.getDefault().backgroundResourcesReleased(token); + } catch (RemoteException e) { + } + } + + public void handleOnBackgroundVisibleBehindChanged(IBinder token, boolean visible) { + ActivityClientRecord r = mActivities.get(token); + if (r != null) { + r.activity.onBackgroundVisibleBehindChanged(visible); + } + } + public void handleInstallProvider(ProviderInfo info) { installContentProviders(mInitialApplication, Lists.newArrayList(info)); } + private void handleEnterAnimationComplete(IBinder token) { + ActivityClientRecord r = mActivities.get(token); + if (r != null) { + r.activity.onEnterAnimationComplete(); + } + } + private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>(); /** @@ -2447,6 +2550,7 @@ try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); data.intent.setExtrasClassLoader(cl); + data.intent.prepareToEnterProcess(); data.setExtrasClassLoader(cl); receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); } catch (Exception e) { @@ -2521,15 +2625,7 @@ return; } - if (mBackupAgents.get(packageName) != null) { - Slog.d(TAG, "BackupAgent " + " for " + packageName - + " already exists"); - return; - } - - BackupAgent agent = null; String classname = data.appInfo.backupAgentName; - // full backup operation but no app-supplied agent? use the default implementation if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) { @@ -2538,29 +2634,38 @@ try { IBinder binder = null; - try { - if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); - - java.lang.ClassLoader cl = packageInfo.getClassLoader(); - agent = (BackupAgent) cl.loadClass(classname).newInstance(); - - // set up the agent's context - ContextImpl context = ContextImpl.createAppContext(this, packageInfo); - context.setOuterContext(agent); - agent.attach(context); - - agent.onCreate(); - binder = agent.onBind(); - mBackupAgents.put(packageName, agent); - } catch (Exception e) { - // If this is during restore, fail silently; otherwise go - // ahead and let the user see the crash. - Slog.e(TAG, "Agent threw during creation: " + e); - if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE - && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) { - throw e; + BackupAgent agent = mBackupAgents.get(packageName); + if (agent != null) { + // reusing the existing instance + if (DEBUG_BACKUP) { + Slog.v(TAG, "Reusing existing agent instance"); } - // falling through with 'binder' still null + binder = agent.onBind(); + } else { + try { + if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); + + java.lang.ClassLoader cl = packageInfo.getClassLoader(); + agent = (BackupAgent) cl.loadClass(classname).newInstance(); + + // set up the agent's context + ContextImpl context = ContextImpl.createAppContext(this, packageInfo); + context.setOuterContext(agent); + agent.attach(context); + + agent.onCreate(); + binder = agent.onBind(); + mBackupAgents.put(packageName, agent); + } catch (Exception e) { + // If this is during restore, fail silently; otherwise go + // ahead and let the user see the crash. + Slog.e(TAG, "Agent threw during creation: " + e); + if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE + && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) { + throw e; + } + // falling through with 'binder' still null + } } // tell the OS that we're live now @@ -2647,6 +2752,7 @@ if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); + data.intent.prepareToEnterProcess(); try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); @@ -2675,6 +2781,7 @@ if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); + data.intent.prepareToEnterProcess(); boolean doRebind = s.onUnbind(data.intent); try { if (doRebind) { @@ -2750,6 +2857,7 @@ try { if (data.args != null) { data.args.setExtrasClassLoader(s.getClassLoader()); + data.args.prepareToEnterProcess(); } int res; if (!data.taskRemoved) { @@ -2837,6 +2945,7 @@ r.paused = false; r.stopped = false; r.state = null; + r.persistentState = null; } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( @@ -2862,12 +2971,14 @@ r.mPendingRemoveWindowManager = null; } - final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, - boolean reallyResume) { + final void handleResumeActivity(IBinder token, + boolean clearHide, boolean isForward, boolean reallyResume) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); + mSomeActivitiesChanged = true; + // TODO Push resumeArgs into the activity for consideration ActivityClientRecord r = performResumeActivity(token, clearHide); if (r != null) { @@ -2973,7 +3084,7 @@ // just end this activity. try { ActivityManagerNative.getDefault() - .finishActivity(token, Activity.RESULT_CANCELED, null); + .finishActivity(token, Activity.RESULT_CANCELED, null, false); } catch (RemoteException ex) { } } @@ -2992,11 +3103,10 @@ int h; if (w < 0) { Resources res = r.activity.getResources(); - mThumbnailHeight = h = - res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); - - mThumbnailWidth = w = - res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); + int wId = com.android.internal.R.dimen.thumbnail_width; + int hId = com.android.internal.R.dimen.thumbnail_height; + mThumbnailWidth = w = res.getDimensionPixelSize(wId); + mThumbnailHeight = h = res.getDimensionPixelSize(hId); } else { h = mThumbnailHeight; } @@ -3037,7 +3147,7 @@ } private void handlePauseActivity(IBinder token, boolean finished, - boolean userLeaving, int configChanges) { + boolean userLeaving, int configChanges, boolean dontReport) { ActivityClientRecord r = mActivities.get(token); if (r != null) { //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); @@ -3054,10 +3164,13 @@ } // Tell the activity manager we have paused. - try { - ActivityManagerNative.getDefault().activityPaused(token); - } catch (RemoteException ex) { + if (!dontReport) { + try { + ActivityManagerNative.getDefault().activityPaused(token); + } catch (RemoteException ex) { + } } + mSomeActivitiesChanged = true; } } @@ -3085,17 +3198,13 @@ + r.intent.getComponent().toShortString()); Slog.e(TAG, e.getMessage(), e); } - Bundle state = null; if (finished) { r.activity.mFinished = true; } try { // Next have the activity save its current state and managed dialogs... if (!r.activity.mFinished && saveState) { - state = new Bundle(); - state.setAllowFds(false); - mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); - r.state = state; + callCallActivityOnSaveInstanceState(r); } // Now we are idle. r.activity.mCalled = false; @@ -3131,7 +3240,7 @@ listeners.get(i).onPaused(r.activity); } - return state; + return !r.activity.mFinished && saveState ? r.state : null; } final void performStopActivity(IBinder token, boolean saveState) { @@ -3142,7 +3251,7 @@ private static class StopInfo implements Runnable { ActivityClientRecord activity; Bundle state; - Bitmap thumbnail; + PersistableBundle persistentState; CharSequence description; @Override public void run() { @@ -3150,7 +3259,7 @@ try { if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity); ActivityManagerNative.getDefault().activityStopped( - activity.token, state, thumbnail, description); + activity.token, state, persistentState, description); } catch (RemoteException ex) { } } @@ -3189,7 +3298,6 @@ private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown, boolean saveState) { if (localLOGV) Slog.v(TAG, "Performing stop of " + r); - Bundle state = null; if (r != null) { if (!keepShown && r.stopped) { if (r.activity.mFinished) { @@ -3209,7 +3317,6 @@ // First create a thumbnail for the activity... // For now, don't create the thumbnail here; we are // doing that by doing a screen snapshot. - info.thumbnail = null; //createThumbnailBitmap(r); info.description = r.activity.onCreateDescription(); } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { @@ -3224,12 +3331,7 @@ // Next have the activity save its current state and managed dialogs... if (!r.activity.mFinished && saveState) { if (r.state == null) { - state = new Bundle(); - state.setAllowFds(false); - mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); - r.state = state; - } else { - state = r.state; + callCallActivityOnSaveInstanceState(r); } } @@ -3305,7 +3407,9 @@ // manager to proceed and allow us to go fully into the background. info.activity = r; info.state = r.state; + info.persistentState = r.persistentState; mH.post(info); + mSomeActivitiesChanged = true; } final void performRestartActivity(IBinder token) { @@ -3339,6 +3443,7 @@ TAG, "Handle window " + r + " visibility: " + show); updateVisibility(r, show); } + mSomeActivitiesChanged = true; } private void handleSleeping(IBinder token, boolean sleeping) { @@ -3387,6 +3492,20 @@ synchronized (mResourcesManager) { mCoreSettings = coreSettings; } + onCoreSettingsChange(); + } + + private void onCoreSettingsChange() { + boolean debugViewAttributes = + mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; + if (debugViewAttributes != View.mDebugViewAttributes) { + View.mDebugViewAttributes = debugViewAttributes; + + // request all activities to relaunch for the changes to take place + for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { + requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, false); + } + } } private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) { @@ -3409,6 +3528,7 @@ try { if (ri.mData != null) { ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); + ri.mData.prepareToEnterProcess(); } if (DEBUG_RESULTS) Slog.v(TAG, "Delivering result to activity " + r + " : " + ri); @@ -3621,6 +3741,7 @@ // If the system process has died, it's game over for everyone. } } + mSomeActivitiesChanged = true; } public final void requestRelaunchActivity(IBinder token, @@ -3683,6 +3804,7 @@ // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); + mSomeActivitiesChanged = true; Configuration changedConfig = null; int configChanges = 0; @@ -3761,9 +3883,7 @@ performPauseActivity(r.token, false, r.isPreHoneycomb()); } if (r.state == null && !r.stopped && !r.isPreHoneycomb()) { - r.state = new Bundle(); - r.state.setAllowFds(false); - mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); + callCallActivityOnSaveInstanceState(r); } handleDestroyActivity(r.token, false, configChanges, true); @@ -3792,25 +3912,15 @@ handleLaunchActivity(r, currentIntent); } - private void handleRequestThumbnail(IBinder token) { - ActivityClientRecord r = mActivities.get(token); - Bitmap thumbnail = createThumbnailBitmap(r); - CharSequence description = null; - try { - description = r.activity.onCreateDescription(); - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to create description of activity " - + r.intent.getComponent().toShortString() - + ": " + e.toString(), e); - } - } - //System.out.println("Reporting top thumbnail " + thumbnail); - try { - ActivityManagerNative.getDefault().reportThumbnail( - token, thumbnail, description); - } catch (RemoteException ex) { + private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) { + r.state = new Bundle(); + r.state.setAllowFds(false); + if (r.isPersistable()) { + r.persistentState = new PersistableBundle(); + mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state, + r.persistentState); + } else { + mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); } } @@ -3964,9 +4074,6 @@ ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config); - // Cleanup hardware accelerated stuff - WindowManagerGlobal.getInstance().trimLocalMemory(); - freeTextLayoutCachesIfNeeded(configDiff); if (callbacks != null) { @@ -4000,24 +4107,25 @@ performConfigurationChanged(r.activity, mCompatConfiguration); freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration)); + + mSomeActivitiesChanged = true; } - final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) { + final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { if (start) { try { switch (profileType) { - default: - mProfiler.setProfiler(pcd.path, pcd.fd); - mProfiler.autoStopProfiler = false; + default: + mProfiler.setProfiler(profilerInfo); mProfiler.startProfiling(); break; } } catch (RuntimeException e) { - Slog.w(TAG, "Profiling failed on path " + pcd.path + Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile + " -- can the process access this path?"); } finally { try { - pcd.fd.close(); + profilerInfo.profileFd.close(); } catch (IOException e) { Slog.w(TAG, "Failure closing profile fd", e); } @@ -4101,9 +4209,6 @@ final void handleTrimMemory(int level) { if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level); - final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance(); - windowManager.startTrimMemory(level); - ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null); final int N = callbacks.size(); @@ -4111,7 +4216,7 @@ callbacks.get(i).onTrimMemory(level); } - windowManager.endTrimMemory(); + WindowManagerGlobal.getInstance().trimMemory(level); } private void setupGraphicsSupport(LoadedApk info, File cacheDir) { @@ -4152,9 +4257,12 @@ mCompatConfiguration = new Configuration(data.config); mProfiler = new Profiler(); - mProfiler.profileFile = data.initProfileFile; - mProfiler.profileFd = data.initProfileFd; - mProfiler.autoStopProfiler = data.initAutoStopProfiler; + if (data.initProfilerInfo != null) { + mProfiler.profileFile = data.initProfilerInfo.profileFile; + mProfiler.profileFd = data.initProfilerInfo.profileFd; + mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; + mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; + } // send up app name; do this *before* waiting for debugger Process.setArgV0(data.processName); @@ -4169,7 +4277,7 @@ HardwareRenderer.disable(false); } } - + if (mProfiler.profileFd != null) { mProfiler.startProfiling(); } @@ -4182,6 +4290,8 @@ AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + Message.updateCheckRecycle(data.appInfo.targetSdkVersion); + /* * Before spawning a new process, reset the time zone to be the system time zone. * This needs to be done because the system time zone could have changed after the @@ -4234,6 +4344,9 @@ final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); DateFormat.set24HourTimePref(is24Hr); + View.mDebugViewAttributes = + mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; + /** * For system applications on userdebug/eng builds, log stack * traces of disk and network access to dropbox for analysis. @@ -4300,8 +4413,8 @@ // crash if we can't get it. IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { - ProxyProperties proxyProperties = service.getProxy(); - Proxy.setHttpProxySystemProperty(proxyProperties); + ProxyInfo proxyInfo = service.getProxy(); + Proxy.setHttpProxySystemProperty(proxyInfo); } catch (RemoteException e) {} } @@ -4318,20 +4431,24 @@ + data.instrumentationName); } + mInstrumentationPackageName = ii.packageName; mInstrumentationAppDir = ii.sourceDir; - mInstrumentationAppLibraryDir = ii.nativeLibraryDir; - mInstrumentationAppPackage = ii.packageName; + mInstrumentationSplitAppDirs = ii.splitSourceDirs; + mInstrumentationLibDir = ii.nativeLibraryDir; mInstrumentedAppDir = data.info.getAppDir(); - mInstrumentedAppLibraryDir = data.info.getLibDir(); + mInstrumentedSplitAppDirs = data.info.getSplitAppDirs(); + mInstrumentedLibDir = data.info.getLibDir(); ApplicationInfo instrApp = new ApplicationInfo(); instrApp.packageName = ii.packageName; instrApp.sourceDir = ii.sourceDir; instrApp.publicSourceDir = ii.publicSourceDir; + instrApp.splitSourceDirs = ii.splitSourceDirs; + instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs; instrApp.dataDir = ii.dataDir; instrApp.nativeLibraryDir = ii.nativeLibraryDir; LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, - appContext.getClassLoader(), false, true); + appContext.getClassLoader(), false, true, false); ContextImpl instrContext = ContextImpl.createAppContext(this, pi); try { @@ -4934,25 +5051,44 @@ android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); - IActivityManager mgr = ActivityManagerNative.getDefault(); + final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } + // Watch for getting close to heap limit. + BinderInternal.addGcWatcher(new Runnable() { + @Override public void run() { + if (!mSomeActivitiesChanged) { + return; + } + Runtime runtime = Runtime.getRuntime(); + long dalvikMax = runtime.maxMemory(); + long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); + if (dalvikUsed > ((3*dalvikMax)/4)) { + if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + + " total=" + (runtime.totalMemory()/1024) + + " used=" + (dalvikUsed/1024)); + mSomeActivitiesChanged = false; + try { + mgr.releaseSomeActivities(mAppThread); + } catch (RemoteException e) { + } + } + } + }); } else { // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. android.ddm.DdmHandleAppName.setAppName("system_process", - UserHandle.myUserId()); + UserHandle.myUserId()); try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); - Application app = Instrumentation.newApplication(Application.class, context); - mAllApplications.add(app); - mInitialApplication = app; - app.onCreate(); + mInitialApplication = context.mPackageInfo.makeApplication(true, null); + mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); @@ -4991,7 +5127,14 @@ } public static ActivityThread systemMain() { - HardwareRenderer.disable(true); + // The system process on low-memory devices do not get to use hardware + // accelerated drawing, since this can add too much overhead to the + // process. + if (!ActivityManager.isHighEndGfx()) { + HardwareRenderer.disable(true); + } else { + HardwareRenderer.enableForegroundTrimming(); + } ActivityThread thread = new ActivityThread(); thread.attach(true); return thread;
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java new file mode 100644 index 0000000..540376e --- /dev/null +++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -0,0 +1,864 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Bundle; +import android.os.Handler; +import android.os.Parcelable; +import android.os.ResultReceiver; +import android.transition.Transition; +import android.transition.TransitionSet; +import android.util.ArrayMap; +import android.view.GhostView; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroupOverlay; +import android.view.ViewParent; +import android.view.ViewTreeObserver; +import android.view.Window; +import android.widget.ImageView; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Base class for ExitTransitionCoordinator and EnterTransitionCoordinator, classes + * that manage activity transitions and the communications coordinating them between + * Activities. The ExitTransitionCoordinator is created in the + * ActivityOptions#makeSceneTransitionAnimation. The EnterTransitionCoordinator + * is created by ActivityOptions#createEnterActivityTransition by Activity when the window is + * attached. + * + * Typical startActivity goes like this: + * 1) ExitTransitionCoordinator created with ActivityOptions#makeSceneTransitionAnimation + * 2) Activity#startActivity called and that calls startExit() through + * ActivityOptions#dispatchStartExit + * - Exit transition starts by setting transitioning Views to INVISIBLE + * 3) Launched Activity starts, creating an EnterTransitionCoordinator. + * - The Window is made translucent + * - The Window background alpha is set to 0 + * - The transitioning views are made INVISIBLE + * - MSG_SET_LISTENER is sent back to the ExitTransitionCoordinator. + * 4) The shared element transition completes. + * - MSG_TAKE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator + * 5) The MSG_TAKE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator. + * - Shared elements are made VISIBLE + * - Shared elements positions and size are set to match the end state of the calling + * Activity. + * - The shared element transition is started + * - If the window allows overlapping transitions, the views transition is started by setting + * the entering Views to VISIBLE and the background alpha is animated to opaque. + * - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator + * 6) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator + * - The shared elements are made INVISIBLE + * 7) The exit transition completes in the calling Activity. + * - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator. + * 8) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator. + * - If the window doesn't allow overlapping enter transitions, the enter transition is started + * by setting entering views to VISIBLE and the background is animated to opaque. + * 9) The background opacity animation completes. + * - The window is made opaque + * 10) The calling Activity gets an onStop() call + * - onActivityStopped() is called and all exited Views are made VISIBLE. + * + * Typical finishAfterTransition goes like this: + * 1) finishAfterTransition() creates an ExitTransitionCoordinator and calls startExit() + * - The Window start transitioning to Translucent with a new ActivityOptions. + * - If no background exists, a black background is substituted + * - The shared elements in the scene are matched against those shared elements + * that were sent by comparing the names. + * - The exit transition is started by setting Views to INVISIBLE. + * 2) The ActivityOptions is received by the Activity and an EnterTransitionCoordinator is created. + * - All transitioning views are made VISIBLE to reverse what was done when onActivityStopped() + * was called + * 3) The Window is made translucent and a callback is received + * - The background alpha is animated to 0 + * 4) The background alpha animation completes + * 5) The shared element transition completes + * - After both 4 & 5 complete, MSG_TAKE_SHARED_ELEMENTS is sent to the + * EnterTransitionCoordinator + * 6) MSG_TAKE_SHARED_ELEMENTS is received by EnterTransitionCoordinator + * - Shared elements are made VISIBLE + * - Shared elements positions and size are set to match the end state of the calling + * Activity. + * - The shared element transition is started + * - If the window allows overlapping transitions, the views transition is started by setting + * the entering Views to VISIBLE. + * - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator + * 7) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator + * - The shared elements are made INVISIBLE + * 8) The exit transition completes in the finishing Activity. + * - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator. + * - finish() is called on the exiting Activity + * 9) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator. + * - If the window doesn't allow overlapping enter transitions, the enter transition is started + * by setting entering views to VISIBLE. + */ +abstract class ActivityTransitionCoordinator extends ResultReceiver { + private static final String TAG = "ActivityTransitionCoordinator"; + + /** + * For Activity transitions, the called Activity's listener to receive calls + * when transitions complete. + */ + static final String KEY_REMOTE_RECEIVER = "android:remoteReceiver"; + + protected static final String KEY_SCREEN_LEFT = "shared_element:screenLeft"; + protected static final String KEY_SCREEN_TOP = "shared_element:screenTop"; + protected static final String KEY_SCREEN_RIGHT = "shared_element:screenRight"; + protected static final String KEY_SCREEN_BOTTOM= "shared_element:screenBottom"; + protected static final String KEY_TRANSLATION_Z = "shared_element:translationZ"; + protected static final String KEY_SNAPSHOT = "shared_element:bitmap"; + protected static final String KEY_SCALE_TYPE = "shared_element:scaleType"; + protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix"; + protected static final String KEY_ELEVATION = "shared_element:elevation"; + + protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values(); + + /** + * Sent by the exiting coordinator (either EnterTransitionCoordinator + * or ExitTransitionCoordinator) after the shared elements have + * become stationary (shared element transition completes). This tells + * the remote coordinator to take control of the shared elements and + * that animations may begin. The remote Activity won't start entering + * until this message is received, but may wait for + * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true. + */ + public static final int MSG_SET_REMOTE_RECEIVER = 100; + + /** + * Sent by the entering coordinator to tell the exiting coordinator + * to hide its shared elements after it has started its shared + * element transition. This is temporary until the + * interlock of shared elements is figured out. + */ + public static final int MSG_HIDE_SHARED_ELEMENTS = 101; + + /** + * Sent by the exiting coordinator (either EnterTransitionCoordinator + * or ExitTransitionCoordinator) after the shared elements have + * become stationary (shared element transition completes). This tells + * the remote coordinator to take control of the shared elements and + * that animations may begin. The remote Activity won't start entering + * until this message is received, but may wait for + * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true. + */ + public static final int MSG_TAKE_SHARED_ELEMENTS = 103; + + /** + * Sent by the exiting coordinator (either + * EnterTransitionCoordinator or ExitTransitionCoordinator) after + * the exiting Views have finished leaving the scene. This will + * be ignored if allowOverlappingTransitions() is true on the + * remote coordinator. If it is false, it will trigger the enter + * transition to start. + */ + public static final int MSG_EXIT_TRANSITION_COMPLETE = 104; + + /** + * Sent by Activity#startActivity to begin the exit transition. + */ + public static final int MSG_START_EXIT_TRANSITION = 105; + + /** + * It took too long for a message from the entering Activity, so we canceled the transition. + */ + public static final int MSG_CANCEL = 106; + + /** + * When returning, this is the destination location for the shared element. + */ + public static final int MSG_SHARED_ELEMENT_DESTINATION = 107; + + /** + * Send the shared element positions. + */ + public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108; + + private Window mWindow; + final protected ArrayList<String> mAllSharedElementNames; + final protected ArrayList<View> mSharedElements = new ArrayList<View>(); + final protected ArrayList<String> mSharedElementNames = new ArrayList<String>(); + protected ArrayList<View> mTransitioningViews = new ArrayList<View>(); + protected SharedElementCallback mListener; + protected ResultReceiver mResultReceiver; + final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback(); + final protected boolean mIsReturning; + private Runnable mPendingTransition; + private boolean mIsStartingTransition; + private ArrayList<GhostViewListeners> mGhostViewListeners = + new ArrayList<GhostViewListeners>(); + private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>(); + + public ActivityTransitionCoordinator(Window window, + ArrayList<String> allSharedElementNames, + SharedElementCallback listener, boolean isReturning) { + super(new Handler()); + mWindow = window; + mListener = listener; + mAllSharedElementNames = allSharedElementNames; + mIsReturning = isReturning; + } + + protected void viewsReady(ArrayMap<String, View> sharedElements) { + sharedElements.retainAll(mAllSharedElementNames); + if (mListener != null) { + mListener.onMapSharedElements(mAllSharedElementNames, sharedElements); + } + mSharedElementNames.addAll(sharedElements.keySet()); + mSharedElements.addAll(sharedElements.values()); + if (getViewsTransition() != null && mTransitioningViews != null) { + ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.captureTransitioningViews(mTransitioningViews); + } + mTransitioningViews.removeAll(mSharedElements); + } + setEpicenter(); + } + + protected void stripOffscreenViews() { + if (mTransitioningViews == null) { + return; + } + Rect r = new Rect(); + for (int i = mTransitioningViews.size() - 1; i >= 0; i--) { + View view = mTransitioningViews.get(i); + if (!view.getGlobalVisibleRect(r)) { + mTransitioningViews.remove(i); + showView(view, true); + } + } + } + + protected Window getWindow() { + return mWindow; + } + + public ViewGroup getDecor() { + return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView(); + } + + /** + * Sets the transition epicenter to the position of the first shared element. + */ + protected void setEpicenter() { + View epicenter = null; + if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) { + int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0)); + if (index >= 0) { + epicenter = mSharedElements.get(index); + } + } + setEpicenter(epicenter); + } + + private void setEpicenter(View view) { + if (view == null) { + mEpicenterCallback.setEpicenter(null); + } else { + Rect epicenter = new Rect(); + view.getBoundsOnScreen(epicenter); + mEpicenterCallback.setEpicenter(epicenter); + } + } + + public ArrayList<String> getAcceptedNames() { + return mSharedElementNames; + } + + public ArrayList<String> getMappedNames() { + ArrayList<String> names = new ArrayList<String>(mSharedElements.size()); + for (int i = 0; i < mSharedElements.size(); i++) { + names.add(mSharedElements.get(i).getTransitionName()); + } + return names; + } + + public ArrayList<View> copyMappedViews() { + return new ArrayList<View>(mSharedElements); + } + + public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; } + + protected Transition setTargets(Transition transition, boolean add) { + if (transition == null || (add && + (mTransitioningViews == null || mTransitioningViews.isEmpty()))) { + return null; + } + // Add the targets to a set containing transition so that transition + // remains unaffected. We don't want to modify the targets of transition itself. + TransitionSet set = new TransitionSet(); + if (mTransitioningViews != null) { + for (int i = mTransitioningViews.size() - 1; i >= 0; i--) { + View view = mTransitioningViews.get(i); + if (add) { + set.addTarget(view); + } else { + set.excludeTarget(view, true); + } + } + } + // By adding the transition after addTarget, we prevent addTarget from + // affecting transition. + set.addTransition(transition); + + if (!add && mTransitioningViews != null && !mTransitioningViews.isEmpty()) { + // Allow children of excluded transitioning views, but not the views themselves + set = new TransitionSet().addTransition(set); + } + + return set; + } + + protected Transition configureTransition(Transition transition, + boolean includeTransitioningViews) { + if (transition != null) { + transition = transition.clone(); + transition.setEpicenterCallback(mEpicenterCallback); + transition = setTargets(transition, includeTransitioningViews); + } + return transition; + } + + protected static Transition mergeTransitions(Transition transition1, Transition transition2) { + if (transition1 == null) { + return transition2; + } else if (transition2 == null) { + return transition1; + } else { + TransitionSet transitionSet = new TransitionSet(); + transitionSet.addTransition(transition1); + transitionSet.addTransition(transition2); + return transitionSet; + } + } + + protected ArrayMap<String, View> mapSharedElements(ArrayList<String> accepted, + ArrayList<View> localViews) { + ArrayMap<String, View> sharedElements = new ArrayMap<String, View>(); + if (accepted != null) { + for (int i = 0; i < accepted.size(); i++) { + sharedElements.put(accepted.get(i), localViews.get(i)); + } + } else { + ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.findNamedViews(sharedElements); + } + } + return sharedElements; + } + + protected void setResultReceiver(ResultReceiver resultReceiver) { + mResultReceiver = resultReceiver; + } + + protected abstract Transition getViewsTransition(); + + private void setSharedElementState(View view, String name, Bundle transitionArgs, + Matrix tempMatrix, RectF tempRect, int[] decorLoc) { + Bundle sharedElementBundle = transitionArgs.getBundle(name); + if (sharedElementBundle == null) { + return; + } + + if (view instanceof ImageView) { + int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1); + if (scaleTypeInt >= 0) { + ImageView imageView = (ImageView) view; + ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt]; + imageView.setScaleType(scaleType); + if (scaleType == ImageView.ScaleType.MATRIX) { + float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX); + tempMatrix.setValues(matrixValues); + imageView.setImageMatrix(tempMatrix); + } + } + } + + float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z); + view.setTranslationZ(z); + float elevation = sharedElementBundle.getFloat(KEY_ELEVATION); + view.setElevation(elevation); + + float left = sharedElementBundle.getFloat(KEY_SCREEN_LEFT); + float top = sharedElementBundle.getFloat(KEY_SCREEN_TOP); + float right = sharedElementBundle.getFloat(KEY_SCREEN_RIGHT); + float bottom = sharedElementBundle.getFloat(KEY_SCREEN_BOTTOM); + + if (decorLoc != null) { + left -= decorLoc[0]; + top -= decorLoc[1]; + right -= decorLoc[0]; + bottom -= decorLoc[1]; + } else { + // Find the location in the view's parent + getSharedElementParentMatrix(view, tempMatrix); + tempRect.set(left, top, right, bottom); + tempMatrix.mapRect(tempRect); + + float leftInParent = tempRect.left; + float topInParent = tempRect.top; + + // Find the size of the view + view.getInverseMatrix().mapRect(tempRect); + float width = tempRect.width(); + float height = tempRect.height(); + + // Now determine the offset due to view transform: + view.setLeft(0); + view.setTop(0); + view.setRight(Math.round(width)); + view.setBottom(Math.round(height)); + tempRect.set(0, 0, width, height); + view.getMatrix().mapRect(tempRect); + + ViewGroup parent = (ViewGroup) view.getParent(); + left = leftInParent - tempRect.left + parent.getScrollX(); + top = topInParent - tempRect.top + parent.getScrollY(); + right = left + width; + bottom = top + height; + } + + int x = Math.round(left); + int y = Math.round(top); + int width = Math.round(right) - x; + int height = Math.round(bottom) - y; + int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY); + int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); + view.measure(widthSpec, heightSpec); + + view.layout(x, y, x + width, y + height); + } + + protected void getSharedElementParentMatrix(View view, Matrix matrix) { + // Find the location in the view's parent + ViewGroup parent = (ViewGroup) view.getParent(); + matrix.reset(); + parent.transformMatrixToLocal(matrix); + } + + protected ArrayList<SharedElementOriginalState> setSharedElementState( + Bundle sharedElementState, final ArrayList<View> snapshots) { + ArrayList<SharedElementOriginalState> originalImageState = + new ArrayList<SharedElementOriginalState>(); + if (sharedElementState != null) { + Matrix tempMatrix = new Matrix(); + RectF tempRect = new RectF(); + final int numSharedElements = mSharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + View sharedElement = mSharedElements.get(i); + String name = mSharedElementNames.get(i); + SharedElementOriginalState originalState = getOldSharedElementState(sharedElement, + name, sharedElementState); + originalImageState.add(originalState); + setSharedElementState(sharedElement, name, sharedElementState, + tempMatrix, tempRect, null); + } + } + if (mListener != null) { + mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots); + } + return originalImageState; + } + + protected void notifySharedElementEnd(ArrayList<View> snapshots) { + if (mListener != null) { + mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots); + } + } + + protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) { + final View decorView = getDecor(); + if (decorView != null) { + decorView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + decorView.getViewTreeObserver().removeOnPreDrawListener(this); + notifySharedElementEnd(snapshots); + return true; + } + } + ); + } + } + + private static SharedElementOriginalState getOldSharedElementState(View view, String name, + Bundle transitionArgs) { + + SharedElementOriginalState state = new SharedElementOriginalState(); + state.mLeft = view.getLeft(); + state.mTop = view.getTop(); + state.mRight = view.getRight(); + state.mBottom = view.getBottom(); + state.mMeasuredWidth = view.getMeasuredWidth(); + state.mMeasuredHeight = view.getMeasuredHeight(); + state.mTranslationZ = view.getTranslationZ(); + state.mElevation = view.getElevation(); + if (!(view instanceof ImageView)) { + return state; + } + Bundle bundle = transitionArgs.getBundle(name); + if (bundle == null) { + return state; + } + int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1); + if (scaleTypeInt < 0) { + return state; + } + + ImageView imageView = (ImageView) view; + state.mScaleType = imageView.getScaleType(); + if (state.mScaleType == ImageView.ScaleType.MATRIX) { + state.mMatrix = new Matrix(imageView.getImageMatrix()); + } + return state; + } + + protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) { + int numSharedElements = names.size(); + if (numSharedElements == 0) { + return null; + } + ArrayList<View> snapshots = new ArrayList<View>(numSharedElements); + Context context = getWindow().getContext(); + int[] decorLoc = new int[2]; + ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.getLocationOnScreen(decorLoc); + } + for (String name: names) { + Bundle sharedElementBundle = state.getBundle(name); + if (sharedElementBundle != null) { + Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT); + View snapshot = null; + if (parcelable != null && mListener != null) { + snapshot = mListener.onCreateSnapshotView(context, parcelable); + } + if (snapshot != null) { + setSharedElementState(snapshot, name, state, null, null, decorLoc); + } + snapshots.add(snapshot); + } + } + return snapshots; + } + + protected static void setOriginalSharedElementState(ArrayList<View> sharedElements, + ArrayList<SharedElementOriginalState> originalState) { + for (int i = 0; i < originalState.size(); i++) { + View view = sharedElements.get(i); + SharedElementOriginalState state = originalState.get(i); + if (view instanceof ImageView && state.mScaleType != null) { + ImageView imageView = (ImageView) view; + imageView.setScaleType(state.mScaleType); + if (state.mScaleType == ImageView.ScaleType.MATRIX) { + imageView.setImageMatrix(state.mMatrix); + } + } + view.setElevation(state.mElevation); + view.setTranslationZ(state.mTranslationZ); + int widthSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredWidth, + View.MeasureSpec.EXACTLY); + int heightSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredHeight, + View.MeasureSpec.EXACTLY); + view.measure(widthSpec, heightSpec); + view.layout(state.mLeft, state.mTop, state.mRight, state.mBottom); + } + } + + protected Bundle captureSharedElementState() { + Bundle bundle = new Bundle(); + RectF tempBounds = new RectF(); + Matrix tempMatrix = new Matrix(); + for (int i = 0; i < mSharedElements.size(); i++) { + View sharedElement = mSharedElements.get(i); + String name = mSharedElementNames.get(i); + captureSharedElementState(sharedElement, name, bundle, tempMatrix, tempBounds); + } + return bundle; + } + + protected void clearState() { + // Clear the state so that we can't hold any references accidentally and leak memory. + mWindow = null; + mSharedElements.clear(); + mTransitioningViews = null; + mOriginalAlphas.clear(); + mResultReceiver = null; + mPendingTransition = null; + mListener = null; + } + + protected long getFadeDuration() { + return getWindow().getTransitionBackgroundFadeDuration(); + } + + protected void hideViews(ArrayList<View> views) { + int count = views.size(); + for (int i = 0; i < count; i++) { + View view = views.get(i); + if (!mOriginalAlphas.containsKey(view)) { + mOriginalAlphas.put(view, view.getAlpha()); + } + view.setAlpha(0f); + } + } + + protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) { + int count = views.size(); + for (int i = 0; i < count; i++) { + showView(views.get(i), setTransitionAlpha); + } + } + + private void showView(View view, boolean setTransitionAlpha) { + Float alpha = mOriginalAlphas.remove(view); + if (alpha != null) { + view.setAlpha(alpha); + } + if (setTransitionAlpha) { + view.setTransitionAlpha(1f); + } + } + + /** + * Captures placement information for Views with a shared element name for + * Activity Transitions. + * + * @param view The View to capture the placement information for. + * @param name The shared element name in the target Activity to apply the placement + * information for. + * @param transitionArgs Bundle to store shared element placement information. + * @param tempBounds A temporary Rect for capturing the current location of views. + */ + protected void captureSharedElementState(View view, String name, Bundle transitionArgs, + Matrix tempMatrix, RectF tempBounds) { + Bundle sharedElementBundle = new Bundle(); + tempMatrix.reset(); + view.transformMatrixToGlobal(tempMatrix); + tempBounds.set(0, 0, view.getWidth(), view.getHeight()); + tempMatrix.mapRect(tempBounds); + + sharedElementBundle.putFloat(KEY_SCREEN_LEFT, tempBounds.left); + sharedElementBundle.putFloat(KEY_SCREEN_RIGHT, tempBounds.right); + sharedElementBundle.putFloat(KEY_SCREEN_TOP, tempBounds.top); + sharedElementBundle.putFloat(KEY_SCREEN_BOTTOM, tempBounds.bottom); + sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ()); + sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation()); + + Parcelable bitmap = null; + if (mListener != null) { + bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds); + } + + if (bitmap != null) { + sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap); + } + + if (view instanceof ImageView) { + ImageView imageView = (ImageView) view; + int scaleTypeInt = scaleTypeToInt(imageView.getScaleType()); + sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt); + if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) { + float[] matrix = new float[9]; + imageView.getImageMatrix().getValues(matrix); + sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix); + } + } + + transitionArgs.putBundle(name, sharedElementBundle); + } + + + protected void startTransition(Runnable runnable) { + if (mIsStartingTransition) { + mPendingTransition = runnable; + } else { + mIsStartingTransition = true; + runnable.run(); + } + } + + protected void transitionStarted() { + mIsStartingTransition = false; + } + + protected void moveSharedElementsToOverlay() { + if (!mWindow.getSharedElementsUseOverlay()) { + return; + } + int numSharedElements = mSharedElements.size(); + ViewGroup decor = getDecor(); + if (decor != null) { + boolean moveWithParent = moveSharedElementWithParent(); + for (int i = 0; i < numSharedElements; i++) { + View view = mSharedElements.get(i); + GhostView.addGhost(view, decor); + ViewGroup parent = (ViewGroup) view.getParent(); + if (moveWithParent && !isInTransitionGroup(parent, decor)) { + GhostViewListeners listener = new GhostViewListeners(view, parent, decor); + parent.getViewTreeObserver().addOnPreDrawListener(listener); + mGhostViewListeners.add(listener); + } + } + } + } + + protected boolean moveSharedElementWithParent() { + return true; + } + + public static boolean isInTransitionGroup(ViewParent viewParent, ViewGroup decor) { + if (viewParent == decor || !(viewParent instanceof ViewGroup)) { + return false; + } + ViewGroup parent = (ViewGroup) viewParent; + if (parent.isTransitionGroup()) { + return true; + } else { + return isInTransitionGroup(parent.getParent(), decor); + } + } + + protected void moveSharedElementsFromOverlay() { + int numListeners = mGhostViewListeners.size(); + for (int i = 0; i < numListeners; i++) { + GhostViewListeners listener = mGhostViewListeners.get(i); + ViewGroup parent = (ViewGroup) listener.getView().getParent(); + parent.getViewTreeObserver().removeOnPreDrawListener(listener); + } + mGhostViewListeners.clear(); + + if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) { + return; + } + ViewGroup decor = getDecor(); + if (decor != null) { + ViewGroupOverlay overlay = decor.getOverlay(); + int count = mSharedElements.size(); + for (int i = 0; i < count; i++) { + View sharedElement = mSharedElements.get(i); + GhostView.removeGhost(sharedElement); + } + } + } + + protected void setGhostVisibility(int visibility) { + int numSharedElements = mSharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + GhostView ghostView = GhostView.getGhost(mSharedElements.get(i)); + if (ghostView != null) { + ghostView.setVisibility(visibility); + } + } + } + + protected void scheduleGhostVisibilityChange(final int visibility) { + final View decorView = getDecor(); + if (decorView != null) { + decorView.getViewTreeObserver() + .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + decorView.getViewTreeObserver().removeOnPreDrawListener(this); + setGhostVisibility(visibility); + return true; + } + }); + } + } + + protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter { + @Override + public void onTransitionStart(Transition transition) { + mIsStartingTransition = false; + Runnable pending = mPendingTransition; + mPendingTransition = null; + if (pending != null) { + startTransition(pending); + } + } + } + + private static int scaleTypeToInt(ImageView.ScaleType scaleType) { + for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) { + if (scaleType == SCALE_TYPE_VALUES[i]) { + return i; + } + } + return -1; + } + + private static class FixedEpicenterCallback extends Transition.EpicenterCallback { + private Rect mEpicenter; + + public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; } + + @Override + public Rect onGetEpicenter(Transition transition) { + return mEpicenter; + } + } + + private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener { + private View mView; + private ViewGroup mDecor; + private View mParent; + private Matrix mMatrix = new Matrix(); + + public GhostViewListeners(View view, View parent, ViewGroup decor) { + mView = view; + mParent = parent; + mDecor = decor; + } + + public View getView() { + return mView; + } + + @Override + public boolean onPreDraw() { + GhostView ghostView = GhostView.getGhost(mView); + if (ghostView == null) { + mParent.getViewTreeObserver().removeOnPreDrawListener(this); + } else { + GhostView.calculateMatrix(mView, mDecor, mMatrix); + ghostView.setMatrix(mMatrix); + } + return true; + } + } + + static class SharedElementOriginalState { + int mLeft; + int mTop; + int mRight; + int mBottom; + int mMeasuredWidth; + int mMeasuredHeight; + ImageView.ScaleType mScaleType; + Matrix mMatrix; + float mTranslationZ; + float mElevation; + } +}
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java new file mode 100644 index 0000000..555d20b --- /dev/null +++ b/core/java/android/app/ActivityTransitionState.java
@@ -0,0 +1,305 @@ +/* + * Copyright (C) 2014 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; + +import android.os.Bundle; +import android.os.ResultReceiver; +import android.transition.Transition; +import android.util.ArrayMap; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +/** + * This class contains all persistence-related functionality for Activity Transitions. + * Activities start exit and enter Activity Transitions through this class. + */ +class ActivityTransitionState { + + private static final String ENTERING_SHARED_ELEMENTS = "android:enteringSharedElements"; + + private static final String EXITING_MAPPED_FROM = "android:exitingMappedFrom"; + + private static final String EXITING_MAPPED_TO = "android:exitingMappedTo"; + + /** + * The shared elements that the calling Activity has said that they transferred to this + * Activity. + */ + private ArrayList<String> mEnteringNames; + + /** + * The names of shared elements that were shared to the called Activity. + */ + private ArrayList<String> mExitingFrom; + + /** + * The names of local Views that were shared out, mapped to those elements in mExitingFrom. + */ + private ArrayList<String> mExitingTo; + + /** + * The local Views that were shared out, mapped to those elements in mExitingFrom. + */ + private ArrayList<View> mExitingToView; + + /** + * The ExitTransitionCoordinator used to start an Activity. Used to make the elements restore + * Visibility of exited Views. + */ + private ExitTransitionCoordinator mCalledExitCoordinator; + + /** + * The ExitTransitionCoordinator used to return to a previous Activity when called with + * {@link android.app.Activity#finishAfterTransition()}. + */ + private ExitTransitionCoordinator mReturnExitCoordinator; + + /** + * We must be able to cancel entering transitions to stop changing the Window to + * opaque when we exit before making the Window opaque. + */ + private EnterTransitionCoordinator mEnterTransitionCoordinator; + + /** + * ActivityOptions used on entering this Activity. + */ + private ActivityOptions mEnterActivityOptions; + + /** + * Has an exit transition been started? If so, we don't want to double-exit. + */ + private boolean mHasExited; + + /** + * Postpone painting and starting the enter transition until this is false. + */ + private boolean mIsEnterPostponed; + + /** + * Potential exit transition coordinators. + */ + private SparseArray<WeakReference<ExitTransitionCoordinator>> mExitTransitionCoordinators; + + /** + * Next key for mExitTransitionCoordinator. + */ + private int mExitTransitionCoordinatorsKey = 1; + + private boolean mIsEnterTriggered; + + public ActivityTransitionState() { + } + + public int addExitTransitionCoordinator(ExitTransitionCoordinator exitTransitionCoordinator) { + if (mExitTransitionCoordinators == null) { + mExitTransitionCoordinators = + new SparseArray<WeakReference<ExitTransitionCoordinator>>(); + } + WeakReference<ExitTransitionCoordinator> ref = new WeakReference(exitTransitionCoordinator); + // clean up old references: + for (int i = mExitTransitionCoordinators.size() - 1; i >= 0; i--) { + WeakReference<ExitTransitionCoordinator> oldRef + = mExitTransitionCoordinators.valueAt(i); + if (oldRef.get() == null) { + mExitTransitionCoordinators.removeAt(i); + } + } + int newKey = mExitTransitionCoordinatorsKey++; + mExitTransitionCoordinators.append(newKey, ref); + return newKey; + } + + public void readState(Bundle bundle) { + if (bundle != null) { + if (mEnterTransitionCoordinator == null || mEnterTransitionCoordinator.isReturning()) { + mEnteringNames = bundle.getStringArrayList(ENTERING_SHARED_ELEMENTS); + } + if (mEnterTransitionCoordinator == null) { + mExitingFrom = bundle.getStringArrayList(EXITING_MAPPED_FROM); + mExitingTo = bundle.getStringArrayList(EXITING_MAPPED_TO); + } + } + } + + public void saveState(Bundle bundle) { + if (mEnteringNames != null) { + bundle.putStringArrayList(ENTERING_SHARED_ELEMENTS, mEnteringNames); + } + if (mExitingFrom != null) { + bundle.putStringArrayList(EXITING_MAPPED_FROM, mExitingFrom); + bundle.putStringArrayList(EXITING_MAPPED_TO, mExitingTo); + } + } + + public void setEnterActivityOptions(Activity activity, ActivityOptions options) { + if (activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) + && options != null && mEnterActivityOptions == null + && mEnterTransitionCoordinator == null + && options.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { + mEnterActivityOptions = options; + mIsEnterTriggered = false; + if (mEnterActivityOptions.isReturning()) { + restoreExitedViews(); + int result = mEnterActivityOptions.getResultCode(); + if (result != 0) { + activity.onActivityReenter(result, mEnterActivityOptions.getResultData()); + } + } + } + } + + public void enterReady(Activity activity) { + if (mEnterActivityOptions == null || mIsEnterTriggered) { + return; + } + mIsEnterTriggered = true; + mHasExited = false; + ArrayList<String> sharedElementNames = mEnterActivityOptions.getSharedElementNames(); + ResultReceiver resultReceiver = mEnterActivityOptions.getResultReceiver(); + if (mEnterActivityOptions.isReturning()) { + restoreExitedViews(); + activity.getWindow().getDecorView().setVisibility(View.VISIBLE); + } + mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity, + resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning()); + + if (!mIsEnterPostponed) { + startEnter(); + } + } + + public void postponeEnterTransition() { + mIsEnterPostponed = true; + } + + public void startPostponedEnterTransition() { + if (mIsEnterPostponed) { + mIsEnterPostponed = false; + if (mEnterTransitionCoordinator != null) { + startEnter(); + } + } + } + + private void startEnter() { + if (mEnterActivityOptions.isReturning()) { + if (mExitingToView != null) { + mEnterTransitionCoordinator.viewInstancesReady(mExitingFrom, mExitingTo, + mExitingToView); + } else { + mEnterTransitionCoordinator.namedViewsReady(mExitingFrom, mExitingTo); + } + } else { + mEnterTransitionCoordinator.namedViewsReady(null, null); + mEnteringNames = mEnterTransitionCoordinator.getAllSharedElementNames(); + } + + mExitingFrom = null; + mExitingTo = null; + mExitingToView = null; + mEnterActivityOptions = null; + } + + public void onStop() { + restoreExitedViews(); + if (mEnterTransitionCoordinator != null) { + mEnterTransitionCoordinator.stop(); + mEnterTransitionCoordinator = null; + } + if (mReturnExitCoordinator != null) { + mReturnExitCoordinator.stop(); + mReturnExitCoordinator = null; + } + } + + public void onResume() { + restoreExitedViews(); + } + + public void clear() { + mEnteringNames = null; + mExitingFrom = null; + mExitingTo = null; + mExitingToView = null; + mCalledExitCoordinator = null; + mEnterTransitionCoordinator = null; + mEnterActivityOptions = null; + mExitTransitionCoordinators = null; + } + + private void restoreExitedViews() { + if (mCalledExitCoordinator != null) { + mCalledExitCoordinator.resetViews(); + mCalledExitCoordinator = null; + } + } + + public boolean startExitBackTransition(Activity activity) { + if (mEnteringNames == null) { + return false; + } else { + if (!mHasExited) { + mHasExited = true; + Transition enterViewsTransition = null; + ViewGroup decor = null; + if (mEnterTransitionCoordinator != null) { + enterViewsTransition = mEnterTransitionCoordinator.getEnterViewsTransition(); + decor = mEnterTransitionCoordinator.getDecor(); + mEnterTransitionCoordinator.cancelEnter(); + mEnterTransitionCoordinator = null; + if (enterViewsTransition != null && decor != null) { + enterViewsTransition.pause(decor); + } + } + + mReturnExitCoordinator = + new ExitTransitionCoordinator(activity, mEnteringNames, null, null, true); + if (enterViewsTransition != null && decor != null) { + enterViewsTransition.resume(decor); + } + mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData); + } + return true; + } + } + + public void startExitOutTransition(Activity activity, Bundle options) { + if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { + return; + } + ActivityOptions activityOptions = new ActivityOptions(options); + mEnterTransitionCoordinator = null; + if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { + int key = activityOptions.getExitCoordinatorKey(); + int index = mExitTransitionCoordinators.indexOfKey(key); + if (index >= 0) { + mCalledExitCoordinator = mExitTransitionCoordinators.valueAt(index).get(); + mExitTransitionCoordinators.removeAt(index); + if (mCalledExitCoordinator != null) { + mExitingFrom = mCalledExitCoordinator.getAcceptedNames(); + mExitingTo = mCalledExitCoordinator.getMappedNames(); + mExitingToView = mCalledExitCoordinator.copyMappedViews(); + mCalledExitCoordinator.startExit(); + } + } + } + } +}
diff --git a/core/java/android/app/AlarmManager.aidl b/core/java/android/app/AlarmManager.aidl new file mode 100644 index 0000000..c9547b2 --- /dev/null +++ b/core/java/android/app/AlarmManager.aidl
@@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014, 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; + +parcelable AlarmManager.AlarmClockInfo;
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index 0cf7ad0..2c596e5 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java
@@ -16,11 +16,17 @@ package android.app; +import android.annotation.SdkConstant; +import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; +import android.os.UserHandle; import android.os.WorkSource; +import android.os.Parcelable.Creator; /** * This class provides access to the system alarm services. These allow you @@ -94,6 +100,17 @@ */ public static final int ELAPSED_REALTIME = 3; + /** + * Broadcast Action: Sent after the value returned by + * {@link #getNextAlarmClock()} has changed. + * + * <p class="note">This is a protected intent that can only be sent by the system. + * It is only sent to registered receivers.</p> + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NEXT_ALARM_CLOCK_CHANGED = + "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; + /** @hide */ public static final long WINDOW_EXACT = 0; /** @hide */ @@ -188,7 +205,7 @@ * @see #RTC_WAKEUP */ public void set(int type, long triggerAtMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation, null); + setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation, null, null); } /** @@ -249,7 +266,7 @@ */ public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, operation, null); + setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, operation, null, null); } /** @@ -299,7 +316,7 @@ */ public void setWindow(int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) { - setImpl(type, windowStartMillis, windowLengthMillis, 0, operation, null); + setImpl(type, windowStartMillis, windowLengthMillis, 0, operation, null, null); } /** @@ -337,17 +354,46 @@ * @see #RTC_WAKEUP */ public void setExact(int type, long triggerAtMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation, null); + setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation, null, null); + } + + /** + * Schedule an alarm that represents an alarm clock. + * + * The system may choose to display information about this alarm to the user. + * + * <p> + * This method is like {@link #setExact(int, long, PendingIntent)}, but implies + * {@link #RTC_WAKEUP}. + * + * @param info + * @param operation Action to perform when the alarm goes off; + * typically comes from {@link PendingIntent#getBroadcast + * IntentSender.getBroadcast()}. + * + * @see #set + * @see #setRepeating + * @see #setWindow + * @see #setExact + * @see #cancel + * @see #getNextAlarmClock() + * @see android.content.Context#sendBroadcast + * @see android.content.Context#registerReceiver + * @see android.content.Intent#filterEquals + */ + public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) { + setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, operation, null, info); } /** @hide */ + @SystemApi public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, PendingIntent operation, WorkSource workSource) { - setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource); + setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource, null); } private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis, - PendingIntent operation, WorkSource workSource) { + PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) { if (triggerAtMillis < 0) { /* NOTYET if (mAlwaysExact) { @@ -361,7 +407,7 @@ try { mService.set(type, triggerAtMillis, windowMillis, intervalMillis, operation, - workSource); + workSource, alarmClock); } catch (RemoteException ex) { } } @@ -461,7 +507,7 @@ */ public void setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { - setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, operation, null); + setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, operation, null, null); } /** @@ -506,4 +552,117 @@ } catch (RemoteException ex) { } } + + /** + * Gets information about the next alarm clock currently scheduled. + * + * The alarm clocks considered are those scheduled by {@link #setAlarmClock} + * from any package of the calling user. + * + * @see #setAlarmClock + * @see AlarmClockInfo + */ + public AlarmClockInfo getNextAlarmClock() { + return getNextAlarmClock(UserHandle.myUserId()); + } + + /** + * Gets information about the next alarm clock currently scheduled. + * + * The alarm clocks considered are those scheduled by {@link #setAlarmClock} + * from any package of the given {@parm userId}. + * + * @see #setAlarmClock + * @see AlarmClockInfo + * + * @hide + */ + public AlarmClockInfo getNextAlarmClock(int userId) { + try { + return mService.getNextAlarmClock(userId); + } catch (RemoteException ex) { + return null; + } + } + + /** + * An immutable description of an alarm clock. + * + * @see AlarmManager#setAlarmClock + * @see AlarmManager#getNextAlarmClock + */ + public static final class AlarmClockInfo implements Parcelable { + + private final long mTriggerTime; + private final PendingIntent mShowIntent; + + /** + * Creates a new alarm clock description. + * + * @param triggerTime time at which the underlying alarm is triggered in wall time + * milliseconds since the epoch + * @param showIntent an intent that can be used to show or edit details of + * the alarm clock. + */ + public AlarmClockInfo(long triggerTime, PendingIntent showIntent) { + mTriggerTime = triggerTime; + mShowIntent = showIntent; + } + + /** + * Use the {@link #CREATOR} + * @hide + */ + AlarmClockInfo(Parcel in) { + mTriggerTime = in.readLong(); + mShowIntent = in.readParcelable(PendingIntent.class.getClassLoader()); + } + + /** + * Returns the time at which the alarm is going to trigger. + * + * This value is UTC wall clock time in milliseconds, as returned by + * {@link System#currentTimeMillis()} for example. + */ + public long getTriggerTime() { + return mTriggerTime; + } + + /** + * Returns an intent intent that can be used to show or edit details of the alarm clock in + * the application that scheduled it. + * + * <p class="note">Beware that any application can retrieve and send this intent, + * potentially with additional fields filled in. See + * {@link PendingIntent#send(android.content.Context, int, android.content.Intent) + * PendingIntent.send()} and {@link android.content.Intent#fillIn Intent.fillIn()} + * for details. + */ + public PendingIntent getShowIntent() { + return mShowIntent; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mTriggerTime); + dest.writeParcelable(mShowIntent, flags); + } + + public static final Creator<AlarmClockInfo> CREATOR = new Creator<AlarmClockInfo>() { + @Override + public AlarmClockInfo createFromParcel(Parcel in) { + return new AlarmClockInfo(in); + } + + @Override + public AlarmClockInfo[] newArray(int size) { + return new AlarmClockInfo[size]; + } + }; + } }
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index 10d5e25..4ce7835 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java
@@ -27,7 +27,6 @@ import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.KeyEvent; -import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.AdapterView; @@ -93,6 +92,18 @@ * the device's default alert theme with a light background. */ public static final int THEME_DEVICE_DEFAULT_LIGHT = 5; + + /** + * No layout hint. + * @hide + */ + public static final int LAYOUT_HINT_NONE = 0; + + /** + * Hint layout to the side. + * @hide + */ + public static final int LAYOUT_HINT_SIDE = 1; protected AlertDialog(Context context) { this(context, resolveDialogTheme(context, 0), true); @@ -147,10 +158,10 @@ } /** - * Gets one of the buttons used in the dialog. - * <p> - * If a button does not exist in the dialog, null will be returned. - * + * Gets one of the buttons used in the dialog. Returns null if the specified + * button does not exist or the dialog has not yet been fully created (for + * example, via {@link #show()} or {@link #create()}). + * * @param whichButton The identifier of the button that should be returned. * For example, this can be * {@link DialogInterface#BUTTON_POSITIVE}. @@ -159,7 +170,7 @@ public Button getButton(int whichButton) { return mAlert.getButton(whichButton); } - + /** * Gets the list view used in the dialog. * @@ -209,6 +220,14 @@ } /** + * Internal api to allow hinting for the best button panel layout. + * @hide + */ + void setButtonPanelLayoutHint(int layoutHint) { + mAlert.setButtonPanelLayoutHint(layoutHint); + } + + /** * Set a message to be sent when a button is pressed. * * @param whichButton Which button to set the message for, can be one of @@ -853,6 +872,21 @@ } /** + * Set a custom view resource to be the contents of the Dialog. The + * resource will be inflated, adding all top-level views to the screen. + * + * @param layoutResId Resource ID to be inflated. + * @return This Builder object to allow for chaining of calls to set + * methods + */ + public Builder setView(int layoutResId) { + P.mView = null; + P.mViewLayoutResId = layoutResId; + P.mViewSpacingSpecified = false; + return this; + } + + /** * Set a custom view to be the contents of the Dialog. If the supplied view is an instance * of a {@link ListView} the light background will be used. * @@ -862,6 +896,7 @@ */ public Builder setView(View view) { P.mView = view; + P.mViewLayoutResId = 0; P.mViewSpacingSpecified = false; return this; } @@ -891,6 +926,7 @@ public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) { P.mView = view; + P.mViewLayoutResId = 0; P.mViewSpacingSpecified = true; P.mViewSpacingLeft = viewSpacingLeft; P.mViewSpacingTop = viewSpacingTop;
diff --git a/core/java/android/app/AppImportanceMonitor.java b/core/java/android/app/AppImportanceMonitor.java new file mode 100644 index 0000000..c760e1e --- /dev/null +++ b/core/java/android/app/AppImportanceMonitor.java
@@ -0,0 +1,150 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.SparseArray; +import android.util.SparseIntArray; + +import java.util.List; + +/** + * Helper for monitoring the current importance of applications. + * @hide + */ +public class AppImportanceMonitor { + final Context mContext; + + final SparseArray<AppEntry> mApps = new SparseArray<>(); + + static class AppEntry { + final int uid; + final SparseArray<Integer> procs = new SparseArray<>(1); + int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; + + AppEntry(int _uid) { + uid = _uid; + } + } + + final IProcessObserver mProcessObserver = new IProcessObserver.Stub() { + @Override + public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { + } + + @Override + public void onProcessStateChanged(int pid, int uid, int procState) { + synchronized (mApps) { + updateImportanceLocked(pid, uid, + ActivityManager.RunningAppProcessInfo.procStateToImportance(procState), + true); + } + } + + @Override + public void onProcessDied(int pid, int uid) { + synchronized (mApps) { + updateImportanceLocked(pid, uid, + ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, true); + } + } + }; + + static final int MSG_UPDATE = 1; + + final Handler mHandler; + + public AppImportanceMonitor(Context context, Looper looper) { + mContext = context; + mHandler = new Handler(looper) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_UPDATE: + onImportanceChanged(msg.arg1, msg.arg2&0xffff, msg.arg2>>16); + break; + default: + super.handleMessage(msg); + } + } + }; + ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); + try { + ActivityManagerNative.getDefault().registerProcessObserver(mProcessObserver); + } catch (RemoteException e) { + } + List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses(); + if (apps != null) { + for (int i=0; i<apps.size(); i++) { + ActivityManager.RunningAppProcessInfo app = apps.get(i); + updateImportanceLocked(app.uid, app.pid, app.importance, false); + } + } + } + + public int getImportance(int uid) { + AppEntry ent = mApps.get(uid); + if (ent == null) { + return ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; + } + return ent.importance; + } + + /** + * Report when an app's importance changed. Called on looper given to constructor. + */ + public void onImportanceChanged(int uid, int importance, int oldImportance) { + } + + void updateImportanceLocked(int uid, int pid, int importance, boolean repChange) { + AppEntry ent = mApps.get(uid); + if (ent == null) { + ent = new AppEntry(uid); + mApps.put(uid, ent); + } + if (importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) { + ent.procs.remove(pid); + } else { + ent.procs.put(pid, importance); + } + updateImportanceLocked(ent, repChange); + } + + void updateImportanceLocked(AppEntry ent, boolean repChange) { + int appImp = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; + for (int i=0; i<ent.procs.size(); i++) { + int procImp = ent.procs.valueAt(i); + if (procImp < appImp) { + appImp = procImp; + } + } + if (appImp != ent.importance) { + int impCode = appImp | (ent.importance<<16); + ent.importance = appImp; + if (appImp >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) { + mApps.remove(ent.uid); + } + if (repChange) { + mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget(); + } + } + } +}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 079cf7a..ba9c9d6 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java
@@ -16,21 +16,25 @@ package android.app; +import android.annotation.SystemApi; +import android.app.usage.UsageStatsManager; +import android.content.Context; +import android.media.AudioAttributes.AttributeUsage; import android.os.Binder; import android.os.IBinder; -import android.util.ArrayMap; -import com.android.internal.app.IAppOpsService; -import com.android.internal.app.IAppOpsCallback; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; +import android.os.UserManager; +import android.util.ArrayMap; + +import com.android.internal.app.IAppOpsCallback; +import com.android.internal.app.IAppOpsService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; /** * API for interacting with "application operation" tracking. @@ -90,6 +94,13 @@ */ public static final int MODE_ERRORED = 2; + /** + * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should + * use its default security check. This mode is not normally used; it should only be used + * with appop permissions, and callers must explicitly check for it and deal with it. + */ + public static final int MODE_DEFAULT = 3; + // when adding one of these: // - increment _NUM_OP // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode @@ -184,8 +195,18 @@ public static final int OP_MONITOR_LOCATION = 41; /** @hide Continually monitoring location data with a relatively high power request. */ public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; + /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */ + public static final int OP_GET_USAGE_STATS = 43; /** @hide */ - public static final int _NUM_OP = 43; + public static final int OP_MUTE_MICROPHONE = 44; + /** @hide */ + public static final int OP_TOAST_WINDOW = 45; + /** @hide Capture the device's display contents and/or audio */ + public static final int OP_PROJECT_MEDIA = 46; + /** @hide Activate a VPN connection without user intervention. */ + public static final int OP_ACTIVATE_VPN = 47; + /** @hide */ + public static final int _NUM_OP = 48; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = @@ -199,6 +220,12 @@ /** Continually monitoring location data with a relatively high power request. */ public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power"; + /** Access to {@link android.app.usage.UsageStatsManager}. */ + public static final String OPSTR_GET_USAGE_STATS + = "android:get_usage_stats"; + /** Activate a VPN connection without user intervention. @hide */ + @SystemApi + public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn"; /** * This maps each operation to the operation that serves as the @@ -252,6 +279,11 @@ OP_WAKE_LOCK, OP_COARSE_LOCATION, OP_COARSE_LOCATION, + OP_GET_USAGE_STATS, + OP_MUTE_MICROPHONE, + OP_TOAST_WINDOW, + OP_PROJECT_MEDIA, + OP_ACTIVATE_VPN, }; /** @@ -302,6 +334,11 @@ null, OPSTR_MONITOR_LOCATION, OPSTR_MONITOR_HIGH_POWER_LOCATION, + OPSTR_GET_USAGE_STATS, + null, + null, + null, + OPSTR_ACTIVATE_VPN, }; /** @@ -352,6 +389,11 @@ "WAKE_LOCK", "MONITOR_LOCATION", "MONITOR_HIGH_POWER_LOCATION", + "GET_USAGE_STATS", + "MUTE_MICROPHONE", + "TOAST_WINDOW", + "PROJECT_MEDIA", + "ACTIVATE_VPN", }; /** @@ -402,6 +444,122 @@ android.Manifest.permission.WAKE_LOCK, null, // no permission for generic location monitoring null, // no permission for high power location monitoring + android.Manifest.permission.PACKAGE_USAGE_STATS, + null, // no permission for muting/unmuting microphone + null, // no permission for displaying toasts + null, // no permission for projecting media + null, // no permission for activating vpn + }; + + /** + * Specifies whether an Op should be restricted by a user restriction. + * Each Op should be filled with a restriction string from UserManager or + * null to specify it is not affected by any user restriction. + */ + private static String[] sOpRestrictions = new String[] { + UserManager.DISALLOW_SHARE_LOCATION, //COARSE_LOCATION + UserManager.DISALLOW_SHARE_LOCATION, //FINE_LOCATION + UserManager.DISALLOW_SHARE_LOCATION, //GPS + null, //VIBRATE + null, //READ_CONTACTS + null, //WRITE_CONTACTS + UserManager.DISALLOW_OUTGOING_CALLS, //READ_CALL_LOG + UserManager.DISALLOW_OUTGOING_CALLS, //WRITE_CALL_LOG + null, //READ_CALENDAR + null, //WRITE_CALENDAR + UserManager.DISALLOW_SHARE_LOCATION, //WIFI_SCAN + null, //POST_NOTIFICATION + null, //NEIGHBORING_CELLS + null, //CALL_PHONE + UserManager.DISALLOW_SMS, //READ_SMS + UserManager.DISALLOW_SMS, //WRITE_SMS + UserManager.DISALLOW_SMS, //RECEIVE_SMS + null, //RECEIVE_EMERGENCY_SMS + UserManager.DISALLOW_SMS, //RECEIVE_MMS + null, //RECEIVE_WAP_PUSH + UserManager.DISALLOW_SMS, //SEND_SMS + UserManager.DISALLOW_SMS, //READ_ICC_SMS + UserManager.DISALLOW_SMS, //WRITE_ICC_SMS + null, //WRITE_SETTINGS + UserManager.DISALLOW_CREATE_WINDOWS, //SYSTEM_ALERT_WINDOW + null, //ACCESS_NOTIFICATIONS + null, //CAMERA + null, //RECORD_AUDIO + null, //PLAY_AUDIO + null, //READ_CLIPBOARD + null, //WRITE_CLIPBOARD + null, //TAKE_MEDIA_BUTTONS + null, //TAKE_AUDIO_FOCUS + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_MASTER_VOLUME + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_VOICE_VOLUME + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_RING_VOLUME + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_MEDIA_VOLUME + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ALARM_VOLUME + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_NOTIFICATION_VOLUME + UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_BLUETOOTH_VOLUME + null, //WAKE_LOCK + UserManager.DISALLOW_SHARE_LOCATION, //MONITOR_LOCATION + UserManager.DISALLOW_SHARE_LOCATION, //MONITOR_HIGH_POWER_LOCATION + null, //GET_USAGE_STATS + UserManager.DISALLOW_UNMUTE_MICROPHONE, // MUTE_MICROPHONE + UserManager.DISALLOW_CREATE_WINDOWS, // TOAST_WINDOW + null, //PROJECT_MEDIA + UserManager.DISALLOW_CONFIG_VPN, // ACTIVATE_VPN + }; + + /** + * This specifies whether each option should allow the system + * (and system ui) to bypass the user restriction when active. + */ + private static boolean[] sOpAllowSystemRestrictionBypass = new boolean[] { + false, //COARSE_LOCATION + false, //FINE_LOCATION + false, //GPS + false, //VIBRATE + false, //READ_CONTACTS + false, //WRITE_CONTACTS + false, //READ_CALL_LOG + false, //WRITE_CALL_LOG + false, //READ_CALENDAR + false, //WRITE_CALENDAR + true, //WIFI_SCAN + false, //POST_NOTIFICATION + false, //NEIGHBORING_CELLS + false, //CALL_PHONE + false, //READ_SMS + false, //WRITE_SMS + false, //RECEIVE_SMS + false, //RECEIVE_EMERGECY_SMS + false, //RECEIVE_MMS + false, //RECEIVE_WAP_PUSH + false, //SEND_SMS + false, //READ_ICC_SMS + false, //WRITE_ICC_SMS + false, //WRITE_SETTINGS + true, //SYSTEM_ALERT_WINDOW + false, //ACCESS_NOTIFICATIONS + false, //CAMERA + false, //RECORD_AUDIO + false, //PLAY_AUDIO + false, //READ_CLIPBOARD + false, //WRITE_CLIPBOARD + false, //TAKE_MEDIA_BUTTONS + false, //TAKE_AUDIO_FOCUS + false, //AUDIO_MASTER_VOLUME + false, //AUDIO_VOICE_VOLUME + false, //AUDIO_RING_VOLUME + false, //AUDIO_MEDIA_VOLUME + false, //AUDIO_ALARM_VOLUME + false, //AUDIO_NOTIFICATION_VOLUME + false, //AUDIO_BLUETOOTH_VOLUME + false, //WAKE_LOCK + false, //MONITOR_LOCATION + false, //MONITOR_HIGH_POWER_LOCATION + false, //GET_USAGE_STATS + false, //MUTE_MICROPHONE + true, //TOAST_WINDOW + false, //PROJECT_MEDIA + false, //ACTIVATE_VPN }; /** @@ -451,6 +609,11 @@ AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA + AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN }; /** @@ -504,6 +667,11 @@ false, false, false, + false, + false, + false, + false, + false, }; private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>(); @@ -533,6 +701,14 @@ throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length + " should be " + _NUM_OP); } + if (sOpRestrictions.length != _NUM_OP) { + throw new IllegalStateException("sOpRestrictions length " + sOpRestrictions.length + + " should be " + _NUM_OP); + } + if (sOpAllowSystemRestrictionBypass.length != _NUM_OP) { + throw new IllegalStateException("sOpAllowSYstemRestrictionsBypass length " + + sOpRestrictions.length + " should be " + _NUM_OP); + } for (int i=0; i<_NUM_OP; i++) { if (sOpToString[i] != null) { sOpStrToOp.put(sOpToString[i], i); @@ -566,6 +742,23 @@ } /** + * Retrieve the user restriction associated with an operation, or null if there is not one. + * @hide + */ + public static String opToRestriction(int op) { + return sOpRestrictions[op]; + } + + /** + * Retrieve whether the op allows the system (and system ui) to + * bypass the user restriction. + * @hide + */ + public static boolean opAllowSystemBypassRestriction(int op) { + return sOpAllowSystemRestrictionBypass[op]; + } + + /** * Retrieve the default mode for the operation. * @hide */ @@ -780,6 +973,26 @@ } } + /** + * Set a non-persisted restriction on an audio operation at a stream-level. + * Restrictions are temporary additional constraints imposed on top of the persisted rules + * defined by {@link #setMode}. + * + * @param code The operation to restrict. + * @param usage The {@link android.media.AudioAttributes} usage value. + * @param mode The restriction mode (MODE_IGNORED,MODE_ERRORED) or MODE_ALLOWED to unrestrict. + * @param exceptionPackages Optional list of packages to exclude from the restriction. + * @hide + */ + public void setRestriction(int code, @AttributeUsage int usage, int mode, + String[] exceptionPackages) { + try { + final int uid = Binder.getCallingUid(); + mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages); + } catch (RemoteException e) { + } + } + /** @hide */ public void resetAllModes() { try { @@ -849,7 +1062,10 @@ return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op]; } - private int strOpToOp(String op) { + /** + * {@hide} + */ + public static int strOpToOp(String op) { Integer val = sOpStrToOp.get(op); if (val == null) { throw new IllegalArgumentException("Unknown operation string: " + op); @@ -1009,6 +1225,35 @@ } /** + * Like {@link #checkOp} but at a stream-level for audio operations. + * @hide + */ + public int checkAudioOp(int op, int stream, int uid, String packageName) { + try { + final int mode = mService.checkAudioOperation(op, stream, uid, packageName); + if (mode == MODE_ERRORED) { + throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); + } + return mode; + } catch (RemoteException e) { + } + return MODE_IGNORED; + } + + /** + * Like {@link #checkAudioOp} but instead of throwing a {@link SecurityException} it + * returns {@link #MODE_ERRORED}. + * @hide + */ + public int checkAudioOpNoThrow(int op, int stream, int uid, String packageName) { + try { + return mService.checkAudioOperation(op, stream, uid, packageName); + } catch (RemoteException e) { + } + return MODE_IGNORED; + } + + /** * Make note of an application performing an operation. Note that you must pass * in both the uid and name of the application to be checked; this function will verify * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java index c117486..841bd16 100644 --- a/core/java/android/app/ApplicationErrorReport.java +++ b/core/java/android/app/ApplicationErrorReport.java
@@ -24,10 +24,10 @@ import android.content.pm.ResolveInfo; import android.os.Parcel; import android.os.Parcelable; -import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; import android.util.Printer; +import android.util.Slog; import com.android.internal.util.FastPrintWriter; import java.io.PrintWriter; @@ -379,6 +379,7 @@ * Save a CrashInfo instance to a parcel. */ public void writeToParcel(Parcel dest, int flags) { + int start = dest.dataPosition(); dest.writeString(exceptionClassName); dest.writeString(exceptionMessage); dest.writeString(throwFileName); @@ -386,6 +387,16 @@ dest.writeString(throwMethodName); dest.writeInt(throwLineNumber); dest.writeString(stackTrace); + int total = dest.dataPosition()-start; + if (total > 10*1024) { + Slog.d("Error", "ERR: exClass=" + exceptionClassName); + Slog.d("Error", "ERR: exMsg=" + exceptionMessage); + Slog.d("Error", "ERR: file=" + throwFileName); + Slog.d("Error", "ERR: class=" + throwClassName); + Slog.d("Error", "ERR: method=" + throwMethodName + " line=" + throwLineNumber); + Slog.d("Error", "ERR: stack=" + stackTrace); + Slog.d("Error", "ERR: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start)); + } } /**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 02192eb..68606836 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java
@@ -33,7 +33,11 @@ import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; import android.content.pm.InstrumentationInfo; +import android.content.pm.KeySet; +import android.content.pm.ManifestDigest; import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; @@ -41,24 +45,33 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.content.pm.ManifestDigest; +import android.content.pm.UserInfo; import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.res.Resources; import android.content.res.XmlResourceParser; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.util.ArrayMap; import android.util.Log; import android.view.Display; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; +import com.android.internal.util.UserIcons; + +import dalvik.system.VMRuntime; + import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; /*package*/ @@ -67,6 +80,22 @@ private final static boolean DEBUG = false; private final static boolean DEBUG_ICONS = false; + private final Object mLock = new Object(); + + @GuardedBy("mLock") + private UserManager mUserManager; + @GuardedBy("mLock") + private PackageInstaller mInstaller; + + UserManager getUserManager() { + synchronized (mLock) { + if (mUserManager == null) { + mUserManager = UserManager.get(mContext); + } + return mUserManager; + } + } + @Override public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { @@ -128,7 +157,6 @@ return intent; } - /** @hide */ @Override public Intent getLeanbackLaunchIntentForPackage(String packageName) { // Try to find a main leanback_launcher activity. @@ -237,6 +265,10 @@ try { ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, mContext.getUserId()); if (ai != null) { + // This is a temporary hack. Callers must use + // createPackageContext(packageName).getApplicationInfo() to + // get the right paths. + maybeAdjustApplicationInfo(ai); return ai; } } catch (RemoteException e) { @@ -246,6 +278,24 @@ throw new NameNotFoundException(packageName); } + private static void maybeAdjustApplicationInfo(ApplicationInfo info) { + // If we're dealing with a multi-arch application that has both + // 32 and 64 bit shared libraries, we might need to choose the secondary + // depending on what the current runtime's instruction set is. + if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) { + final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet(); + final String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi); + + // If the runtimeIsa is the same as the primary isa, then we do nothing. + // Everything will be set up correctly because info.nativeLibraryDir will + // correspond to the right ISA. + if (runtimeIsa.equals(secondaryIsa)) { + info.nativeLibraryDir = info.secondaryNativeLibraryDir; + } + } + } + + @Override public ActivityInfo getActivityInfo(ComponentName className, int flags) throws NameNotFoundException { @@ -620,10 +670,15 @@ } @Override - public ProviderInfo resolveContentProvider(String name, - int flags) { + public ProviderInfo resolveContentProvider(String name, int flags) { + return resolveContentProviderAsUser(name, flags, mContext.getUserId()); + } + + /** @hide **/ + @Override + public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) { try { - return mPM.resolveContentProvider(name, flags, mContext.getUserId()); + return mPM.resolveContentProvider(name, flags, userId); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } @@ -698,10 +753,10 @@ putCachedIcon(name, dr); return dr; } catch (NameNotFoundException e) { - Log.w("PackageManager", "Failure retrieving resources for" + Log.w("PackageManager", "Failure retrieving resources for " + appInfo.packageName); } catch (Resources.NotFoundException e) { - Log.w("PackageManager", "Failure retrieving resources for" + Log.w("PackageManager", "Failure retrieving resources for " + appInfo.packageName + ": " + e.getMessage()); } catch (RuntimeException e) { // If an exception was thrown, fall through to return @@ -813,6 +868,49 @@ return getApplicationLogo(getApplicationInfo(packageName, 0)); } + @Override + public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) { + final int badgeResId = getBadgeResIdForUser(user.getIdentifier()); + if (badgeResId == 0) { + return icon; + } + Drawable badgeIcon = getDrawable("system", badgeResId, null); + return getBadgedDrawable(icon, badgeIcon, null, true); + } + + @Override + public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user, + Rect badgeLocation, int badgeDensity) { + Drawable badgeDrawable = getUserBadgeForDensity(user, badgeDensity); + if (badgeDrawable == null) { + return drawable; + } + return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true); + } + + @Override + public Drawable getUserBadgeForDensity(UserHandle user, int density) { + UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + if (userInfo != null && userInfo.isManagedProfile()) { + if (density <= 0) { + density = mContext.getResources().getDisplayMetrics().densityDpi; + } + return Resources.getSystem().getDrawableForDensity( + com.android.internal.R.drawable.ic_corp_badge, density); + } + return null; + } + + @Override + public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) { + UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + if (userInfo != null && userInfo.isManagedProfile()) { + return Resources.getSystem().getString( + com.android.internal.R.string.managed_profile_label_badge, label); + } + return label; + } + @Override public Resources getResourcesForActivity( ComponentName activityName) throws NameNotFoundException { return getResourcesForApplication( @@ -824,9 +922,11 @@ if (app.packageName.equals("system")) { return mContext.mMainThread.getSystemContext().getResources(); } + final boolean sameUid = (app.uid == Process.myUid()); Resources r = mContext.mMainThread.getTopLevelResources( - app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir, - app.resourceDirs, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo); + sameUid ? app.sourceDir : app.publicSourceDir, + sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs, + app.resourceDirs, null, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo); if (r != null) { return r; } @@ -1047,7 +1147,7 @@ putCachedString(name, text); return text; } catch (NameNotFoundException e) { - Log.w("PackageManager", "Failure retrieving resources for" + Log.w("PackageManager", "Failure retrieving resources for " + appInfo.packageName); } catch (RuntimeException e) { // If an exception was thrown, fall through to return @@ -1093,34 +1193,72 @@ @Override public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName) { - try { - mPM.installPackage(packageURI, observer, flags, installerPackageName); - } catch (RemoteException e) { - // Should never happen! - } + final VerificationParams verificationParams = new VerificationParams(null, null, + null, VerificationParams.NO_UID, null); + installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags, + installerPackageName, verificationParams, null); } @Override public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) { - try { - mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName, - verificationURI, manifestDigest, encryptionParams); - } catch (RemoteException e) { - // Should never happen! - } + final VerificationParams verificationParams = new VerificationParams(verificationURI, null, + null, VerificationParams.NO_UID, manifestDigest); + installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags, + installerPackageName, verificationParams, encryptionParams); } @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, + public void installPackageWithVerificationAndEncryption(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { + installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags, + installerPackageName, verificationParams, encryptionParams); + } + + @Override + public void installPackage(Uri packageURI, PackageInstallObserver observer, + int flags, String installerPackageName) { + final VerificationParams verificationParams = new VerificationParams(null, null, + null, VerificationParams.NO_UID, null); + installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null); + } + + @Override + public void installPackageWithVerification(Uri packageURI, + PackageInstallObserver observer, int flags, String installerPackageName, + Uri verificationURI, ManifestDigest manifestDigest, + ContainerEncryptionParams encryptionParams) { + final VerificationParams verificationParams = new VerificationParams(verificationURI, null, + null, VerificationParams.NO_UID, manifestDigest); + installCommon(packageURI, observer, flags, installerPackageName, verificationParams, + encryptionParams); + } + + @Override + public void installPackageWithVerificationAndEncryption(Uri packageURI, + PackageInstallObserver observer, int flags, String installerPackageName, + VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { + installCommon(packageURI, observer, flags, installerPackageName, verificationParams, + encryptionParams); + } + + private void installCommon(Uri packageURI, + PackageInstallObserver observer, int flags, String installerPackageName, + VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { + if (!"file".equals(packageURI.getScheme())) { + throw new UnsupportedOperationException("Only file:// URIs are supported"); + } + if (encryptionParams != null) { + throw new UnsupportedOperationException("ContainerEncryptionParams not supported"); + } + + final String originPath = packageURI.getPath(); try { - mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags, - installerPackageName, verificationParams, encryptionParams); - } catch (RemoteException e) { - // Should never happen! + mPM.installPackage(originPath, observer.getBinder(), flags, installerPackageName, + verificationParams, null); + } catch (RemoteException ignored) { } } @@ -1195,6 +1333,7 @@ // Should never happen! } } + @Override public void clearApplicationUserData(String packageName, IPackageDataObserver observer) { @@ -1292,7 +1431,18 @@ public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { try { - mPM.replacePreferredActivity(filter, match, set, activity); + mPM.replacePreferredActivity(filter, match, set, activity, UserHandle.myUserId()); + } catch (RemoteException e) { + // Should never happen! + } + } + + @Override + public void replacePreferredActivityAsUser(IntentFilter filter, + int match, ComponentName[] set, ComponentName activity, + int userId) { + try { + mPM.replacePreferredActivity(filter, match, set, activity, userId); } catch (RemoteException e) { // Should never happen! } @@ -1370,10 +1520,10 @@ } @Override - public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked, + public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, UserHandle user) { try { - return mPM.setApplicationBlockedSettingAsUser(packageName, blocked, + return mPM.setApplicationHiddenSettingAsUser(packageName, hidden, user.getIdentifier()); } catch (RemoteException re) { // Should never happen! @@ -1382,15 +1532,66 @@ } @Override - public boolean getApplicationBlockedSettingAsUser(String packageName, UserHandle user) { + public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) { try { - return mPM.getApplicationBlockedSettingAsUser(packageName, user.getIdentifier()); + return mPM.getApplicationHiddenSettingAsUser(packageName, user.getIdentifier()); } catch (RemoteException re) { // Should never happen! } return false; } + /** @hide */ + @Override + public KeySet getKeySetByAlias(String packageName, String alias) { + Preconditions.checkNotNull(packageName); + Preconditions.checkNotNull(alias); + KeySet ks; + try { + ks = mPM.getKeySetByAlias(packageName, alias); + } catch (RemoteException e) { + return null; + } + return ks; + } + + /** @hide */ + @Override + public KeySet getSigningKeySet(String packageName) { + Preconditions.checkNotNull(packageName); + KeySet ks; + try { + ks = mPM.getSigningKeySet(packageName); + } catch (RemoteException e) { + return null; + } + return ks; + } + + /** @hide */ + @Override + public boolean isSignedBy(String packageName, KeySet ks) { + Preconditions.checkNotNull(packageName); + Preconditions.checkNotNull(ks); + try { + return mPM.isPackageSignedByKeySet(packageName, ks); + } catch (RemoteException e) { + return false; + } + } + + /** @hide */ + @Override + public boolean isSignedByExactly(String packageName, KeySet ks) { + Preconditions.checkNotNull(packageName); + Preconditions.checkNotNull(ks); + try { + return mPM.isPackageSignedByKeySetExactly(packageName, ks); + } catch (RemoteException e) { + return false; + } + } + /** * @hide */ @@ -1404,6 +1605,150 @@ return null; } + @Override + public PackageInstaller getPackageInstaller() { + synchronized (mLock) { + if (mInstaller == null) { + try { + mInstaller = new PackageInstaller(mContext, this, mPM.getPackageInstaller(), + mContext.getPackageName(), mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + return mInstaller; + } + } + + @Override + public boolean isPackageAvailable(String packageName) { + try { + return mPM.isPackageAvailable(packageName, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** + * @hide + */ + @Override + public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId, + int flags) { + try { + mPM.addCrossProfileIntentFilter(filter, mContext.getOpPackageName(), + mContext.getUserId(), sourceUserId, targetUserId, flags); + } catch (RemoteException e) { + // Should never happen! + } + } + + /** + * @hide + */ + @Override + public void clearCrossProfileIntentFilters(int sourceUserId) { + try { + mPM.clearCrossProfileIntentFilters(sourceUserId, mContext.getOpPackageName(), + mContext.getUserId()); + } catch (RemoteException e) { + // Should never happen! + } + } + + /** + * @hide + */ + public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { + if (itemInfo.showUserIcon != UserHandle.USER_NULL) { + Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon); + if (bitmap == null) { + return UserIcons.getDefaultUserIcon(itemInfo.showUserIcon, /* light= */ false); + } + return new BitmapDrawable(bitmap); + } + Drawable dr = null; + if (itemInfo.packageName != null) { + dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo); + } + if (dr == null) { + dr = itemInfo.loadDefaultIcon(this); + } + return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId())); + } + + private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable, + Rect badgeLocation, boolean tryBadgeInPlace) { + final int badgedWidth = drawable.getIntrinsicWidth(); + final int badgedHeight = drawable.getIntrinsicHeight(); + final boolean canBadgeInPlace = tryBadgeInPlace + && (drawable instanceof BitmapDrawable) + && ((BitmapDrawable) drawable).getBitmap().isMutable(); + + final Bitmap bitmap; + if (canBadgeInPlace) { + bitmap = ((BitmapDrawable) drawable).getBitmap(); + } else { + bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Bitmap.Config.ARGB_8888); + } + Canvas canvas = new Canvas(bitmap); + + if (!canBadgeInPlace) { + drawable.setBounds(0, 0, badgedWidth, badgedHeight); + drawable.draw(canvas); + } + + if (badgeLocation != null) { + if (badgeLocation.left < 0 || badgeLocation.top < 0 + || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) { + throw new IllegalArgumentException("Badge location " + badgeLocation + + " not in badged drawable bounds " + + new Rect(0, 0, badgedWidth, badgedHeight)); + } + badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height()); + + canvas.save(); + canvas.translate(badgeLocation.left, badgeLocation.top); + badgeDrawable.draw(canvas); + canvas.restore(); + } else { + badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight); + badgeDrawable.draw(canvas); + } + + if (!canBadgeInPlace) { + BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap); + + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity()); + } + + return mergedDrawable; + } + + return drawable; + } + + private int getBadgeResIdForUser(int userHandle) { + // Return the framework-provided badge. + UserInfo userInfo = getUserIfProfile(userHandle); + if (userInfo != null && userInfo.isManagedProfile()) { + return com.android.internal.R.drawable.ic_corp_icon_badge; + } + return 0; + } + + private UserInfo getUserIfProfile(int userHandle) { + List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId()); + for (UserInfo user : userProfiles) { + if (user.id == userHandle) { + return user; + } + } + return null; + } + private final ContextImpl mContext; private final IPackageManager mPM;
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index badaec3..0123e167 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java
@@ -25,14 +25,17 @@ import android.content.pm.ServiceInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Debug; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.IBinder; import android.os.Parcel; import android.os.ParcelFileDescriptor; +import com.android.internal.app.IVoiceInteractor; import java.io.FileDescriptor; import java.io.IOException; @@ -75,7 +78,8 @@ boolean finished = data.readInt() != 0; boolean userLeaving = data.readInt() != 0; int configChanges = data.readInt(); - schedulePauseActivity(b, finished, userLeaving, configChanges); + boolean dontReport = data.readInt() != 0; + schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport); return true; } @@ -113,7 +117,8 @@ IBinder b = data.readStrongBinder(); int procState = data.readInt(); boolean isForward = data.readInt() != 0; - scheduleResumeActivity(b, procState, isForward); + Bundle resumeArgs = data.readBundle(); + scheduleResumeActivity(b, procState, isForward, resumeArgs); return true; } @@ -125,7 +130,7 @@ scheduleSendResult(b, ri); return true; } - + case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -135,21 +140,22 @@ ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data); Configuration curConfig = Configuration.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); + IVoiceInteractor voiceInteractor = IVoiceInteractor.Stub.asInterface( + data.readStrongBinder()); int procState = data.readInt(); Bundle state = data.readBundle(); + PersistableBundle persistentState = data.readPersistableBundle(); List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR); List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); boolean notResumed = data.readInt() != 0; boolean isForward = data.readInt() != 0; - String profileName = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - boolean autoStopProfiler = data.readInt() != 0; - scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, procState, state, - ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, voiceInteractor, + procState, state, persistentState, ri, pi, notResumed, isForward, profilerInfo); return true; } - + case SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -265,10 +271,8 @@ data.createTypedArrayList(ProviderInfo.CREATOR); ComponentName testName = (data.readInt() != 0) ? new ComponentName(data) : null; - String profileName = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - boolean autoStopProfiler = data.readInt() != 0; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle testArgs = data.readBundle(); IBinder binder = data.readStrongBinder(); IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder); @@ -283,11 +287,9 @@ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); HashMap<String, IBinder> services = data.readHashMap(null); Bundle coreSettings = data.readBundle(); - bindApplication(packageName, info, - providers, testName, profileName, profileFd, autoStopProfiler, - testArgs, testWatcher, uiAutomationConnection, testMode, - openGlTrace, restrictedBackupMode, persistent, config, compatInfo, - services, coreSettings); + bindApplication(packageName, info, providers, testName, profilerInfo, testArgs, + testWatcher, uiAutomationConnection, testMode, openGlTrace, + restrictedBackupMode, persistent, config, compatInfo, services, coreSettings); return true; } @@ -305,14 +307,6 @@ return true; } - case REQUEST_THUMBNAIL_TRANSACTION: - { - data.enforceInterface(IApplicationThread.descriptor); - IBinder b = data.readStrongBinder(); - requestThumbnail(b); - return true; - } - case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -338,7 +332,7 @@ final String proxy = data.readString(); final String port = data.readString(); final String exclList = data.readString(); - final String pacFileUrl = data.readString(); + final Uri pacFileUrl = Uri.CREATOR.createFromParcel(data); setHttpProxy(proxy, port, exclList, pacFileUrl); return true; } @@ -402,7 +396,7 @@ scheduleLowMemory(); return true; } - + case SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -410,19 +404,18 @@ scheduleActivityConfigurationChanged(b); return true; } - + case PROFILER_CONTROL_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); boolean start = data.readInt() != 0; int profileType = data.readInt(); - String path = data.readString(); - ParcelFileDescriptor fd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - profilerControl(start, path, fd, profileType); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + profilerControl(start, profilerInfo, profileType); return true; } - + case SET_SCHEDULING_GROUP_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -610,6 +603,16 @@ return true; } + case SCHEDULE_ON_NEW_ACTIVITY_OPTIONS_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + IBinder token = data.readStrongBinder(); + ActivityOptions options = new ActivityOptions(data.readBundle()); + scheduleOnNewActivityOptions(token, options); + reply.writeNoException(); + return true; + } + case SET_PROCESS_STATE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -636,6 +639,34 @@ reply.writeNoException(); return true; } + + case CANCEL_VISIBLE_BEHIND_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + IBinder token = data.readStrongBinder(); + scheduleCancelVisibleBehind(token); + reply.writeNoException(); + return true; + } + + case BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + IBinder token = data.readStrongBinder(); + boolean enabled = data.readInt() > 0; + scheduleBackgroundVisibleBehindChanged(token, enabled); + reply.writeNoException(); + return true; + } + + case ENTER_ANIMATION_COMPLETE_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + IBinder token = data.readStrongBinder(); + scheduleEnterAnimationComplete(token); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -659,13 +690,14 @@ } public final void schedulePauseActivity(IBinder token, boolean finished, - boolean userLeaving, int configChanges) throws RemoteException { + boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(finished ? 1 : 0); data.writeInt(userLeaving ? 1 :0); data.writeInt(configChanges); + data.writeInt(dontReport ? 1 : 0); mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); @@ -705,20 +737,22 @@ data.recycle(); } - public final void scheduleResumeActivity(IBinder token, int procState, boolean isForward) + public final void scheduleResumeActivity(IBinder token, int procState, boolean isForward, + Bundle resumeArgs) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(procState); data.writeInt(isForward ? 1 : 0); + data.writeBundle(resumeArgs); mRemote.transact(SCHEDULE_RESUME_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } public final void scheduleSendResult(IBinder token, List<ResultInfo> results) - throws RemoteException { + throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); @@ -730,10 +764,10 @@ public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, - int procState, Bundle state, List<ResultInfo> pendingResults, - List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) - throws RemoteException { + IVoiceInteractor voiceInteractor, int procState, Bundle state, + PersistableBundle persistentState, List<ResultInfo> pendingResults, + List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, + ProfilerInfo profilerInfo) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); intent.writeToParcel(data, 0); @@ -742,20 +776,20 @@ info.writeToParcel(data, 0); curConfig.writeToParcel(data, 0); compatInfo.writeToParcel(data, 0); + data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null); data.writeInt(procState); data.writeBundle(state); + data.writePersistableBundle(persistentState); data.writeTypedList(pendingResults); data.writeTypedList(pendingNewIntents); data.writeInt(notResumed ? 1 : 0); data.writeInt(isForward ? 1 : 0); - data.writeString(profileName); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } - data.writeInt(autoStopProfiler ? 1 : 0); mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); @@ -886,7 +920,7 @@ } public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, - int flags, Intent args) throws RemoteException { + int flags, Intent args) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); @@ -915,9 +949,8 @@ } public final void bindApplication(String packageName, ApplicationInfo info, - List<ProviderInfo> providers, ComponentName testName, String profileName, - ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle testArgs, - IInstrumentationWatcher testWatcher, + List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo, + Bundle testArgs, IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, @@ -933,14 +966,12 @@ data.writeInt(1); testName.writeToParcel(data, 0); } - data.writeString(profileName); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } - data.writeInt(autoStopProfiler ? 1 : 0); data.writeBundle(testArgs); data.writeStrongInterface(testWatcher); data.writeStrongInterface(uiAutomationConnection); @@ -973,16 +1004,6 @@ data.recycle(); } - public final void requestThumbnail(IBinder token) - throws RemoteException { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(IApplicationThread.descriptor); - data.writeStrongBinder(token); - mRemote.transact(REQUEST_THUMBNAIL_TRANSACTION, data, null, - IBinder.FLAG_ONEWAY); - data.recycle(); - } - public final void scheduleConfigurationChanged(Configuration config) throws RemoteException { Parcel data = Parcel.obtain(); @@ -1010,13 +1031,13 @@ } public void setHttpProxy(String proxy, String port, String exclList, - String pacFileUrl) throws RemoteException { + Uri pacFileUrl) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeString(proxy); data.writeString(port); data.writeString(exclList); - data.writeString(pacFileUrl); + pacFileUrl.writeToParcel(data, 0); mRemote.transact(SET_HTTP_PROXY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } @@ -1077,7 +1098,7 @@ IBinder.FLAG_ONEWAY); data.recycle(); } - + public final void scheduleActivityConfigurationChanged( IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); @@ -1087,17 +1108,16 @@ IBinder.FLAG_ONEWAY); data.recycle(); } - - public void profilerControl(boolean start, String path, - ParcelFileDescriptor fd, int profileType) throws RemoteException { + + public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) + throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeInt(start ? 1 : 0); data.writeInt(profileType); - data.writeString(path); - if (fd != null) { + if (profilerInfo != null) { data.writeInt(1); - fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -1105,7 +1125,7 @@ IBinder.FLAG_ONEWAY); data.recycle(); } - + public void setSchedulingGroup(int group) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -1114,7 +1134,7 @@ IBinder.FLAG_ONEWAY); data.recycle(); } - + public void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -1123,9 +1143,8 @@ mRemote.transact(DISPATCH_PACKAGE_BROADCAST_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); - } - + public void scheduleCrash(String msg) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -1133,7 +1152,6 @@ mRemote.transact(SCHEDULE_CRASH_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); - } public void dumpHeap(boolean managed, String path, @@ -1255,7 +1273,20 @@ data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(timeout ? 1 : 0); - mRemote.transact(SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + mRemote.transact(SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION, data, null, + IBinder.FLAG_ONEWAY); + data.recycle(); + } + + @Override + public void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options) + throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeStrongBinder(token); + data.writeBundle(options == null ? null : options.toBundle()); + mRemote.transact(SCHEDULE_ON_NEW_ACTIVITY_OPTIONS_TRANSACTION, data, null, + IBinder.FLAG_ONEWAY); data.recycle(); } @@ -1285,4 +1316,34 @@ mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } + + @Override + public void scheduleCancelVisibleBehind(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeStrongBinder(token); + mRemote.transact(CANCEL_VISIBLE_BEHIND_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } + + @Override + public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled) + throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeStrongBinder(token); + data.writeInt(enabled ? 1 : 0); + mRemote.transact(BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION, data, null, + IBinder.FLAG_ONEWAY); + data.recycle(); + } + + @Override + public void scheduleEnterAnimationComplete(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeStrongBinder(token); + mRemote.transact(ENTER_ANIMATION_COMPLETE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } }
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 89ee145..0092ee7 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java
@@ -16,12 +16,24 @@ package android.app; +import com.android.internal.util.FastPrintWriter; + +import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.transition.Transition; +import android.transition.TransitionManager; +import android.transition.TransitionSet; +import android.transition.TransitionUtils; +import android.util.ArrayMap; import android.util.Log; import android.util.LogWriter; -import com.android.internal.util.FastPrintWriter; +import android.util.Pair; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -37,15 +49,19 @@ final CharSequence mBreadCrumbTitleText; final int mBreadCrumbShortTitleRes; final CharSequence mBreadCrumbShortTitleText; + final ArrayList<String> mSharedElementSourceNames; + final ArrayList<String> mSharedElementTargetNames; public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) { int numRemoved = 0; BackStackRecord.Op op = bse.mHead; while (op != null) { - if (op.removed != null) numRemoved += op.removed.size(); + if (op.removed != null) { + numRemoved += op.removed.size(); + } op = op.next; } - mOps = new int[bse.mNumOp*7 + numRemoved]; + mOps = new int[bse.mNumOp * 7 + numRemoved]; if (!bse.mAddToBackStack) { throw new IllegalStateException("Not on back stack"); @@ -63,7 +79,7 @@ if (op.removed != null) { final int N = op.removed.size(); mOps[pos++] = N; - for (int i=0; i<N; i++) { + for (int i = 0; i < N; i++) { mOps[pos++] = op.removed.get(i).mIndex; } } else { @@ -79,6 +95,8 @@ mBreadCrumbTitleText = bse.mBreadCrumbTitleText; mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes; mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText; + mSharedElementSourceNames = bse.mSharedElementSourceNames; + mSharedElementTargetNames = bse.mSharedElementTargetNames; } public BackStackState(Parcel in) { @@ -91,6 +109,8 @@ mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mBreadCrumbShortTitleRes = in.readInt(); mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + mSharedElementSourceNames = in.createStringArrayList(); + mSharedElementTargetNames = in.createStringArrayList(); } public BackStackRecord instantiate(FragmentManagerImpl fm) { @@ -100,8 +120,10 @@ while (pos < mOps.length) { BackStackRecord.Op op = new BackStackRecord.Op(); op.cmd = mOps[pos++]; - if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, - "Instantiate " + bse + " op #" + num + " base fragment #" + mOps[pos]); + if (FragmentManagerImpl.DEBUG) { + Log.v(FragmentManagerImpl.TAG, + "Instantiate " + bse + " op #" + num + " base fragment #" + mOps[pos]); + } int findex = mOps[pos++]; if (findex >= 0) { Fragment f = fm.mActive.get(findex); @@ -116,9 +138,11 @@ final int N = mOps[pos++]; if (N > 0) { op.removed = new ArrayList<Fragment>(N); - for (int i=0; i<N; i++) { - if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, - "Instantiate " + bse + " set remove fragment #" + mOps[pos]); + for (int i = 0; i < N; i++) { + if (FragmentManagerImpl.DEBUG) { + Log.v(FragmentManagerImpl.TAG, + "Instantiate " + bse + " set remove fragment #" + mOps[pos]); + } Fragment r = fm.mActive.get(mOps[pos++]); op.removed.add(r); } @@ -135,6 +159,8 @@ bse.mBreadCrumbTitleText = mBreadCrumbTitleText; bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes; bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText; + bse.mSharedElementSourceNames = mSharedElementSourceNames; + bse.mSharedElementTargetNames = mSharedElementTargetNames; bse.bumpBackStackNesting(1); return bse; } @@ -153,6 +179,8 @@ TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0); dest.writeInt(mBreadCrumbShortTitleRes); TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0); + dest.writeStringList(mSharedElementSourceNames); + dest.writeStringList(mSharedElementTargetNames); } public static final Parcelable.Creator<BackStackState> CREATOR @@ -217,6 +245,9 @@ int mBreadCrumbShortTitleRes; CharSequence mBreadCrumbShortTitleText; + ArrayList<String> mSharedElementSourceNames; + ArrayList<String> mSharedElementTargetNames; + @Override public String toString() { StringBuilder sb = new StringBuilder(128); @@ -240,78 +271,112 @@ void dump(String prefix, PrintWriter writer, boolean full) { if (full) { - writer.print(prefix); writer.print("mName="); writer.print(mName); - writer.print(" mIndex="); writer.print(mIndex); - writer.print(" mCommitted="); writer.println(mCommitted); + writer.print(prefix); + writer.print("mName="); + writer.print(mName); + writer.print(" mIndex="); + writer.print(mIndex); + writer.print(" mCommitted="); + writer.println(mCommitted); if (mTransition != FragmentTransaction.TRANSIT_NONE) { - writer.print(prefix); writer.print("mTransition=#"); - writer.print(Integer.toHexString(mTransition)); - writer.print(" mTransitionStyle=#"); - writer.println(Integer.toHexString(mTransitionStyle)); + writer.print(prefix); + writer.print("mTransition=#"); + writer.print(Integer.toHexString(mTransition)); + writer.print(" mTransitionStyle=#"); + writer.println(Integer.toHexString(mTransitionStyle)); } - if (mEnterAnim != 0 || mExitAnim !=0) { - writer.print(prefix); writer.print("mEnterAnim=#"); - writer.print(Integer.toHexString(mEnterAnim)); - writer.print(" mExitAnim=#"); - writer.println(Integer.toHexString(mExitAnim)); + if (mEnterAnim != 0 || mExitAnim != 0) { + writer.print(prefix); + writer.print("mEnterAnim=#"); + writer.print(Integer.toHexString(mEnterAnim)); + writer.print(" mExitAnim=#"); + writer.println(Integer.toHexString(mExitAnim)); } - if (mPopEnterAnim != 0 || mPopExitAnim !=0) { - writer.print(prefix); writer.print("mPopEnterAnim=#"); - writer.print(Integer.toHexString(mPopEnterAnim)); - writer.print(" mPopExitAnim=#"); - writer.println(Integer.toHexString(mPopExitAnim)); + if (mPopEnterAnim != 0 || mPopExitAnim != 0) { + writer.print(prefix); + writer.print("mPopEnterAnim=#"); + writer.print(Integer.toHexString(mPopEnterAnim)); + writer.print(" mPopExitAnim=#"); + writer.println(Integer.toHexString(mPopExitAnim)); } if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) { - writer.print(prefix); writer.print("mBreadCrumbTitleRes=#"); - writer.print(Integer.toHexString(mBreadCrumbTitleRes)); - writer.print(" mBreadCrumbTitleText="); - writer.println(mBreadCrumbTitleText); + writer.print(prefix); + writer.print("mBreadCrumbTitleRes=#"); + writer.print(Integer.toHexString(mBreadCrumbTitleRes)); + writer.print(" mBreadCrumbTitleText="); + writer.println(mBreadCrumbTitleText); } if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) { - writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#"); - writer.print(Integer.toHexString(mBreadCrumbShortTitleRes)); - writer.print(" mBreadCrumbShortTitleText="); - writer.println(mBreadCrumbShortTitleText); + writer.print(prefix); + writer.print("mBreadCrumbShortTitleRes=#"); + writer.print(Integer.toHexString(mBreadCrumbShortTitleRes)); + writer.print(" mBreadCrumbShortTitleText="); + writer.println(mBreadCrumbShortTitleText); } } if (mHead != null) { - writer.print(prefix); writer.println("Operations:"); + writer.print(prefix); + writer.println("Operations:"); String innerPrefix = prefix + " "; Op op = mHead; int num = 0; while (op != null) { String cmdStr; switch (op.cmd) { - case OP_NULL: cmdStr="NULL"; break; - case OP_ADD: cmdStr="ADD"; break; - case OP_REPLACE: cmdStr="REPLACE"; break; - case OP_REMOVE: cmdStr="REMOVE"; break; - case OP_HIDE: cmdStr="HIDE"; break; - case OP_SHOW: cmdStr="SHOW"; break; - case OP_DETACH: cmdStr="DETACH"; break; - case OP_ATTACH: cmdStr="ATTACH"; break; - default: cmdStr="cmd=" + op.cmd; break; + case OP_NULL: + cmdStr = "NULL"; + break; + case OP_ADD: + cmdStr = "ADD"; + break; + case OP_REPLACE: + cmdStr = "REPLACE"; + break; + case OP_REMOVE: + cmdStr = "REMOVE"; + break; + case OP_HIDE: + cmdStr = "HIDE"; + break; + case OP_SHOW: + cmdStr = "SHOW"; + break; + case OP_DETACH: + cmdStr = "DETACH"; + break; + case OP_ATTACH: + cmdStr = "ATTACH"; + break; + default: + cmdStr = "cmd=" + op.cmd; + break; } - writer.print(prefix); writer.print(" Op #"); writer.print(num); - writer.print(": "); writer.print(cmdStr); - writer.print(" "); writer.println(op.fragment); + writer.print(prefix); + writer.print(" Op #"); + writer.print(num); + writer.print(": "); + writer.print(cmdStr); + writer.print(" "); + writer.println(op.fragment); if (full) { if (op.enterAnim != 0 || op.exitAnim != 0) { - writer.print(innerPrefix); writer.print("enterAnim=#"); - writer.print(Integer.toHexString(op.enterAnim)); - writer.print(" exitAnim=#"); - writer.println(Integer.toHexString(op.exitAnim)); + writer.print(innerPrefix); + writer.print("enterAnim=#"); + writer.print(Integer.toHexString(op.enterAnim)); + writer.print(" exitAnim=#"); + writer.println(Integer.toHexString(op.exitAnim)); } if (op.popEnterAnim != 0 || op.popExitAnim != 0) { - writer.print(innerPrefix); writer.print("popEnterAnim=#"); - writer.print(Integer.toHexString(op.popEnterAnim)); - writer.print(" popExitAnim=#"); - writer.println(Integer.toHexString(op.popExitAnim)); + writer.print(innerPrefix); + writer.print("popEnterAnim=#"); + writer.print(Integer.toHexString(op.popEnterAnim)); + writer.print(" popExitAnim=#"); + writer.println(Integer.toHexString(op.popExitAnim)); } } if (op.removed != null && op.removed.size() > 0) { - for (int i=0; i<op.removed.size(); i++) { + for (int i = 0; i < op.removed.size(); i++) { writer.print(innerPrefix); if (op.removed.size() == 1) { writer.print("Removed: "); @@ -319,8 +384,10 @@ if (i == 0) { writer.println("Removed:"); } - writer.print(innerPrefix); writer.print(" #"); writer.print(i); - writer.print(": "); + writer.print(innerPrefix); + writer.print(" #"); + writer.print(i); + writer.print(": "); } writer.println(op.removed.get(i)); } @@ -494,6 +561,62 @@ return this; } + @Override + public FragmentTransaction addSharedElement(View sharedElement, String name) { + String transitionName = sharedElement.getTransitionName(); + if (transitionName == null) { + throw new IllegalArgumentException("Unique transitionNames are required for all" + + " sharedElements"); + } + if (mSharedElementSourceNames == null) { + mSharedElementSourceNames = new ArrayList<String>(); + mSharedElementTargetNames = new ArrayList<String>(); + } + mSharedElementSourceNames.add(transitionName); + mSharedElementTargetNames.add(name); + return this; + } + + /** TODO: remove this */ + @Override + public FragmentTransaction setSharedElement(View sharedElement, String name) { + String transitionName = sharedElement.getTransitionName(); + if (transitionName == null) { + throw new IllegalArgumentException("Unique transitionNames are required for all" + + " sharedElements"); + } + mSharedElementSourceNames = new ArrayList<String>(1); + mSharedElementSourceNames.add(transitionName); + + mSharedElementTargetNames = new ArrayList<String>(1); + mSharedElementTargetNames.add(name); + return this; + } + + /** TODO: remove this */ + @Override + public FragmentTransaction setSharedElements(Pair<View, String>... sharedElements) { + if (sharedElements == null || sharedElements.length == 0) { + mSharedElementSourceNames = null; + mSharedElementTargetNames = null; + } else { + ArrayList<String> sourceNames = new ArrayList<String>(sharedElements.length); + ArrayList<String> targetNames = new ArrayList<String>(sharedElements.length); + for (int i = 0; i < sharedElements.length; i++) { + String transitionName = sharedElements[i].first.getTransitionName(); + if (transitionName == null) { + throw new IllegalArgumentException("Unique transitionNames are required for all" + + " sharedElements"); + } + sourceNames.add(transitionName); + targetNames.add(sharedElements[i].second); + } + mSharedElementSourceNames = sourceNames; + mSharedElementTargetNames = targetNames; + } + return this; + } + public FragmentTransaction setTransitionStyle(int styleRes) { mTransitionStyle = styleRes; return this; @@ -550,21 +673,27 @@ if (!mAddToBackStack) { return; } - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting in " + this - + " by " + amt); + if (FragmentManagerImpl.DEBUG) { + Log.v(TAG, "Bump nesting in " + this + + " by " + amt); + } Op op = mHead; while (op != null) { if (op.fragment != null) { op.fragment.mBackStackNesting += amt; - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " - + op.fragment + " to " + op.fragment.mBackStackNesting); + if (FragmentManagerImpl.DEBUG) { + Log.v(TAG, "Bump nesting of " + + op.fragment + " to " + op.fragment.mBackStackNesting); + } } if (op.removed != null) { - for (int i=op.removed.size()-1; i>=0; i--) { + for (int i = op.removed.size() - 1; i >= 0; i--) { Fragment r = op.removed.get(i); r.mBackStackNesting += amt; - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " - + r + " to " + r.mBackStackNesting); + if (FragmentManagerImpl.DEBUG) { + Log.v(TAG, "Bump nesting of " + + r + " to " + r.mBackStackNesting); + } } } op = op.next; @@ -578,9 +707,11 @@ public int commitAllowingStateLoss() { return commitInternal(true); } - + int commitInternal(boolean allowStateLoss) { - if (mCommitted) throw new IllegalStateException("commit already called"); + if (mCommitted) { + throw new IllegalStateException("commit already called"); + } if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Commit: " + this); LogWriter logw = new LogWriter(Log.VERBOSE, TAG); @@ -597,9 +728,11 @@ mManager.enqueueAction(this, allowStateLoss); return mIndex; } - + public void run() { - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); + if (FragmentManagerImpl.DEBUG) { + Log.v(TAG, "Run: " + this); + } if (mAddToBackStack) { if (mIndex < 0) { @@ -609,6 +742,11 @@ bumpBackStackNesting(1); + SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); + SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); + calculateFragments(firstOutFragments, lastInFragments); + beginTransition(firstOutFragments, lastInFragments, false); + Op op = mHead; while (op != null) { switch (op.cmd) { @@ -616,14 +754,17 @@ Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); - } break; + } + break; case OP_REPLACE: { Fragment f = op.fragment; if (mManager.mAdded != null) { - for (int i=0; i<mManager.mAdded.size(); i++) { + for (int i = 0; i < mManager.mAdded.size(); i++) { Fragment old = mManager.mAdded.get(i); - if (FragmentManagerImpl.DEBUG) Log.v(TAG, - "OP_REPLACE: adding=" + f + " old=" + old); + if (FragmentManagerImpl.DEBUG) { + Log.v(TAG, + "OP_REPLACE: adding=" + f + " old=" + old); + } if (f == null || old.mContainerId == f.mContainerId) { if (old == f) { op.fragment = f = null; @@ -635,8 +776,10 @@ old.mNextAnim = op.exitAnim; if (mAddToBackStack) { old.mBackStackNesting += 1; - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " - + old + " to " + old.mBackStackNesting); + if (FragmentManagerImpl.DEBUG) { + Log.v(TAG, "Bump nesting of " + + old + " to " + old.mBackStackNesting); + } } mManager.removeFragment(old, mTransition, mTransitionStyle); } @@ -647,32 +790,38 @@ f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } - } break; + } + break; case OP_REMOVE: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.removeFragment(f, mTransition, mTransitionStyle); - } break; + } + break; case OP_HIDE: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.hideFragment(f, mTransition, mTransitionStyle); - } break; + } + break; case OP_SHOW: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.showFragment(f, mTransition, mTransitionStyle); - } break; + } + break; case OP_DETACH: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.detachFragment(f, mTransition, mTransitionStyle); - } break; + } + break; case OP_ATTACH: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.attachFragment(f, mTransition, mTransitionStyle); - } break; + } + break; default: { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } @@ -689,7 +838,671 @@ } } - public void popFromBackStack(boolean doStateMove) { + private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) { + if (fragment != null) { + int containerId = fragment.mContainerId; + if (containerId != 0 && !fragment.isHidden() && fragment.isAdded() && + fragment.getView() != null && fragments.get(containerId) == null) { + fragments.put(containerId, fragment); + } + } + } + + private void setLastIn(SparseArray<Fragment> fragments, Fragment fragment) { + if (fragment != null) { + int containerId = fragment.mContainerId; + if (containerId != 0) { + fragments.put(containerId, fragment); + } + } + } + + /** + * Finds the first removed fragment and last added fragments when going forward. + * If none of the fragments have transitions, then both lists will be empty. + * + * @param firstOutFragments The list of first fragments to be removed, keyed on the + * container ID. This list will be modified by the method. + * @param lastInFragments The list of last fragments to be added, keyed on the + * container ID. This list will be modified by the method. + */ + private void calculateFragments(SparseArray<Fragment> firstOutFragments, + SparseArray<Fragment> lastInFragments) { + if (!mManager.mContainer.hasView()) { + return; // nothing to see, so no transitions + } + Op op = mHead; + while (op != null) { + switch (op.cmd) { + case OP_ADD: + setLastIn(lastInFragments, op.fragment); + break; + case OP_REPLACE: { + Fragment f = op.fragment; + if (mManager.mAdded != null) { + for (int i = 0; i < mManager.mAdded.size(); i++) { + Fragment old = mManager.mAdded.get(i); + if (f == null || old.mContainerId == f.mContainerId) { + if (old == f) { + f = null; + } else { + setFirstOut(firstOutFragments, old); + } + } + } + } + setLastIn(lastInFragments, f); + break; + } + case OP_REMOVE: + setFirstOut(firstOutFragments, op.fragment); + break; + case OP_HIDE: + setFirstOut(firstOutFragments, op.fragment); + break; + case OP_SHOW: + setLastIn(lastInFragments, op.fragment); + break; + case OP_DETACH: + setFirstOut(firstOutFragments, op.fragment); + break; + case OP_ATTACH: + setLastIn(lastInFragments, op.fragment); + break; + } + + op = op.next; + } + } + + /** + * Finds the first removed fragment and last added fragments when popping the back stack. + * If none of the fragments have transitions, then both lists will be empty. + * + * @param firstOutFragments The list of first fragments to be removed, keyed on the + * container ID. This list will be modified by the method. + * @param lastInFragments The list of last fragments to be added, keyed on the + * container ID. This list will be modified by the method. + */ + public void calculateBackFragments(SparseArray<Fragment> firstOutFragments, + SparseArray<Fragment> lastInFragments) { + if (!mManager.mContainer.hasView()) { + return; // nothing to see, so no transitions + } + Op op = mHead; + while (op != null) { + switch (op.cmd) { + case OP_ADD: + setFirstOut(firstOutFragments, op.fragment); + break; + case OP_REPLACE: + if (op.removed != null) { + for (int i = op.removed.size() - 1; i >= 0; i--) { + setLastIn(lastInFragments, op.removed.get(i)); + } + } + setFirstOut(firstOutFragments, op.fragment); + break; + case OP_REMOVE: + setLastIn(lastInFragments, op.fragment); + break; + case OP_HIDE: + setLastIn(lastInFragments, op.fragment); + break; + case OP_SHOW: + setFirstOut(firstOutFragments, op.fragment); + break; + case OP_DETACH: + setLastIn(lastInFragments, op.fragment); + break; + case OP_ATTACH: + setFirstOut(firstOutFragments, op.fragment); + break; + } + + op = op.next; + } + } + + /** + * When custom fragment transitions are used, this sets up the state for each transition + * and begins the transition. A different transition is started for each fragment container + * and consists of up to 3 different transitions: the exit transition, a shared element + * transition and an enter transition. + * + * <p>The exit transition operates against the leaf nodes of the first fragment + * with a view that was removed. If no such fragment was removed, then no exit + * transition is executed. The exit transition comes from the outgoing fragment.</p> + * + * <p>The enter transition operates against the last fragment that was added. If + * that fragment does not have a view or no fragment was added, then no enter + * transition is executed. The enter transition comes from the incoming fragment.</p> + * + * <p>The shared element transition operates against all views and comes either + * from the outgoing fragment or the incoming fragment, depending on whether this + * is going forward or popping the back stack. When going forward, the incoming + * fragment's enter shared element transition is used, but when going back, the + * outgoing fragment's return shared element transition is used. Shared element + * transitions only operate if there is both an incoming and outgoing fragment.</p> + * + * @param firstOutFragments The list of first fragments to be removed, keyed on the + * container ID. + * @param lastInFragments The list of last fragments to be added, keyed on the + * container ID. + * @param isBack true if this is popping the back stack or false if this is a + * forward operation. + * @return The TransitionState used to complete the operation of the transition + * in {@link #setNameOverrides(android.app.BackStackRecord.TransitionState, java.util.ArrayList, + * java.util.ArrayList)}. + */ + private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments, + SparseArray<Fragment> lastInFragments, boolean isBack) { + TransitionState state = new TransitionState(); + + // Adding a non-existent target view makes sure that the transitions don't target + // any views by default. They'll only target the views we tell add. If we don't + // add any, then no views will be targeted. + state.nonExistentView = new View(mManager.mActivity); + + // Go over all leaving fragments. + for (int i = 0; i < firstOutFragments.size(); i++) { + int containerId = firstOutFragments.keyAt(i); + configureTransitions(containerId, state, isBack, firstOutFragments, + lastInFragments); + } + + // Now go over all entering fragments that didn't have a leaving fragment. + for (int i = 0; i < lastInFragments.size(); i++) { + int containerId = lastInFragments.keyAt(i); + if (firstOutFragments.get(containerId) == null) { + configureTransitions(containerId, state, isBack, firstOutFragments, + lastInFragments); + } + } + return state; + } + + private static Transition cloneTransition(Transition transition) { + if (transition != null) { + transition = transition.clone(); + } + return transition; + } + + private static Transition getEnterTransition(Fragment inFragment, boolean isBack) { + if (inFragment == null) { + return null; + } + return cloneTransition(isBack ? inFragment.getReenterTransition() : + inFragment.getEnterTransition()); + } + + private static Transition getExitTransition(Fragment outFragment, boolean isBack) { + if (outFragment == null) { + return null; + } + return cloneTransition(isBack ? outFragment.getReturnTransition() : + outFragment.getExitTransition()); + } + + private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment, + boolean isBack) { + if (inFragment == null || outFragment == null) { + return null; + } + return cloneTransition(isBack ? outFragment.getSharedElementReturnTransition() : + inFragment.getSharedElementEnterTransition()); + } + + private static ArrayList<View> captureExitingViews(Transition exitTransition, + Fragment outFragment, ArrayMap<String, View> namedViews) { + ArrayList<View> viewList = null; + if (exitTransition != null) { + viewList = new ArrayList<View>(); + View root = outFragment.getView(); + root.captureTransitioningViews(viewList); + if (namedViews != null) { + viewList.removeAll(namedViews.values()); + } + addTargets(exitTransition, viewList); + } + return viewList; + } + + private ArrayMap<String, View> remapSharedElements(TransitionState state, Fragment outFragment, + boolean isBack) { + ArrayMap<String, View> namedViews = new ArrayMap<String, View>(); + if (mSharedElementSourceNames != null) { + outFragment.getView().findNamedViews(namedViews); + if (isBack) { + namedViews.retainAll(mSharedElementTargetNames); + } else { + namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames, + namedViews); + } + } + + if (isBack) { + outFragment.mEnterTransitionCallback.onMapSharedElements( + mSharedElementTargetNames, namedViews); + setBackNameOverrides(state, namedViews, false); + } else { + outFragment.mExitTransitionCallback.onMapSharedElements( + mSharedElementTargetNames, namedViews); + setNameOverrides(state, namedViews, false); + } + + return namedViews; + } + + /** + * Prepares the enter transition by adding a non-existent view to the transition's target list + * and setting it epicenter callback. By adding a non-existent view to the target list, + * we can prevent any view from being targeted at the beginning of the transition. + * We will add to the views before the end state of the transition is captured so that the + * views will appear. At the start of the transition, we clear the list of targets so that + * we can restore the state of the transition and use it again. + * + * <p>The shared element transition maps its shared elements immediately prior to + * capturing the final state of the Transition.</p> + */ + private ArrayList<View> addTransitionTargets(final TransitionState state, + final Transition enterTransition, final Transition sharedElementTransition, + final Transition overallTransition, final View container, + final Fragment inFragment, final Fragment outFragment, + final ArrayList<View> hiddenFragmentViews, final boolean isBack, + final ArrayList<View> sharedElementTargets) { + if (enterTransition == null && sharedElementTransition == null && + overallTransition == null) { + return null; + } + final ArrayList<View> enteringViews = new ArrayList<View>(); + container.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + container.getViewTreeObserver().removeOnPreDrawListener(this); + + // Don't include any newly-hidden fragments in the transition. + excludeHiddenFragments(hiddenFragmentViews, inFragment.mContainerId, + overallTransition); + + ArrayMap<String, View> namedViews = null; + if (sharedElementTransition != null) { + namedViews = mapSharedElementsIn(state, isBack, inFragment); + removeTargets(sharedElementTransition, sharedElementTargets); + sharedElementTargets.clear(); + if (namedViews.isEmpty()) { + sharedElementTargets.add(state.nonExistentView); + } else { + sharedElementTargets.addAll(namedViews.values()); + } + + addTargets(sharedElementTransition, sharedElementTargets); + + setEpicenterIn(namedViews, state); + + callSharedElementEnd(state, inFragment, outFragment, isBack, + namedViews); + } + + if (enterTransition != null) { + View view = inFragment.getView(); + if (view != null) { + view.captureTransitioningViews(enteringViews); + if (namedViews != null) { + enteringViews.removeAll(namedViews.values()); + } + addTargets(enterTransition, enteringViews); + } + setSharedElementEpicenter(enterTransition, state); + } + return true; + } + }); + return enteringViews; + } + + private void callSharedElementEnd(TransitionState state, Fragment inFragment, + Fragment outFragment, boolean isBack, ArrayMap<String, View> namedViews) { + SharedElementCallback sharedElementCallback = isBack ? + outFragment.mEnterTransitionCallback : + inFragment.mEnterTransitionCallback; + ArrayList<String> names = new ArrayList<String>(namedViews.keySet()); + ArrayList<View> views = new ArrayList<View>(namedViews.values()); + sharedElementCallback.onSharedElementEnd(names, views, null); + } + + private void setEpicenterIn(ArrayMap<String, View> namedViews, TransitionState state) { + if (mSharedElementTargetNames != null && !namedViews.isEmpty()) { + // now we know the epicenter of the entering transition. + View epicenter = namedViews + .get(mSharedElementTargetNames.get(0)); + if (epicenter != null) { + state.enteringEpicenterView = epicenter; + } + } + } + + private ArrayMap<String, View> mapSharedElementsIn(TransitionState state, + boolean isBack, Fragment inFragment) { + // Now map the shared elements in the incoming fragment + ArrayMap<String, View> namedViews = mapEnteringSharedElements(state, inFragment, isBack); + + // remap shared elements and set the name mapping used + // in the shared element transition. + if (isBack) { + inFragment.mExitTransitionCallback.onMapSharedElements( + mSharedElementTargetNames, namedViews); + setBackNameOverrides(state, namedViews, true); + } else { + inFragment.mEnterTransitionCallback.onMapSharedElements( + mSharedElementTargetNames, namedViews); + setNameOverrides(state, namedViews, true); + } + return namedViews; + } + + private static Transition mergeTransitions(Transition enterTransition, + Transition exitTransition, Transition sharedElementTransition, Fragment inFragment, + boolean isBack) { + boolean overlap = true; + if (enterTransition != null && exitTransition != null) { + overlap = isBack ? inFragment.getAllowReturnTransitionOverlap() : + inFragment.getAllowEnterTransitionOverlap(); + } + + // Wrap the transitions. Explicit targets like in enter and exit will cause the + // views to be targeted regardless of excluded views. If that happens, then the + // excluded fragments views (hidden fragments) will still be in the transition. + + Transition transition; + if (overlap) { + // Regular transition -- do it all together + TransitionSet transitionSet = new TransitionSet(); + if (enterTransition != null) { + transitionSet.addTransition(enterTransition); + } + if (exitTransition != null) { + transitionSet.addTransition(exitTransition); + } + if (sharedElementTransition != null) { + transitionSet.addTransition(sharedElementTransition); + } + transition = transitionSet; + } else { + // First do exit, then enter, but allow shared element transition to happen + // during both. + Transition staggered = null; + if (exitTransition != null && enterTransition != null) { + staggered = new TransitionSet() + .addTransition(exitTransition) + .addTransition(enterTransition) + .setOrdering(TransitionSet.ORDERING_SEQUENTIAL); + } else if (exitTransition != null) { + staggered = exitTransition; + } else if (enterTransition != null) { + staggered = enterTransition; + } + if (sharedElementTransition != null) { + TransitionSet together = new TransitionSet(); + if (staggered != null) { + together.addTransition(staggered); + } + together.addTransition(sharedElementTransition); + transition = together; + } else { + transition = staggered; + } + } + return transition; + } + + /** + * Configures custom transitions for a specific fragment container. + * + * @param containerId The container ID of the fragments to configure the transition for. + * @param state The Transition State keeping track of the executing transitions. + * @param firstOutFragments The list of first fragments to be removed, keyed on the + * container ID. + * @param lastInFragments The list of last fragments to be added, keyed on the + * container ID. + * @param isBack true if this is popping the back stack or false if this is a + * forward operation. + */ + private void configureTransitions(int containerId, TransitionState state, boolean isBack, + SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) { + ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId); + if (sceneRoot != null) { + Fragment inFragment = lastInFragments.get(containerId); + Fragment outFragment = firstOutFragments.get(containerId); + + Transition enterTransition = getEnterTransition(inFragment, isBack); + Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment, + isBack); + Transition exitTransition = getExitTransition(outFragment, isBack); + + if (enterTransition == null && sharedElementTransition == null && + exitTransition == null) { + return; // no transitions! + } + if (enterTransition != null) { + enterTransition.addTarget(state.nonExistentView); + } + ArrayMap<String, View> namedViews = null; + ArrayList<View> sharedElementTargets = new ArrayList<View>(); + if (sharedElementTransition != null) { + namedViews = remapSharedElements(state, outFragment, isBack); + if (namedViews.isEmpty()) { + sharedElementTargets.add(state.nonExistentView); + } else { + sharedElementTargets.addAll(namedViews.values()); + } + addTargets(sharedElementTransition, sharedElementTargets); + + // Notify the start of the transition. + SharedElementCallback callback = isBack ? + outFragment.mEnterTransitionCallback : + inFragment.mEnterTransitionCallback; + ArrayList<String> names = new ArrayList<String>(namedViews.keySet()); + ArrayList<View> views = new ArrayList<View>(namedViews.values()); + callback.onSharedElementStart(names, views, null); + } + + ArrayList<View> exitingViews = captureExitingViews(exitTransition, outFragment, + namedViews); + if (exitingViews == null || exitingViews.isEmpty()) { + exitTransition = null; + } + + // Set the epicenter of the exit transition + if (mSharedElementTargetNames != null && namedViews != null) { + View epicenterView = namedViews.get(mSharedElementTargetNames.get(0)); + if (epicenterView != null) { + if (exitTransition != null) { + setEpicenter(exitTransition, epicenterView); + } + if (sharedElementTransition != null) { + setEpicenter(sharedElementTransition, epicenterView); + } + } + } + + Transition transition = mergeTransitions(enterTransition, exitTransition, + sharedElementTransition, inFragment, isBack); + + if (transition != null) { + ArrayList<View> hiddenFragments = new ArrayList<View>(); + ArrayList<View> enteringViews = addTransitionTargets(state, enterTransition, + sharedElementTransition, transition, sceneRoot, inFragment, outFragment, + hiddenFragments, isBack, sharedElementTargets); + + transition.setNameOverrides(state.nameOverrides); + // We want to exclude hidden views later, so we need a non-null list in the + // transition now. + transition.excludeTarget(state.nonExistentView, true); + // Now exclude all currently hidden fragments. + excludeHiddenFragments(hiddenFragments, containerId, transition); + TransitionManager.beginDelayedTransition(sceneRoot, transition); + // Remove the view targeting after the transition starts + removeTargetedViewsFromTransitions(sceneRoot, state.nonExistentView, + enterTransition, enteringViews, exitTransition, exitingViews, + sharedElementTransition, sharedElementTargets, transition, hiddenFragments); + } + } + } + + /** + * After the transition has started, remove all targets that we added to the transitions + * so that the transitions are left in a clean state. + */ + private void removeTargetedViewsFromTransitions( + final ViewGroup sceneRoot, final View nonExistingView, + final Transition enterTransition, final ArrayList<View> enteringViews, + final Transition exitTransition, final ArrayList<View> exitingViews, + final Transition sharedElementTransition, final ArrayList<View> sharedElementTargets, + final Transition overallTransition, final ArrayList<View> hiddenViews) { + if (overallTransition != null) { + sceneRoot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); + if (enterTransition != null) { + enterTransition.removeTarget(nonExistingView); + removeTargets(enterTransition, enteringViews); + } + if (exitTransition != null) { + removeTargets(exitTransition, exitingViews); + } + if (sharedElementTransition != null) { + removeTargets(sharedElementTransition, sharedElementTargets); + } + int numViews = hiddenViews.size(); + for (int i = 0; i < numViews; i++) { + overallTransition.excludeTarget(hiddenViews.get(i), false); + } + overallTransition.excludeTarget(nonExistingView, false); + return true; + } + }); + } + } + + private static void removeTargets(Transition transition, ArrayList<View> views) { + int numViews = views.size(); + for (int i = 0; i < numViews; i++) { + transition.removeTarget(views.get(i)); + } + } + + private static void addTargets(Transition transition, ArrayList<View> views) { + int numViews = views.size(); + for (int i = 0; i < numViews; i++) { + transition.addTarget(views.get(i)); + } + } + + /** + * Remaps a name-to-View map, substituting different names for keys. + * + * @param inMap A list of keys found in the map, in the order in toGoInMap + * @param toGoInMap A list of keys to use for the new map, in the order of inMap + * @param namedViews The current mapping + * @return a new Map after it has been mapped with the new names as keys. + */ + private static ArrayMap<String, View> remapNames(ArrayList<String> inMap, + ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews) { + ArrayMap<String, View> remappedViews = new ArrayMap<String, View>(); + if (!namedViews.isEmpty()) { + int numKeys = inMap.size(); + for (int i = 0; i < numKeys; i++) { + View view = namedViews.get(inMap.get(i)); + + if (view != null) { + remappedViews.put(toGoInMap.get(i), view); + } + } + } + return remappedViews; + } + + /** + * Maps shared elements to views in the entering fragment. + * + * @param state The transition State as returned from {@link #beginTransition( + * android.util.SparseArray, android.util.SparseArray, boolean)}. + * @param inFragment The last fragment to be added. + * @param isBack true if this is popping the back stack or false if this is a + * forward operation. + */ + private ArrayMap<String, View> mapEnteringSharedElements(TransitionState state, + Fragment inFragment, boolean isBack) { + ArrayMap<String, View> namedViews = new ArrayMap<String, View>(); + View root = inFragment.getView(); + if (root != null) { + if (mSharedElementSourceNames != null) { + root.findNamedViews(namedViews); + if (isBack) { + namedViews = remapNames(mSharedElementSourceNames, + mSharedElementTargetNames, namedViews); + } else { + namedViews.retainAll(mSharedElementTargetNames); + } + } + } + return namedViews; + } + + private void excludeHiddenFragments(final ArrayList<View> hiddenFragmentViews, int containerId, + Transition transition) { + if (mManager.mAdded != null) { + for (int i = 0; i < mManager.mAdded.size(); i++) { + Fragment fragment = mManager.mAdded.get(i); + if (fragment.mView != null && fragment.mContainer != null && + fragment.mContainerId == containerId) { + if (fragment.mHidden) { + if (!hiddenFragmentViews.contains(fragment.mView)) { + transition.excludeTarget(fragment.mView, true); + hiddenFragmentViews.add(fragment.mView); + } + } else { + transition.excludeTarget(fragment.mView, false); + hiddenFragmentViews.remove(fragment.mView); + } + } + } + } + } + + private static void setEpicenter(Transition transition, View view) { + final Rect epicenter = new Rect(); + view.getBoundsOnScreen(epicenter); + + transition.setEpicenterCallback(new Transition.EpicenterCallback() { + @Override + public Rect onGetEpicenter(Transition transition) { + return epicenter; + } + }); + } + + private void setSharedElementEpicenter(Transition transition, final TransitionState state) { + transition.setEpicenterCallback(new Transition.EpicenterCallback() { + private Rect mEpicenter; + + @Override + public Rect onGetEpicenter(Transition transition) { + if (mEpicenter == null && state.enteringEpicenterView != null) { + mEpicenter = new Rect(); + state.enteringEpicenterView.getBoundsOnScreen(mEpicenter); + } + return mEpicenter; + } + }); + } + + public TransitionState popFromBackStack(boolean doStateMove, TransitionState state, + SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) { if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "popFromBackStack: " + this); LogWriter logw = new LogWriter(Log.VERBOSE, TAG); @@ -698,6 +1511,14 @@ pw.flush(); } + if (state == null) { + if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) { + state = beginTransition(firstOutFragments, lastInFragments, true); + } + } else if (!doStateMove) { + setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames); + } + bumpBackStackNesting(-1); Op op = mTail; @@ -709,7 +1530,8 @@ mManager.removeFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); - } break; + } + break; case OP_REPLACE: { Fragment f = op.fragment; if (f != null) { @@ -719,42 +1541,48 @@ mTransitionStyle); } if (op.removed != null) { - for (int i=0; i<op.removed.size(); i++) { + for (int i = 0; i < op.removed.size(); i++) { Fragment old = op.removed.get(i); old.mNextAnim = op.popEnterAnim; mManager.addFragment(old, false); } } - } break; + } + break; case OP_REMOVE: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.addFragment(f, false); - } break; + } + break; case OP_HIDE: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.showFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); - } break; + } + break; case OP_SHOW: { Fragment f = op.fragment; f.mNextAnim = op.popExitAnim; mManager.hideFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); - } break; + } + break; case OP_DETACH: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.attachFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); - } break; + } + break; case OP_ATTACH: { Fragment f = op.fragment; f.mNextAnim = op.popExitAnim; mManager.detachFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); - } break; + } + break; default: { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } @@ -766,12 +1594,70 @@ if (doStateMove) { mManager.moveToState(mManager.mCurState, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); + state = null; } if (mIndex >= 0) { mManager.freeBackStackIndex(mIndex); mIndex = -1; } + return state; + } + + private static void setNameOverride(ArrayMap<String, String> overrides, + String source, String target) { + if (source != null && target != null && !source.equals(target)) { + for (int index = 0; index < overrides.size(); index++) { + if (source.equals(overrides.valueAt(index))) { + overrides.setValueAt(index, target); + return; + } + } + overrides.put(source, target); + } + } + + private static void setNameOverrides(TransitionState state, ArrayList<String> sourceNames, + ArrayList<String> targetNames) { + if (sourceNames != null) { + for (int i = 0; i < sourceNames.size(); i++) { + String source = sourceNames.get(i); + String target = targetNames.get(i); + setNameOverride(state.nameOverrides, source, target); + } + } + } + + private void setBackNameOverrides(TransitionState state, ArrayMap<String, View> namedViews, + boolean isEnd) { + int count = mSharedElementTargetNames.size(); + for (int i = 0; i < count; i++) { + String source = mSharedElementSourceNames.get(i); + String originalTarget = mSharedElementTargetNames.get(i); + View view = namedViews.get(originalTarget); + if (view != null) { + String target = view.getTransitionName(); + if (isEnd) { + setNameOverride(state.nameOverrides, source, target); + } else { + setNameOverride(state.nameOverrides, target, source); + } + } + } + } + + private void setNameOverrides(TransitionState state, ArrayMap<String, View> namedViews, + boolean isEnd) { + int count = namedViews.size(); + for (int i = 0; i < count; i++) { + String source = namedViews.keyAt(i); + String target = namedViews.valueAt(i).getTransitionName(); + if (isEnd) { + setNameOverride(state.nameOverrides, source, target); + } else { + setNameOverride(state.nameOverrides, target, source); + } + } } public String getName() { @@ -789,4 +1675,10 @@ public boolean isEmpty() { return mNumOp == 0; } + + public class TransitionState { + public ArrayMap<String, String> nameOverrides = new ArrayMap<String, String>(); + public View enteringEpicenterView; + public View nonExistentView; + } }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index e49fd67..e9340eb 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java
@@ -16,13 +16,21 @@ package android.app; +import android.app.usage.IUsageStatsManager; +import android.app.usage.UsageStatsManager; +import android.appwidget.AppWidgetManager; import android.os.Build; + +import android.service.persistentdata.IPersistentDataBlockService; +import android.service.persistentdata.PersistentDataBlockManager; +import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.policy.PolicyManager; import com.android.internal.util.Preconditions; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.ContextWrapper; @@ -31,11 +39,15 @@ import android.content.IntentFilter; import android.content.IIntentReceiver; import android.content.IntentSender; +import android.content.IRestrictionsManager; import android.content.ReceiverCallNotAllowedException; +import android.content.RestrictionsManager; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; +import android.content.pm.ILauncherApps; import android.content.pm.IPackageManager; +import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetManager; @@ -51,8 +63,8 @@ import android.hardware.ISerialManager; import android.hardware.SerialManager; import android.hardware.SystemSensorManager; -import android.hardware.hdmi.HdmiCecManager; -import android.hardware.hdmi.IHdmiCecService; +import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.IHdmiControlService; import android.hardware.camera2.CameraManager; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; @@ -64,10 +76,17 @@ import android.location.LocationManager; import android.media.AudioManager; import android.media.MediaRouter; +import android.media.projection.MediaProjectionManager; +import android.media.session.MediaSessionManager; +import android.media.tv.ITvInputManager; +import android.media.tv.TvInputManager; import android.net.ConnectivityManager; import android.net.IConnectivityManager; +import android.net.EthernetManager; +import android.net.IEthernetManager; import android.net.INetworkPolicyManager; import android.net.NetworkPolicyManager; +import android.net.NetworkScoreManager; import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; @@ -75,7 +94,12 @@ import android.net.wifi.WifiManager; import android.net.wifi.p2p.IWifiP2pManager; import android.net.wifi.p2p.WifiP2pManager; +import android.net.wifi.IWifiScanner; +import android.net.wifi.WifiScanner; +import android.net.wifi.IRttManager; +import android.net.wifi.RttManager; import android.nfc.NfcManager; +import android.os.BatteryManager; import android.os.Binder; import android.os.Bundle; import android.os.Debug; @@ -98,6 +122,9 @@ import android.os.storage.StorageManager; import android.print.IPrintManager; import android.print.PrintManager; +import android.service.fingerprint.IFingerprintService; +import android.service.fingerprint.FingerprintManager; +import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.content.ClipboardManager; import android.util.AndroidRuntimeException; @@ -115,10 +142,13 @@ import android.accounts.AccountManager; import android.accounts.IAccountManager; import android.app.admin.DevicePolicyManager; +import android.app.job.IJobScheduler; +import android.app.trust.TrustManager; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; import com.android.internal.os.IDropBoxManagerService; +import com.android.internal.telecom.ITelecomService; import java.io.File; import java.io.FileInputStream; @@ -220,7 +250,11 @@ @GuardedBy("mSync") private File mFilesDir; @GuardedBy("mSync") + private File mNoBackupFilesDir; + @GuardedBy("mSync") private File mCacheDir; + @GuardedBy("mSync") + private File mCodeCacheDir; @GuardedBy("mSync") private File[] mExternalObbDirs; @@ -228,6 +262,8 @@ private File[] mExternalFilesDirs; @GuardedBy("mSync") private File[] mExternalCacheDirs; + @GuardedBy("mSync") + private File[] mExternalMediaDirs; private static final String[] EMPTY_FILE_LIST = {}; @@ -359,13 +395,12 @@ return new BluetoothManager(ctx); }}); - registerService(HDMI_CEC_SERVICE, new StaticServiceFetcher() { + registerService(HDMI_CONTROL_SERVICE, new StaticServiceFetcher() { public Object createStaticService() { - IBinder b = ServiceManager.getService(HDMI_CEC_SERVICE); - return new HdmiCecManager(IHdmiCecService.Stub.asInterface(b)); + IBinder b = ServiceManager.getService(HDMI_CONTROL_SERVICE); + return new HdmiControlManager(IHdmiControlService.Stub.asInterface(b)); }}); - registerService(CLIPBOARD_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new ClipboardManager(ctx.getOuterContext(), @@ -375,8 +410,7 @@ registerService(CONNECTIVITY_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE); - return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b), - ctx.getPackageName()); + return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b)); }}); registerService(COUNTRY_DETECTOR, new StaticServiceFetcher() { @@ -395,6 +429,11 @@ return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName()); }}); + registerService(BATTERY_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return new BatteryManager(); + }}); + registerService(NFC_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new NfcManager(ctx); @@ -463,7 +502,8 @@ outerContext.getApplicationInfo().targetSdkVersion, com.android.internal.R.style.Theme_Dialog, com.android.internal.R.style.Theme_Holo_Dialog, - com.android.internal.R.style.Theme_DeviceDefault_Dialog)), + com.android.internal.R.style.Theme_DeviceDefault_Dialog, + com.android.internal.R.style.Theme_DeviceDefault_Light_Dialog)), ctx.mMainThread.getHandler()); }}); @@ -482,6 +522,9 @@ public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(POWER_SERVICE); IPowerManager service = IPowerManager.Stub.asInterface(b); + if (service == null) { + Log.wtf(TAG, "Failed to get power manager service."); + } return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler()); }}); @@ -519,6 +562,11 @@ return new TelephonyManager(ctx.getOuterContext()); }}); + registerService(TELECOM_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return new TelecomManager(ctx.getOuterContext()); + }}); + registerService(UI_MODE_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new UiModeManager(); @@ -557,6 +605,27 @@ return new WifiP2pManager(service); }}); + registerService(WIFI_SCANNING_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(WIFI_SCANNING_SERVICE); + IWifiScanner service = IWifiScanner.Stub.asInterface(b); + return new WifiScanner(ctx.getOuterContext(), service); + }}); + + registerService(WIFI_RTT_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(WIFI_RTT_SERVICE); + IRttManager service = IRttManager.Stub.asInterface(b); + return new RttManager(ctx.getOuterContext(), service); + }}); + + registerService(ETHERNET_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(ETHERNET_SERVICE); + IEthernetManager service = IEthernetManager.Stub.asInterface(b); + return new EthernetManager(ctx.getOuterContext(), service); + }}); + registerService(WINDOW_SERVICE, new ServiceFetcher() { Display mDefaultDisplay; public Object getService(ContextImpl ctx) { @@ -592,6 +661,21 @@ } }); + registerService(LAUNCHER_APPS_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(LAUNCHER_APPS_SERVICE); + ILauncherApps service = ILauncherApps.Stub.asInterface(b); + return new LauncherApps(ctx, service); + } + }); + + registerService(RESTRICTIONS_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(RESTRICTIONS_SERVICE); + IRestrictionsManager service = IRestrictionsManager.Stub.asInterface(b); + return new RestrictionsManager(ctx, service); + } + }); registerService(PRINT_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE); @@ -604,6 +688,81 @@ public Object createService(ContextImpl ctx) { return new ConsumerIrManager(ctx); }}); + + registerService(MEDIA_SESSION_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return new MediaSessionManager(ctx); + } + }); + + registerService(TRUST_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(TRUST_SERVICE); + return new TrustManager(b); + } + }); + + registerService(FINGERPRINT_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder binder = ServiceManager.getService(FINGERPRINT_SERVICE); + IFingerprintService service = IFingerprintService.Stub.asInterface(binder); + return new FingerprintManager(ctx.getOuterContext(), service); + } + }); + + registerService(TV_INPUT_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder iBinder = ServiceManager.getService(TV_INPUT_SERVICE); + ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder); + return new TvInputManager(service, UserHandle.myUserId()); + } + }); + + registerService(NETWORK_SCORE_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return new NetworkScoreManager(ctx); + } + }); + + registerService(USAGE_STATS_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder iBinder = ServiceManager.getService(USAGE_STATS_SERVICE); + IUsageStatsManager service = IUsageStatsManager.Stub.asInterface(iBinder); + return new UsageStatsManager(ctx.getOuterContext(), service); + } + }); + + registerService(JOB_SCHEDULER_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(JOB_SCHEDULER_SERVICE); + return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b)); + }}); + + registerService(PERSISTENT_DATA_BLOCK_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(PERSISTENT_DATA_BLOCK_SERVICE); + IPersistentDataBlockService persistentDataBlockService = + IPersistentDataBlockService.Stub.asInterface(b); + if (persistentDataBlockService != null) { + return new PersistentDataBlockManager(persistentDataBlockService); + } else { + // not supported + return null; + } + } + }); + + registerService(MEDIA_PROJECTION_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return new MediaProjectionManager(ctx); + } + }); + + registerService(APPWIDGET_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(APPWIDGET_SERVICE); + return new AppWidgetManager(ctx, IAppWidgetService.Stub.asInterface(b)); + }}); } static ContextImpl getImpl(Context context) { @@ -826,27 +985,42 @@ return f.delete(); } + // Common-path handling of app data dir creation + private static File createFilesDirLocked(File file) { + if (!file.exists()) { + if (!file.mkdirs()) { + if (file.exists()) { + // spurious failure; probably racing with another process for this app + return file; + } + Log.w(TAG, "Unable to create files subdir " + file.getPath()); + return null; + } + FileUtils.setPermissions( + file.getPath(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, + -1, -1); + } + return file; + } + @Override public File getFilesDir() { synchronized (mSync) { if (mFilesDir == null) { mFilesDir = new File(getDataDirFile(), "files"); } - if (!mFilesDir.exists()) { - if(!mFilesDir.mkdirs()) { - if (mFilesDir.exists()) { - // spurious failure; probably racing with another process for this app - return mFilesDir; - } - Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath()); - return null; - } - FileUtils.setPermissions( - mFilesDir.getPath(), - FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, - -1, -1); + return createFilesDirLocked(mFilesDir); + } + } + + @Override + public File getNoBackupFilesDir() { + synchronized (mSync) { + if (mNoBackupFilesDir == null) { + mNoBackupFilesDir = new File(getDataDirFile(), "no_backup"); } - return mFilesDir; + return createFilesDirLocked(mNoBackupFilesDir); } } @@ -898,22 +1072,18 @@ if (mCacheDir == null) { mCacheDir = new File(getDataDirFile(), "cache"); } - if (!mCacheDir.exists()) { - if(!mCacheDir.mkdirs()) { - if (mCacheDir.exists()) { - // spurious failure; probably racing with another process for this app - return mCacheDir; - } - Log.w(TAG, "Unable to create cache directory " + mCacheDir.getAbsolutePath()); - return null; - } - FileUtils.setPermissions( - mCacheDir.getPath(), - FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, - -1, -1); - } + return createFilesDirLocked(mCacheDir); } - return mCacheDir; + } + + @Override + public File getCodeCacheDir() { + synchronized (mSync) { + if (mCodeCacheDir == null) { + mCodeCacheDir = new File(getDataDirFile(), "code_cache"); + } + return createFilesDirLocked(mCodeCacheDir); + } } @Override @@ -935,6 +1105,18 @@ } @Override + public File[] getExternalMediaDirs() { + synchronized (mSync) { + if (mExternalMediaDirs == null) { + mExternalMediaDirs = Environment.buildExternalStorageAppMediaDirs(getPackageName()); + } + + // Create dirs if needed + return ensureDirsExistOrFilter(mExternalMediaDirs); + } + } + + @Override public File getFileStreamPath(String name) { return makeFilename(getFilesDir(), name); } @@ -1065,7 +1247,7 @@ ActivityManagerNative.getDefault().startActivityAsUser( mMainThread.getApplicationThread(), getBasePackageName(), intent, intent.resolveTypeIfNeeded(getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, options, + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options, user.getIdentifier()); } catch (RemoteException re) { } @@ -1265,6 +1447,15 @@ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + sendOrderedBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE, + resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + + @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, BroadcastReceiver resultReceiver, + Handler scheduler, + int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { @@ -1288,7 +1479,7 @@ ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermission, - AppOpsManager.OP_NONE, true, false, user.getIdentifier()); + appOp, true, false, user.getIdentifier()); } catch (RemoteException e) { } } @@ -1480,13 +1671,13 @@ private void validateServiceIntent(Intent service) { if (service.getComponent() == null && service.getPackage() == null) { - if (true || getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.KITKAT) { + if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) { + IllegalArgumentException ex = new IllegalArgumentException( + "Service Intent must be explicit: " + service); + throw ex; + } else { Log.w(TAG, "Implicit intents with startService are not safe: " + service + " " + Debug.getCallers(2, 3)); - //IllegalArgumentException ex = new IllegalArgumentException( - // "Service Intent must be explicit: " + service); - //Log.e(TAG, "This will become an error", ex); - //throw ex; } } } @@ -1740,8 +1931,8 @@ public void grantUriPermission(String toPackage, Uri uri, int modeFlags) { try { ActivityManagerNative.getDefault().grantUriPermission( - mMainThread.getApplicationThread(), toPackage, uri, - modeFlags); + mMainThread.getApplicationThread(), toPackage, + ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); } catch (RemoteException e) { } } @@ -1750,8 +1941,8 @@ public void revokeUriPermission(Uri uri, int modeFlags) { try { ActivityManagerNative.getDefault().revokeUriPermission( - mMainThread.getApplicationThread(), uri, - modeFlags); + mMainThread.getApplicationThread(), + ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); } catch (RemoteException e) { } } @@ -1760,12 +1951,17 @@ public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { try { return ActivityManagerNative.getDefault().checkUriPermission( - uri, pid, uid, modeFlags); + ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags, + resolveUserId(uri)); } catch (RemoteException e) { return PackageManager.PERMISSION_DENIED; } } + private int resolveUserId(Uri uri) { + return ContentProvider.getUserIdFromUri(uri, getUserId()); + } + @Override public int checkCallingUriPermission(Uri uri, int modeFlags) { int pid = Binder.getCallingPid(); @@ -1809,17 +2005,26 @@ } private String uriModeFlagToString(int uriModeFlags) { - switch (uriModeFlags) { - case Intent.FLAG_GRANT_READ_URI_PERMISSION | - Intent.FLAG_GRANT_WRITE_URI_PERMISSION: - return "read and write"; - case Intent.FLAG_GRANT_READ_URI_PERMISSION: - return "read"; - case Intent.FLAG_GRANT_WRITE_URI_PERMISSION: - return "write"; + StringBuilder builder = new StringBuilder(); + if ((uriModeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { + builder.append("read and "); } - throw new IllegalArgumentException( - "Unknown permission mode flags: " + uriModeFlags); + if ((uriModeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { + builder.append("write and "); + } + if ((uriModeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) { + builder.append("persistable and "); + } + if ((uriModeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) { + builder.append("prefix and "); + } + + if (builder.length() > 5) { + builder.setLength(builder.length() - 5); + return builder.toString(); + } else { + throw new IllegalArgumentException("Unknown permission mode flags: " + uriModeFlags); + } } private void enforceForUri( @@ -1887,6 +2092,25 @@ } @Override + public Context createApplicationContext(ApplicationInfo application, int flags) + throws NameNotFoundException { + LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(), + flags | CONTEXT_REGISTER_PACKAGE); + if (pi != null) { + final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; + ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken, + new UserHandle(UserHandle.getUserId(application.uid)), restricted, + mDisplay, mOverrideConfiguration); + if (c.mResources != null) { + return c; + } + } + + throw new PackageManager.NameNotFoundException( + "Application package " + application.packageName + " not found"); + } + + @Override public Context createPackageContext(String packageName, int flags) throws NameNotFoundException { return createPackageContextAsUser(packageName, flags, @@ -1903,7 +2127,7 @@ } LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), - flags, user.getIdentifier()); + flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken, user, restricted, mDisplay, mOverrideConfiguration); @@ -2013,7 +2237,6 @@ mUser = user; mPackageInfo = packageInfo; - mContentResolver = new ApplicationContentResolver(this, mainThread, user); mResourcesManager = ResourcesManager.getInstance(); mDisplay = display; mOverrideConfiguration = overrideConfiguration; @@ -2036,8 +2259,9 @@ || overrideConfiguration != null || (compatInfo != null && compatInfo.applicationScale != resources.getCompatibilityInfo().applicationScale)) { - resources = mResourcesManager.getTopLevelResources( - packageInfo.getResDir(), packageInfo.getOverlayDirs(), displayId, + resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(), + packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(), + packageInfo.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfiguration, compatInfo, activityToken); } } @@ -2059,10 +2283,12 @@ mOpPackageName = mBasePackageName; } } + + mContentResolver = new ApplicationContentResolver(this, mainThread, user); } - void installSystemApplicationInfo(ApplicationInfo info) { - mPackageInfo.installSystemApplicationInfo(info); + void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { + mPackageInfo.installSystemApplicationInfo(info, classLoader); } final void scheduleFinalCleanup(String who, String what) { @@ -2192,12 +2418,16 @@ @Override protected IContentProvider acquireProvider(Context context, String auth) { - return mMainThread.acquireProvider(context, auth, mUser.getIdentifier(), true); + return mMainThread.acquireProvider(context, + ContentProvider.getAuthorityWithoutUserId(auth), + resolveUserIdFromAuthority(auth), true); } @Override protected IContentProvider acquireExistingProvider(Context context, String auth) { - return mMainThread.acquireExistingProvider(context, auth, mUser.getIdentifier(), true); + return mMainThread.acquireExistingProvider(context, + ContentProvider.getAuthorityWithoutUserId(auth), + resolveUserIdFromAuthority(auth), true); } @Override @@ -2207,7 +2437,9 @@ @Override protected IContentProvider acquireUnstableProvider(Context c, String auth) { - return mMainThread.acquireProvider(c, auth, mUser.getIdentifier(), false); + return mMainThread.acquireProvider(c, + ContentProvider.getAuthorityWithoutUserId(auth), + resolveUserIdFromAuthority(auth), false); } @Override @@ -2224,5 +2456,10 @@ public void appNotRespondingViaProvider(IContentProvider icp) { mMainThread.appNotRespondingViaProvider(icp.asBinder()); } + + /** @hide */ + protected int resolveUserIdFromAuthority(String auth) { + return ContentProvider.getUserIdFromAuthority(auth, mUser.getIdentifier()); + } } }
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java index d168800..f79d32b 100644 --- a/core/java/android/app/DatePickerDialog.java +++ b/core/java/android/app/DatePickerDialog.java
@@ -21,10 +21,13 @@ import android.content.DialogInterface.OnClickListener; import android.os.Bundle; import android.text.format.DateUtils; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; +import android.widget.Button; import android.widget.DatePicker; import android.widget.DatePicker.OnDateChangedListener; +import android.widget.DatePicker.ValidationCallback; import com.android.internal.R; @@ -44,7 +47,7 @@ private static final String DAY = "day"; private final DatePicker mDatePicker; - private final OnDateSetListener mCallBack; + private final OnDateSetListener mDateSetListener; private final Calendar mCalendar; private boolean mTitleNeedsUpdate = true; @@ -79,49 +82,65 @@ this(context, 0, callBack, year, monthOfYear, dayOfMonth); } + static int resolveDialogTheme(Context context, int resid) { + if (resid == 0) { + final TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(R.attr.datePickerDialogTheme, outValue, true); + return outValue.resourceId; + } else { + return resid; + } + } + /** * @param context The context the dialog is to run in. * @param theme the theme to apply to this dialog - * @param callBack How the parent is notified that the date is set. + * @param listener How the parent is notified that the date is set. * @param year The initial year of the dialog. * @param monthOfYear The initial month of the dialog. * @param dayOfMonth The initial day of the dialog. */ - public DatePickerDialog(Context context, - int theme, - OnDateSetListener callBack, - int year, - int monthOfYear, - int dayOfMonth) { - super(context, theme); + public DatePickerDialog(Context context, int theme, OnDateSetListener listener, int year, + int monthOfYear, int dayOfMonth) { + super(context, resolveDialogTheme(context, theme)); - mCallBack = callBack; - + mDateSetListener = listener; mCalendar = Calendar.getInstance(); - Context themeContext = getContext(); - setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_done), this); - setIcon(0); - - LayoutInflater inflater = - (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = inflater.inflate(R.layout.date_picker_dialog, null); + final Context themeContext = getContext(); + final LayoutInflater inflater = LayoutInflater.from(themeContext); + final View view = inflater.inflate(R.layout.date_picker_dialog, null); setView(view); + setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this); + setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this); + setButtonPanelLayoutHint(LAYOUT_HINT_SIDE); + mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); mDatePicker.init(year, monthOfYear, dayOfMonth, this); - updateTitle(year, monthOfYear, dayOfMonth); + mDatePicker.setValidationCallback(mValidationCallback); } - public void onClick(DialogInterface dialog, int which) { - tryNotifyDateSet(); - } - - public void onDateChanged(DatePicker view, int year, - int month, int day) { + @Override + public void onDateChanged(DatePicker view, int year, int month, int day) { mDatePicker.init(year, month, day, this); updateTitle(year, month, day); } + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case BUTTON_POSITIVE: + if (mDateSetListener != null) { + mDateSetListener.onDateSet(mDatePicker, mDatePicker.getYear(), + mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); + } + break; + case BUTTON_NEGATIVE: + cancel(); + break; + } + } + /** * Gets the {@link DatePicker} contained in this dialog. * @@ -142,20 +161,6 @@ mDatePicker.updateDate(year, monthOfYear, dayOfMonth); } - private void tryNotifyDateSet() { - if (mCallBack != null) { - mDatePicker.clearFocus(); - mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(), - mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); - } - } - - @Override - protected void onStop() { - tryNotifyDateSet(); - super.onStop(); - } - private void updateTitle(int year, int month, int day) { if (!mDatePicker.getCalendarViewShown()) { mCalendar.set(Calendar.YEAR, year); @@ -180,7 +185,7 @@ @Override public Bundle onSaveInstanceState() { - Bundle state = super.onSaveInstanceState(); + final Bundle state = super.onSaveInstanceState(); state.putInt(YEAR, mDatePicker.getYear()); state.putInt(MONTH, mDatePicker.getMonth()); state.putInt(DAY, mDatePicker.getDayOfMonth()); @@ -190,9 +195,19 @@ @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); - int year = savedInstanceState.getInt(YEAR); - int month = savedInstanceState.getInt(MONTH); - int day = savedInstanceState.getInt(DAY); + final int year = savedInstanceState.getInt(YEAR); + final int month = savedInstanceState.getInt(MONTH); + final int day = savedInstanceState.getInt(DAY); mDatePicker.init(year, month, day, this); } + + private final ValidationCallback mValidationCallback = new ValidationCallback() { + @Override + public void onValidationChanged(boolean valid) { + final Button positive = getButton(BUTTON_POSITIVE); + if (positive != null) { + positive.setEnabled(valid); + } + } + }; }
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 7a362df..12d4513 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java
@@ -17,8 +17,7 @@ package android.app; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import com.android.internal.app.ActionBarImpl; +import com.android.internal.app.WindowDecorActionBar; import com.android.internal.policy.PolicyManager; import android.content.ComponentName; @@ -88,7 +87,7 @@ final WindowManager mWindowManager; Window mWindow; View mDecor; - private ActionBarImpl mActionBar; + private ActionBar mActionBar; /** * This field should be made private, so it is hidden from the SDK. * {@hide} @@ -241,6 +240,18 @@ } /** + * Forces immediate creation of the dialog. + * <p> + * Note that you should not override this method to perform dialog creation. + * Rather, override {@link #onCreate(Bundle)}. + */ + public void create() { + if (!mCreated) { + dispatchOnCreate(null); + } + } + + /** * Start the dialog and display it on screen. The window is placed in the * application layer and opaque. Note that you should not override this * method to do initialization when the dialog is shown, instead implement @@ -270,7 +281,7 @@ final ApplicationInfo info = mContext.getApplicationInfo(); mWindow.setDefaultIcon(info.icon); mWindow.setDefaultLogo(info.logo); - mActionBar = new ActionBarImpl(this); + mActionBar = new WindowDecorActionBar(this); } WindowManager.LayoutParams l = mWindow.getAttributes(); @@ -458,11 +469,12 @@ } /** - * Finds a view that was identified by the id attribute from the XML that - * was processed in {@link #onStart}. + * Finds a child view with the given identifier. Returns null if the + * specified child view does not exist or the dialog has not yet been fully + * created (for example, via {@link #show()} or {@link #create()}). * * @param id the identifier of the view to find - * @return The view if found or null otherwise. + * @return The view with the given id or null. */ public View findViewById(int id) { return mWindow.findViewById(id); @@ -481,7 +493,7 @@ /** * Set the screen content to an explicit view. This view is placed * directly into the screen's view hierarchy. It can itself be a complex - * view hierarhcy. + * view hierarchy. * * @param view The desired content to display. */
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java new file mode 100644 index 0000000..add67f2 --- /dev/null +++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -0,0 +1,663 @@ +/* + * Copyright (C) 2014 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; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.graphics.Matrix; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.ResultReceiver; +import android.text.TextUtils; +import android.transition.Transition; +import android.transition.TransitionManager; +import android.util.ArrayMap; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroupOverlay; +import android.view.ViewTreeObserver; +import android.view.Window; + +import java.util.ArrayList; + +/** + * This ActivityTransitionCoordinator is created by the Activity to manage + * the enter scene and shared element transfer into the Scene, either during + * launch of an Activity or returning from a launched Activity. + */ +class EnterTransitionCoordinator extends ActivityTransitionCoordinator { + private static final String TAG = "EnterTransitionCoordinator"; + + private static final int MIN_ANIMATION_FRAMES = 2; + + private boolean mSharedElementTransitionStarted; + private Activity mActivity; + private boolean mHasStopped; + private boolean mIsCanceled; + private ObjectAnimator mBackgroundAnimator; + private boolean mIsExitTransitionComplete; + private boolean mIsReadyForTransition; + private Bundle mSharedElementsBundle; + private boolean mWasOpaque; + private boolean mAreViewsReady; + private boolean mIsViewsTransitionStarted; + private boolean mIsViewsTransitionComplete; + private boolean mIsSharedElementTransitionComplete; + private ArrayList<Matrix> mSharedElementParentMatrices; + private Transition mEnterViewsTransition; + + public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver, + ArrayList<String> sharedElementNames, boolean isReturning) { + super(activity.getWindow(), sharedElementNames, + getListener(activity, isReturning), isReturning); + mActivity = activity; + setResultReceiver(resultReceiver); + prepareEnter(); + Bundle resultReceiverBundle = new Bundle(); + resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this); + mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle); + final View decorView = getDecor(); + if (decorView != null) { + decorView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + if (mIsReadyForTransition) { + decorView.getViewTreeObserver().removeOnPreDrawListener(this); + } + return mIsReadyForTransition; + } + }); + } + } + + public void viewInstancesReady(ArrayList<String> accepted, ArrayList<String> localNames, + ArrayList<View> localViews) { + boolean remap = false; + for (int i = 0; i < localViews.size(); i++) { + View view = localViews.get(i); + if (!TextUtils.equals(view.getTransitionName(), localNames.get(i)) + || !view.isAttachedToWindow()) { + remap = true; + break; + } + } + if (remap) { + triggerViewsReady(mapNamedElements(accepted, localNames)); + } else { + triggerViewsReady(mapSharedElements(accepted, localViews)); + } + } + + public void namedViewsReady(ArrayList<String> accepted, ArrayList<String> localNames) { + triggerViewsReady(mapNamedElements(accepted, localNames)); + } + + public Transition getEnterViewsTransition() { + return mEnterViewsTransition; + } + + @Override + protected void viewsReady(ArrayMap<String, View> sharedElements) { + super.viewsReady(sharedElements); + mIsReadyForTransition = true; + hideViews(mSharedElements); + if (getViewsTransition() != null && mTransitioningViews != null) { + hideViews(mTransitioningViews); + } + if (mIsReturning) { + sendSharedElementDestination(); + } else { + setSharedElementMatrices(); + moveSharedElementsToOverlay(); + } + if (mSharedElementsBundle != null) { + onTakeSharedElements(); + } + } + + private void triggerViewsReady(final ArrayMap<String, View> sharedElements) { + if (mAreViewsReady) { + return; + } + mAreViewsReady = true; + // Ensure the views have been laid out before capturing the views -- we need the epicenter. + if (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()) { + viewsReady(sharedElements); + } else { + final View sharedElement = sharedElements.valueAt(0); + sharedElement.getViewTreeObserver() + .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + sharedElement.getViewTreeObserver().removeOnPreDrawListener(this); + viewsReady(sharedElements); + return true; + } + }); + } + } + + private ArrayMap<String, View> mapNamedElements(ArrayList<String> accepted, + ArrayList<String> localNames) { + ArrayMap<String, View> sharedElements = new ArrayMap<String, View>(); + ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.findNamedViews(sharedElements); + } + if (accepted != null) { + for (int i = 0; i < localNames.size(); i++) { + String localName = localNames.get(i); + String acceptedName = accepted.get(i); + if (localName != null && !localName.equals(acceptedName)) { + View view = sharedElements.remove(localName); + if (view != null) { + sharedElements.put(acceptedName, view); + } + } + } + } + return sharedElements; + } + + private void sendSharedElementDestination() { + boolean allReady; + final View decorView = getDecor(); + if (allowOverlappingTransitions() && getEnterViewsTransition() != null) { + allReady = false; + } else if (decorView == null) { + allReady = true; + } else { + allReady = !decorView.isLayoutRequested(); + if (allReady) { + for (int i = 0; i < mSharedElements.size(); i++) { + if (mSharedElements.get(i).isLayoutRequested()) { + allReady = false; + break; + } + } + } + } + if (allReady) { + Bundle state = captureSharedElementState(); + setSharedElementMatrices(); + moveSharedElementsToOverlay(); + mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state); + } else if (decorView != null) { + decorView.getViewTreeObserver() + .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + decorView.getViewTreeObserver().removeOnPreDrawListener(this); + if (mResultReceiver != null) { + Bundle state = captureSharedElementState(); + setSharedElementMatrices(); + moveSharedElementsToOverlay(); + mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state); + } + return true; + } + }); + } + if (allowOverlappingTransitions()) { + startEnterTransitionOnly(); + } + } + + private static SharedElementCallback getListener(Activity activity, boolean isReturning) { + return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener; + } + + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + switch (resultCode) { + case MSG_TAKE_SHARED_ELEMENTS: + if (!mIsCanceled) { + mSharedElementsBundle = resultData; + onTakeSharedElements(); + } + break; + case MSG_EXIT_TRANSITION_COMPLETE: + if (!mIsCanceled) { + mIsExitTransitionComplete = true; + if (mSharedElementTransitionStarted) { + onRemoteExitTransitionComplete(); + } + } + break; + case MSG_CANCEL: + cancel(); + break; + } + } + + private void cancel() { + if (!mIsCanceled) { + mIsCanceled = true; + if (getViewsTransition() == null || mIsViewsTransitionStarted) { + showViews(mSharedElements, true); + } else if (mTransitioningViews != null) { + mTransitioningViews.addAll(mSharedElements); + } + mSharedElementNames.clear(); + mSharedElements.clear(); + mAllSharedElementNames.clear(); + startSharedElementTransition(null); + onRemoteExitTransitionComplete(); + } + } + + public boolean isReturning() { + return mIsReturning; + } + + protected void prepareEnter() { + ViewGroup decorView = getDecor(); + if (mActivity == null || decorView == null) { + return; + } + mActivity.overridePendingTransition(0, 0); + if (!mIsReturning) { + mWasOpaque = mActivity.convertToTranslucent(null, null); + Drawable background = decorView.getBackground(); + if (background != null) { + getWindow().setBackgroundDrawable(null); + background = background.mutate(); + background.setAlpha(0); + getWindow().setBackgroundDrawable(background); + } + } else { + mActivity = null; // all done with it now. + } + } + + @Override + protected Transition getViewsTransition() { + Window window = getWindow(); + if (window == null) { + return null; + } + if (mIsReturning) { + return window.getReenterTransition(); + } else { + return window.getEnterTransition(); + } + } + + protected Transition getSharedElementTransition() { + Window window = getWindow(); + if (window == null) { + return null; + } + if (mIsReturning) { + return window.getSharedElementReenterTransition(); + } else { + return window.getSharedElementEnterTransition(); + } + } + + private void startSharedElementTransition(Bundle sharedElementState) { + ViewGroup decorView = getDecor(); + if (decorView == null) { + return; + } + // Remove rejected shared elements + ArrayList<String> rejectedNames = new ArrayList<String>(mAllSharedElementNames); + rejectedNames.removeAll(mSharedElementNames); + ArrayList<View> rejectedSnapshots = createSnapshots(sharedElementState, rejectedNames); + if (mListener != null) { + mListener.onRejectSharedElements(rejectedSnapshots); + } + startRejectedAnimations(rejectedSnapshots); + + // Now start shared element transition + ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState, + mSharedElementNames); + showViews(mSharedElements, true); + scheduleSetSharedElementEnd(sharedElementSnapshots); + ArrayList<SharedElementOriginalState> originalImageViewState = + setSharedElementState(sharedElementState, sharedElementSnapshots); + requestLayoutForSharedElements(); + + boolean startEnterTransition = allowOverlappingTransitions() && !mIsReturning; + boolean startSharedElementTransition = true; + setGhostVisibility(View.INVISIBLE); + scheduleGhostVisibilityChange(View.INVISIBLE); + Transition transition = beginTransition(decorView, startEnterTransition, + startSharedElementTransition); + scheduleGhostVisibilityChange(View.VISIBLE); + setGhostVisibility(View.VISIBLE); + + if (startEnterTransition) { + startEnterTransition(transition); + } + + setOriginalSharedElementState(mSharedElements, originalImageViewState); + + if (mResultReceiver != null) { + // We can't trust that the view will disappear on the same frame that the shared + // element appears here. Assure that we get at least 2 frames for double-buffering. + decorView.postOnAnimation(new Runnable() { + int mAnimations; + + @Override + public void run() { + if (mAnimations++ < MIN_ANIMATION_FRAMES) { + View decorView = getDecor(); + if (decorView != null) { + decorView.postOnAnimation(this); + } + } else if (mResultReceiver != null) { + mResultReceiver.send(MSG_HIDE_SHARED_ELEMENTS, null); + mResultReceiver = null; // all done sending messages. + } + } + }); + } + } + + private void onTakeSharedElements() { + if (!mIsReadyForTransition || mSharedElementsBundle == null) { + return; + } + final Bundle sharedElementState = mSharedElementsBundle; + mSharedElementsBundle = null; + final View decorView = getDecor(); + if (decorView != null) { + decorView.getViewTreeObserver() + .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + decorView.getViewTreeObserver().removeOnPreDrawListener(this); + startTransition(new Runnable() { + @Override + public void run() { + startSharedElementTransition(sharedElementState); + } + }); + return false; + } + }); + decorView.invalidate(); + } + } + + private void requestLayoutForSharedElements() { + int numSharedElements = mSharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + mSharedElements.get(i).requestLayout(); + } + } + + private Transition beginTransition(ViewGroup decorView, boolean startEnterTransition, + boolean startSharedElementTransition) { + Transition sharedElementTransition = null; + if (startSharedElementTransition) { + if (!mSharedElementNames.isEmpty()) { + sharedElementTransition = configureTransition(getSharedElementTransition(), false); + } + if (sharedElementTransition == null) { + sharedElementTransitionStarted(); + sharedElementTransitionComplete(); + } else { + sharedElementTransition.addListener(new Transition.TransitionListenerAdapter() { + @Override + public void onTransitionStart(Transition transition) { + sharedElementTransitionStarted(); + } + + @Override + public void onTransitionEnd(Transition transition) { + transition.removeListener(this); + sharedElementTransitionComplete(); + } + }); + } + } + Transition viewsTransition = null; + if (startEnterTransition) { + mIsViewsTransitionStarted = true; + if (mTransitioningViews != null && !mTransitioningViews.isEmpty()) { + viewsTransition = configureTransition(getViewsTransition(), true); + if (viewsTransition != null && !mIsReturning) { + stripOffscreenViews(); + } + } + if (viewsTransition == null) { + viewTransitionComplete(); + } else { + viewsTransition.forceVisibility(View.INVISIBLE, true); + final ArrayList<View> transitioningViews = mTransitioningViews; + viewsTransition.addListener(new ContinueTransitionListener() { + @Override + public void onTransitionStart(Transition transition) { + mEnterViewsTransition = transition; + if (transitioningViews != null) { + showViews(transitioningViews, false); + } + super.onTransitionStart(transition); + } + + @Override + public void onTransitionEnd(Transition transition) { + mEnterViewsTransition = null; + transition.removeListener(this); + viewTransitionComplete(); + super.onTransitionEnd(transition); + } + }); + } + } + + Transition transition = mergeTransitions(sharedElementTransition, viewsTransition); + if (transition != null) { + transition.addListener(new ContinueTransitionListener()); + TransitionManager.beginDelayedTransition(decorView, transition); + if (startSharedElementTransition && !mSharedElementNames.isEmpty()) { + mSharedElements.get(0).invalidate(); + } else if (startEnterTransition && mTransitioningViews != null && + !mTransitioningViews.isEmpty()) { + mTransitioningViews.get(0).invalidate(); + } + } else { + transitionStarted(); + } + return transition; + } + + private void viewTransitionComplete() { + mIsViewsTransitionComplete = true; + if (mIsSharedElementTransitionComplete) { + moveSharedElementsFromOverlay(); + } + } + + private void sharedElementTransitionComplete() { + mIsSharedElementTransitionComplete = true; + if (mIsViewsTransitionComplete) { + moveSharedElementsFromOverlay(); + } + } + + private void sharedElementTransitionStarted() { + mSharedElementTransitionStarted = true; + if (mIsExitTransitionComplete) { + send(MSG_EXIT_TRANSITION_COMPLETE, null); + } + } + + private void startEnterTransition(Transition transition) { + ViewGroup decorView = getDecor(); + if (!mIsReturning && decorView != null) { + Drawable background = decorView.getBackground(); + if (background != null) { + background = background.mutate(); + getWindow().setBackgroundDrawable(background); + mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 255); + mBackgroundAnimator.setDuration(getFadeDuration()); + mBackgroundAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + makeOpaque(); + } + }); + mBackgroundAnimator.start(); + } else if (transition != null) { + transition.addListener(new Transition.TransitionListenerAdapter() { + @Override + public void onTransitionEnd(Transition transition) { + transition.removeListener(this); + makeOpaque(); + } + }); + } else { + makeOpaque(); + } + } + } + + public void stop() { + // Restore the background to its previous state since the + // Activity is stopping. + if (mBackgroundAnimator != null) { + mBackgroundAnimator.end(); + mBackgroundAnimator = null; + } else if (mWasOpaque) { + ViewGroup decorView = getDecor(); + if (decorView != null) { + Drawable drawable = decorView.getBackground(); + if (drawable != null) { + drawable.setAlpha(1); + } + } + } + makeOpaque(); + mIsCanceled = true; + mResultReceiver = null; + mActivity = null; + moveSharedElementsFromOverlay(); + if (mTransitioningViews != null) { + showViews(mTransitioningViews, true); + } + showViews(mSharedElements, true); + clearState(); + } + + public void cancelEnter() { + setGhostVisibility(View.INVISIBLE); + mHasStopped = true; + mIsCanceled = true; + mResultReceiver = null; + if (mBackgroundAnimator != null) { + mBackgroundAnimator.cancel(); + mBackgroundAnimator = null; + } + mActivity = null; + clearState(); + } + + private void makeOpaque() { + if (!mHasStopped && mActivity != null) { + if (mWasOpaque) { + mActivity.convertFromTranslucent(); + } + mActivity = null; + } + } + + private boolean allowOverlappingTransitions() { + return mIsReturning ? getWindow().getAllowExitTransitionOverlap() + : getWindow().getAllowEnterTransitionOverlap(); + } + + private void startRejectedAnimations(final ArrayList<View> rejectedSnapshots) { + if (rejectedSnapshots == null || rejectedSnapshots.isEmpty()) { + return; + } + final ViewGroup decorView = getDecor(); + if (decorView != null) { + ViewGroupOverlay overlay = decorView.getOverlay(); + ObjectAnimator animator = null; + int numRejected = rejectedSnapshots.size(); + for (int i = 0; i < numRejected; i++) { + View snapshot = rejectedSnapshots.get(i); + overlay.add(snapshot); + animator = ObjectAnimator.ofFloat(snapshot, View.ALPHA, 1, 0); + animator.start(); + } + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + ViewGroupOverlay overlay = decorView.getOverlay(); + int numRejected = rejectedSnapshots.size(); + for (int i = 0; i < numRejected; i++) { + overlay.remove(rejectedSnapshots.get(i)); + } + } + }); + } + } + + protected void onRemoteExitTransitionComplete() { + if (!allowOverlappingTransitions()) { + startEnterTransitionOnly(); + } + } + + private void startEnterTransitionOnly() { + startTransition(new Runnable() { + @Override + public void run() { + boolean startEnterTransition = true; + boolean startSharedElementTransition = false; + ViewGroup decorView = getDecor(); + if (decorView != null) { + Transition transition = beginTransition(decorView, startEnterTransition, + startSharedElementTransition); + startEnterTransition(transition); + } + } + }); + } + + private void setSharedElementMatrices() { + int numSharedElements = mSharedElements.size(); + if (numSharedElements > 0) { + mSharedElementParentMatrices = new ArrayList<Matrix>(numSharedElements); + } + for (int i = 0; i < numSharedElements; i++) { + View view = mSharedElements.get(i); + + // Find the location in the view's parent + ViewGroup parent = (ViewGroup) view.getParent(); + Matrix matrix = new Matrix(); + parent.transformMatrixToLocal(matrix); + + mSharedElementParentMatrices.add(matrix); + } + } + + @Override + protected void getSharedElementParentMatrix(View view, Matrix matrix) { + int index = mSharedElementParentMatrices == null ? -1 : mSharedElements.indexOf(view); + if (index < 0) { + super.getSharedElementParentMatrix(view, matrix); + } else { + matrix.set(mSharedElementParentMatrices.get(index)); + } + } +}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java new file mode 100644 index 0000000..dd3df47 --- /dev/null +++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -0,0 +1,476 @@ +/* + * Copyright (C) 2014 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; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.transition.Transition; +import android.transition.TransitionManager; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; + +import java.util.ArrayList; + +/** + * This ActivityTransitionCoordinator is created in ActivityOptions#makeSceneTransitionAnimation + * to govern the exit of the Scene and the shared elements when calling an Activity as well as + * the reentry of the Scene when coming back from the called Activity. + */ +class ExitTransitionCoordinator extends ActivityTransitionCoordinator { + private static final String TAG = "ExitTransitionCoordinator"; + private static final long MAX_WAIT_MS = 1000; + + private boolean mExitComplete; + + private Bundle mSharedElementBundle; + + private boolean mExitNotified; + + private boolean mSharedElementNotified; + + private Activity mActivity; + + private boolean mIsBackgroundReady; + + private boolean mIsCanceled; + + private Handler mHandler; + + private ObjectAnimator mBackgroundAnimator; + + private boolean mIsHidden; + + private Bundle mExitSharedElementBundle; + + private boolean mIsExitStarted; + + private boolean mSharedElementsHidden; + + public ExitTransitionCoordinator(Activity activity, ArrayList<String> names, + ArrayList<String> accepted, ArrayList<View> mapped, boolean isReturning) { + super(activity.getWindow(), names, getListener(activity, isReturning), isReturning); + viewsReady(mapSharedElements(accepted, mapped)); + stripOffscreenViews(); + mIsBackgroundReady = !isReturning; + mActivity = activity; + } + + private static SharedElementCallback getListener(Activity activity, boolean isReturning) { + return isReturning ? activity.mEnterTransitionListener : activity.mExitTransitionListener; + } + + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + switch (resultCode) { + case MSG_SET_REMOTE_RECEIVER: + stopCancel(); + mResultReceiver = resultData.getParcelable(KEY_REMOTE_RECEIVER); + if (mIsCanceled) { + mResultReceiver.send(MSG_CANCEL, null); + mResultReceiver = null; + } else { + notifyComplete(); + } + break; + case MSG_HIDE_SHARED_ELEMENTS: + stopCancel(); + if (!mIsCanceled) { + hideSharedElements(); + } + break; + case MSG_START_EXIT_TRANSITION: + mHandler.removeMessages(MSG_CANCEL); + startExit(); + break; + case MSG_SHARED_ELEMENT_DESTINATION: + mExitSharedElementBundle = resultData; + sharedElementExitBack(); + break; + } + } + + private void stopCancel() { + if (mHandler != null) { + mHandler.removeMessages(MSG_CANCEL); + } + } + + private void delayCancel() { + if (mHandler != null) { + mHandler.sendEmptyMessageDelayed(MSG_CANCEL, MAX_WAIT_MS); + } + } + + public void resetViews() { + if (mTransitioningViews != null) { + showViews(mTransitioningViews, true); + } + showViews(mSharedElements, true); + mIsHidden = true; + ViewGroup decorView = getDecor(); + if (!mIsReturning && decorView != null) { + decorView.suppressLayout(false); + } + moveSharedElementsFromOverlay(); + clearState(); + } + + private void sharedElementExitBack() { + final ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.suppressLayout(true); + } + if (decorView != null && mExitSharedElementBundle != null && + !mExitSharedElementBundle.isEmpty() && + !mSharedElements.isEmpty() && getSharedElementTransition() != null) { + startTransition(new Runnable() { + public void run() { + startSharedElementExit(decorView); + } + }); + } else { + sharedElementTransitionComplete(); + } + } + + private void startSharedElementExit(final ViewGroup decorView) { + Transition transition = getSharedElementExitTransition(); + transition.addListener(new Transition.TransitionListenerAdapter() { + @Override + public void onTransitionEnd(Transition transition) { + transition.removeListener(this); + if (mExitComplete) { + delayCancel(); + } + } + }); + final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle, + mSharedElementNames); + decorView.getViewTreeObserver() + .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + decorView.getViewTreeObserver().removeOnPreDrawListener(this); + setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots); + return true; + } + }); + setGhostVisibility(View.INVISIBLE); + scheduleGhostVisibilityChange(View.INVISIBLE); + if (mListener != null) { + mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, + sharedElementSnapshots); + } + TransitionManager.beginDelayedTransition(decorView, transition); + scheduleGhostVisibilityChange(View.VISIBLE); + setGhostVisibility(View.VISIBLE); + decorView.invalidate(); + } + + private void hideSharedElements() { + moveSharedElementsFromOverlay(); + if (!mIsHidden) { + hideViews(mSharedElements); + } + mSharedElementsHidden = true; + finishIfNecessary(); + } + + public void startExit() { + if (!mIsExitStarted) { + mIsExitStarted = true; + ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.suppressLayout(true); + } + moveSharedElementsToOverlay(); + startTransition(new Runnable() { + @Override + public void run() { + beginTransitions(); + } + }); + } + } + + public void startExit(int resultCode, Intent data) { + if (!mIsExitStarted) { + mIsExitStarted = true; + ViewGroup decorView = getDecor(); + if (decorView != null) { + decorView.suppressLayout(true); + } + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + mIsCanceled = true; + finish(); + } + }; + delayCancel(); + moveSharedElementsToOverlay(); + if (decorView != null && decorView.getBackground() == null) { + getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK)); + } + ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this, + mAllSharedElementNames, resultCode, data); + mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() { + @Override + public void onTranslucentConversionComplete(boolean drawComplete) { + if (!mIsCanceled) { + fadeOutBackground(); + } + } + }, options); + startTransition(new Runnable() { + @Override + public void run() { + startExitTransition(); + } + }); + } + } + + public void stop() { + if (mIsReturning && mActivity != null) { + // Override the previous ActivityOptions. We don't want the + // activity to have options since we're essentially canceling the + // transition and finishing right now. + mActivity.convertToTranslucent(null, null); + finish(); + } + } + + private void startExitTransition() { + Transition transition = getExitTransition(); + ViewGroup decorView = getDecor(); + if (transition != null && decorView != null && mTransitioningViews != null) { + TransitionManager.beginDelayedTransition(decorView, transition); + mTransitioningViews.get(0).invalidate(); + } else { + transitionStarted(); + } + } + + private void fadeOutBackground() { + if (mBackgroundAnimator == null) { + ViewGroup decor = getDecor(); + Drawable background; + if (decor != null && (background = decor.getBackground()) != null) { + background = background.mutate(); + getWindow().setBackgroundDrawable(background); + mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 0); + mBackgroundAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mBackgroundAnimator = null; + if (!mIsCanceled) { + mIsBackgroundReady = true; + notifyComplete(); + } + } + }); + mBackgroundAnimator.setDuration(getFadeDuration()); + mBackgroundAnimator.start(); + } else { + mIsBackgroundReady = true; + } + } + } + + private Transition getExitTransition() { + Transition viewsTransition = null; + if (mTransitioningViews != null && !mTransitioningViews.isEmpty()) { + viewsTransition = configureTransition(getViewsTransition(), true); + } + if (viewsTransition == null) { + exitTransitionComplete(); + } else { + final ArrayList<View> transitioningViews = mTransitioningViews; + viewsTransition.addListener(new ContinueTransitionListener() { + @Override + public void onTransitionEnd(Transition transition) { + transition.removeListener(this); + exitTransitionComplete(); + if (mIsHidden && transitioningViews != null) { + showViews(transitioningViews, true); + } + if (mSharedElementBundle != null) { + delayCancel(); + } + super.onTransitionEnd(transition); + } + }); + viewsTransition.forceVisibility(View.INVISIBLE, false); + } + return viewsTransition; + } + + private Transition getSharedElementExitTransition() { + Transition sharedElementTransition = null; + if (!mSharedElements.isEmpty()) { + sharedElementTransition = configureTransition(getSharedElementTransition(), false); + } + if (sharedElementTransition == null) { + sharedElementTransitionComplete(); + } else { + sharedElementTransition.addListener(new ContinueTransitionListener() { + @Override + public void onTransitionEnd(Transition transition) { + transition.removeListener(this); + sharedElementTransitionComplete(); + if (mIsHidden) { + showViews(mSharedElements, true); + } + } + }); + mSharedElements.get(0).invalidate(); + } + return sharedElementTransition; + } + + private void beginTransitions() { + Transition sharedElementTransition = getSharedElementExitTransition(); + Transition viewsTransition = getExitTransition(); + + Transition transition = mergeTransitions(sharedElementTransition, viewsTransition); + ViewGroup decorView = getDecor(); + if (transition != null && decorView != null) { + setGhostVisibility(View.INVISIBLE); + scheduleGhostVisibilityChange(View.INVISIBLE); + TransitionManager.beginDelayedTransition(decorView, transition); + scheduleGhostVisibilityChange(View.VISIBLE); + setGhostVisibility(View.VISIBLE); + decorView.invalidate(); + } else { + transitionStarted(); + } + } + + private void exitTransitionComplete() { + mExitComplete = true; + notifyComplete(); + } + + protected boolean isReadyToNotify() { + return mSharedElementBundle != null && mResultReceiver != null && mIsBackgroundReady; + } + + private void sharedElementTransitionComplete() { + mSharedElementBundle = mExitSharedElementBundle == null + ? captureSharedElementState() : captureExitSharedElementsState(); + notifyComplete(); + } + + private Bundle captureExitSharedElementsState() { + Bundle bundle = new Bundle(); + RectF bounds = new RectF(); + Matrix matrix = new Matrix(); + for (int i = 0; i < mSharedElements.size(); i++) { + String name = mSharedElementNames.get(i); + Bundle sharedElementState = mExitSharedElementBundle.getBundle(name); + if (sharedElementState != null) { + bundle.putBundle(name, sharedElementState); + } else { + View view = mSharedElements.get(i); + captureSharedElementState(view, name, bundle, matrix, bounds); + } + } + return bundle; + } + + protected void notifyComplete() { + if (isReadyToNotify()) { + if (!mSharedElementNotified) { + mSharedElementNotified = true; + delayCancel(); + mResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, mSharedElementBundle); + } + if (!mExitNotified && mExitComplete) { + mExitNotified = true; + mResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null); + mResultReceiver = null; // done talking + ViewGroup decorView = getDecor(); + if (!mIsReturning && decorView != null) { + decorView.suppressLayout(false); + } + finishIfNecessary(); + } + } + } + + private void finishIfNecessary() { + if (mIsReturning && mExitNotified && mActivity != null && (mSharedElements.isEmpty() || + mSharedElementsHidden)) { + finish(); + } + if (!mIsReturning && mExitNotified) { + mActivity = null; // don't need it anymore + } + } + + private void finish() { + stopCancel(); + if (mActivity != null) { + mActivity.mActivityTransitionState.clear(); + mActivity.finish(); + mActivity.overridePendingTransition(0, 0); + mActivity = null; + } + // Clear the state so that we can't hold any references accidentally and leak memory. + mHandler = null; + mSharedElementBundle = null; + if (mBackgroundAnimator != null) { + mBackgroundAnimator.cancel(); + mBackgroundAnimator = null; + } + mExitSharedElementBundle = null; + clearState(); + } + + @Override + protected boolean moveSharedElementWithParent() { + return !mIsReturning; + } + + @Override + protected Transition getViewsTransition() { + if (mIsReturning) { + return getWindow().getReturnTransition(); + } else { + return getWindow().getExitTransition(); + } + } + + protected Transition getSharedElementTransition() { + if (mIsReturning) { + return getWindow().getSharedElementReturnTransition(); + } else { + return getWindow().getSharedElementExitTransition(); + } + } +}
diff --git a/core/java/android/app/ExpandableListActivity.java b/core/java/android/app/ExpandableListActivity.java index 9651078..e08f25a 100644 --- a/core/java/android/app/ExpandableListActivity.java +++ b/core/java/android/app/ExpandableListActivity.java
@@ -27,7 +27,6 @@ import android.widget.ExpandableListView; import android.widget.SimpleCursorTreeAdapter; import android.widget.SimpleExpandableListAdapter; -import android.widget.AdapterView.AdapterContextMenuInfo; import java.util.Map;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index af8f177..5196834 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java
@@ -17,14 +17,20 @@ package android.app; import android.animation.Animator; +import android.annotation.Nullable; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.transition.Transition; +import android.transition.TransitionInflater; +import android.transition.TransitionSet; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.AttributeSet; @@ -56,11 +62,11 @@ final boolean mRetainInstance; final boolean mDetached; final Bundle mArguments; - + Bundle mSavedFragmentState; - + Fragment mInstance; - + public FragmentState(Fragment frag) { mClassName = frag.getClass().getName(); mIndex = frag.mIndex; @@ -72,7 +78,7 @@ mDetached = frag.mDetached; mArguments = frag.mArguments; } - + public FragmentState(Parcel in) { mClassName = in.readString(); mIndex = in.readInt(); @@ -85,18 +91,18 @@ mArguments = in.readBundle(); mSavedFragmentState = in.readBundle(); } - + public Fragment instantiate(Activity activity, Fragment parent) { if (mInstance != null) { return mInstance; } - + if (mArguments != null) { mArguments.setClassLoader(activity.getClassLoader()); } - + mInstance = Fragment.instantiate(activity, mClassName, mArguments); - + if (mSavedFragmentState != null) { mSavedFragmentState.setClassLoader(activity.getClassLoader()); mInstance.mSavedFragmentState = mSavedFragmentState; @@ -115,7 +121,7 @@ return mInstance; } - + public int describeContents() { return 0; } @@ -132,13 +138,13 @@ dest.writeBundle(mArguments); dest.writeBundle(mSavedFragmentState); } - + public static final Parcelable.Creator<FragmentState> CREATOR = new Parcelable.Creator<FragmentState>() { public FragmentState createFromParcel(Parcel in) { return new FragmentState(in); } - + public FragmentState[] newArray(int size) { return new FragmentState[size]; } @@ -160,11 +166,12 @@ * activity: if the activity is stopped, no fragments inside of it can be * started; when the activity is destroyed, all fragments will be destroyed. * - * <p>All subclasses of Fragment must include a public empty constructor. + * <p>All subclasses of Fragment must include a public no-argument constructor. * The framework will often re-instantiate a fragment class when needed, * in particular during state restore, and needs to be able to find this - * constructor to instantiate it. If the empty constructor is not available, - * a runtime exception will occur in some cases during state restore. + * constructor to instantiate it. If the no-argument constructor is not + * available, a runtime exception will occur in some cases during state + * restore. * * <p>Topics covered here: * <ol> @@ -297,17 +304,17 @@ * how you can determine if a fragment placed in a container is no longer * running in a layout with that container and avoid creating its view hierarchy * in that case.) - * + * * <p>The attributes of the <fragment> tag are used to control the * LayoutParams provided when attaching the fragment's view to the parent * container. They can also be parsed by the fragment in {@link #onInflate} * as parameters. - * + * * <p>The fragment being instantiated must have some kind of unique identifier * so that it can be re-associated with a previous instance if the parent * activity needs to be destroyed and recreated. This can be provided these * ways: - * + * * <ul> * <li>If nothing is explicitly supplied, the view ID of the container will * be used. @@ -316,7 +323,7 @@ * <li><code>android:id</code> can be used in <fragment> to provide * a specific identifier for the fragment. * </ul> - * + * * <a name="BackStack"></a> * <h3>Back Stack</h3> * @@ -345,7 +352,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener { private static final ArrayMap<String, Class<?>> sClassMap = new ArrayMap<String, Class<?>>(); - + static final int INVALID_STATE = -1; // Invalid state used as a null value. static final int INITIALIZING = 0; // Not yet created. static final int CREATED = 1; // Created. @@ -353,9 +360,11 @@ static final int STOPPED = 3; // Fully created, not started. static final int STARTED = 4; // Created and started, not resumed. static final int RESUMED = 5; // Created started and resumed. - + + private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet(); + int mState = INITIALIZING; - + // Non-null if the fragment's view hierarchy is currently animating away, // meaning we need to wait a bit on completely destroying it. This is the // animation that is running. @@ -368,13 +377,13 @@ // When instantiated from saved state, this is the saved state. Bundle mSavedFragmentState; SparseArray<Parcelable> mSavedViewState; - + // Index into active fragment array. int mIndex = -1; - + // Internal unique name for this fragment; String mWho; - + // Construction arguments; Bundle mArguments; @@ -389,25 +398,25 @@ // True if the fragment is in the list of added fragments. boolean mAdded; - + // If set this fragment is being removed from its activity. boolean mRemoving; // True if the fragment is in the resumed state. boolean mResumed; - + // Set to true if this fragment was instantiated from a layout file. boolean mFromLayout; - + // Set to true when the view has actually been inflated in its layout. boolean mInLayout; // True if this fragment has been restored from previously saved state. boolean mRestored; - + // Number of active back stack entries this fragment is in. int mBackStackNesting; - + // The fragment manager we are associated with. Set as soon as the // fragment is used in a transaction; cleared after it has been removed // from all transactions. @@ -426,29 +435,29 @@ // was dynamically added to the view hierarchy, or the ID supplied in // layout. int mFragmentId; - + // When a fragment is being dynamically added to the view hierarchy, this // is the identifier of the parent container it is being added to. int mContainerId; - + // The optional named tag for this fragment -- usually used to find // fragments that are not part of the layout. String mTag; - + // Set to true when the app has requested that this fragment be hidden // from the user. boolean mHidden; - + // Set to true when the app has requested that this fragment be detached. boolean mDetached; // If set this fragment would like its instance retained across // configuration changes. boolean mRetainInstance; - + // If set this fragment is being retained across the current config change. boolean mRetaining; - + // If set this fragment has menu items to contribute. boolean mHasMenu; @@ -457,16 +466,16 @@ // Used to verify that subclasses call through to super class. boolean mCalled; - + // If app has requested a specific animation, this is the one to use. int mNextAnim; - + // The parent container of the fragment after dynamically added to UI. ViewGroup mContainer; - + // The View generated for this fragment. View mView; - + // Whether this fragment should defer starting until after other fragments // have been started and their loaders are finished. boolean mDeferStart; @@ -477,7 +486,19 @@ LoaderManagerImpl mLoaderManager; boolean mLoadersStarted; boolean mCheckedForLoaderManager; - + + private Transition mEnterTransition = null; + private Transition mReturnTransition = USE_DEFAULT_TRANSITION; + private Transition mExitTransition = null; + private Transition mReenterTransition = USE_DEFAULT_TRANSITION; + private Transition mSharedElementEnterTransition = null; + private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION; + private Boolean mAllowReturnTransitionOverlap; + private Boolean mAllowEnterTransitionOverlap; + + SharedElementCallback mEnterTransitionCallback = SharedElementCallback.NULL_CALLBACK; + SharedElementCallback mExitTransitionCallback = SharedElementCallback.NULL_CALLBACK; + /** * State information that has been retrieved from a fragment instance * through {@link FragmentManager#saveFragmentInstanceState(Fragment) @@ -541,7 +562,7 @@ * will not be called when the fragment is re-instantiated; instead, * arguments can be supplied by the caller with {@link #setArguments} * and later retrieved by the Fragment with {@link #getArguments}. - * + * * <p>Applications should generally not implement a constructor. The * first place application code an run where the fragment is ready to * be used is in {@link #onAttach(Activity)}, the point where the fragment @@ -575,7 +596,7 @@ * the given fragment class. This is a runtime exception; it is not * normally expected to happen. */ - public static Fragment instantiate(Context context, String fname, Bundle args) { + public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) { try { Class<?> clazz = sClassMap.get(fname); if (clazz == null) { @@ -607,7 +628,7 @@ + " empty constructor that is public", e); } } - + final void restoreViewState(Bundle savedInstanceState) { if (mSavedViewState != null) { mView.restoreHierarchyState(mSavedViewState); @@ -647,7 +668,7 @@ @Override final public int hashCode() { return super.hashCode(); } - + @Override public String toString() { StringBuilder sb = new StringBuilder(128); @@ -667,7 +688,7 @@ sb.append('}'); return sb.toString(); } - + /** * Return the identifier this fragment is known by. This is either * the android:id value supplied in a layout or the container view ID @@ -676,14 +697,14 @@ final public int getId() { return mFragmentId; } - + /** * Get the tag name of the fragment, if specified. */ final public String getTag() { return mTag; } - + /** * Supply the construction arguments for this fragment. This can only * be called before the fragment has been attached to its activity; that @@ -758,7 +779,7 @@ final public Activity getActivity() { return mActivity; } - + /** * Return <code>getActivity().getResources()</code>. */ @@ -768,7 +789,7 @@ } return mActivity.getResources(); } - + /** * Return a localized, styled CharSequence from the application's package's * default string table. @@ -868,7 +889,7 @@ final public boolean isRemoving() { return mRemoving; } - + /** * Return true if the layout is included as part of an activity view * hierarchy via the <fragment> tag. This will always be true when @@ -887,7 +908,7 @@ final public boolean isResumed() { return mResumed; } - + /** * Return true if the fragment is currently visible to the user. This means * it: (1) has been added, (2) has its view attached to the window, and @@ -897,7 +918,7 @@ return isAdded() && !isHidden() && mView != null && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; } - + /** * Return true if the fragment has been hidden. By default fragments * are shown. You can find out about changes to this state with @@ -908,7 +929,7 @@ final public boolean isHidden() { return mHidden; } - + /** * Called when the hidden state (as returned by {@link #isHidden()} of * the fragment has changed. Fragments start out not hidden; this will @@ -918,7 +939,7 @@ */ public void onHiddenChanged(boolean hidden) { } - + /** * Control whether a fragment instance is retained across Activity * re-creation (such as from a configuration change). This can only @@ -940,16 +961,16 @@ } mRetainInstance = retain; } - + final public boolean getRetainInstance() { return mRetainInstance; } - + /** * Report that this fragment would like to participate in populating * the options menu by receiving a call to {@link #onCreateOptionsMenu} * and related methods. - * + * * @param hasMenu If true, the fragment has menu items to contribute. */ public void setHasOptionsMenu(boolean hasMenu) { @@ -1032,7 +1053,7 @@ public void startActivity(Intent intent) { startActivity(intent, null); } - + /** * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's * containing Activity. @@ -1079,13 +1100,13 @@ mActivity.startActivityFromFragment(this, intent, requestCode, options); } } - + /** * Receive the result from a previous call to * {@link #startActivityForResult(Intent, int)}. This follows the * related Activity API as described there in * {@link Activity#onActivityResult(int, int, Intent)}. - * + * * @param requestCode The integer request code originally supplied to * startActivityForResult(), allowing you to identify who this * result came from. @@ -1096,16 +1117,24 @@ */ public void onActivityResult(int requestCode, int resultCode, Intent data) { } - + /** * @hide Hack so that DialogFragment can make its Dialog before creating * its views, and the view construction can use the dialog's context for * inflation. Maybe this should become a public API. Note sure. */ public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { - return mActivity.getLayoutInflater(); + // Newer platform versions use the child fragment manager's LayoutInflaterFactory. + if (mActivity.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) { + LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity); + getChildFragmentManager(); // Init if needed; use raw implementation below. + result.setPrivateFactory(mChildFragmentManager.getLayoutInflaterFactory()); + return result; + } else { + return mActivity.getLayoutInflater(); + } } - + /** * @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead. */ @@ -1121,7 +1150,7 @@ * tag in a layout file. Note this is <em>before</em> the fragment's * {@link #onAttach(Activity)} has been called; all you should do here is * parse the attributes and save them away. - * + * * <p>This is called every time the fragment is inflated, even if it is * being inflated into a new instance with saved state. It typically makes * sense to re-parse the parameters each time, to allow them to change with @@ -1159,8 +1188,33 @@ public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { onInflate(attrs, savedInstanceState); mCalled = true; + + TypedArray a = activity.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.Fragment); + mEnterTransition = loadTransition(activity, a, mEnterTransition, null, + com.android.internal.R.styleable.Fragment_fragmentEnterTransition); + mReturnTransition = loadTransition(activity, a, mReturnTransition, USE_DEFAULT_TRANSITION, + com.android.internal.R.styleable.Fragment_fragmentReturnTransition); + mExitTransition = loadTransition(activity, a, mExitTransition, null, + com.android.internal.R.styleable.Fragment_fragmentExitTransition); + mReenterTransition = loadTransition(activity, a, mReenterTransition, USE_DEFAULT_TRANSITION, + com.android.internal.R.styleable.Fragment_fragmentReenterTransition); + mSharedElementEnterTransition = loadTransition(activity, a, mSharedElementEnterTransition, + null, com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition); + mSharedElementReturnTransition = loadTransition(activity, a, mSharedElementReturnTransition, + USE_DEFAULT_TRANSITION, + com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition); + if (mAllowEnterTransitionOverlap == null) { + mAllowEnterTransitionOverlap = a.getBoolean( + com.android.internal.R.styleable.Fragment_fragmentAllowEnterTransitionOverlap, true); + } + if (mAllowReturnTransitionOverlap == null) { + mAllowReturnTransitionOverlap = a.getBoolean( + com.android.internal.R.styleable.Fragment_fragmentAllowReturnTransitionOverlap, true); + } + a.recycle(); } - + /** * Called when a fragment is first attached to its activity. * {@link #onCreate(Bundle)} will be called after this. @@ -1168,25 +1222,25 @@ public void onAttach(Activity activity) { mCalled = true; } - + /** * Called when a fragment loads an animation. */ public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { return null; } - + /** * Called to do initial creation of a fragment. This is called after * {@link #onAttach(Activity)} and before * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. - * + * * <p>Note that this can be called while the fragment's activity is * still in the process of being created. As such, you can not rely * on things like the activity's content view hierarchy being initialized * at this point. If you want to do work once the activity itself is * created, see {@link #onActivityCreated(Bundle)}. - * + * * @param savedInstanceState If the fragment is being re-created from * a previous saved state, this is the state. */ @@ -1199,10 +1253,10 @@ * This is optional, and non-graphical fragments can return null (which * is the default implementation). This will be called between * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. - * + * * <p>If you return a View from here, you will later be called in * {@link #onDestroyView} when the view is being released. - * + * * @param inflater The LayoutInflater object that can be used to inflate * any views in the fragment, * @param container If non-null, this is the parent view that the fragment's @@ -1210,10 +1264,11 @@ * but this can be used to generate the LayoutParams of the view. * @param savedInstanceState If non-null, this fragment is being re-constructed * from a previous saved state as given here. - * + * * @return Return the View for the fragment's UI, or null. */ - public View onCreateView(LayoutInflater inflater, ViewGroup container, + @Nullable + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { return null; } @@ -1228,19 +1283,20 @@ * @param savedInstanceState If non-null, this fragment is being re-constructed * from a previous saved state as given here. */ - public void onViewCreated(View view, Bundle savedInstanceState) { + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { } - + /** * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}), * if provided. - * + * * @return The fragment's root view, or null if it has no layout. */ + @Nullable public View getView() { return mView; } - + /** * Called when the fragment's activity has been created and this * fragment's view hierarchy instantiated. It can be used to do final @@ -1280,7 +1336,7 @@ */ public void onStart() { mCalled = true; - + if (!mLoadersStarted) { mLoadersStarted = true; if (!mCheckedForLoaderManager) { @@ -1292,7 +1348,7 @@ } } } - + /** * Called when the fragment is visible to the user and actively running. * This is generally @@ -1302,7 +1358,7 @@ public void onResume() { mCalled = true; } - + /** * Called to ask the fragment to save its current dynamic state, so it * can later be reconstructed in a new instance of its process is @@ -1324,11 +1380,11 @@ */ public void onSaveInstanceState(Bundle outState) { } - + public void onConfigurationChanged(Configuration newConfig) { mCalled = true; } - + /** * Called when the Fragment is no longer resumed. This is generally * tied to {@link Activity#onPause() Activity.onPause} of the containing @@ -1337,7 +1393,7 @@ public void onPause() { mCalled = true; } - + /** * Called when the Fragment is no longer started. This is generally * tied to {@link Activity#onStop() Activity.onStop} of the containing @@ -1346,11 +1402,11 @@ public void onStop() { mCalled = true; } - + public void onLowMemory() { mCalled = true; } - + public void onTrimMemory(int level) { mCalled = true; } @@ -1367,7 +1423,7 @@ public void onDestroyView() { mCalled = true; } - + /** * Called when the fragment is no longer in use. This is called * after {@link #onStop()} and before {@link #onDetach()}. @@ -1422,16 +1478,16 @@ public void onDetach() { mCalled = true; } - + /** * Initialize the contents of the Activity's standard options menu. You * should place your menu items in to <var>menu</var>. For this method * to be called, you must have first called {@link #setHasOptionsMenu}. See * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} * for more information. - * + * * @param menu The options menu in which you place your items. - * + * * @see #setHasOptionsMenu * @see #onPrepareOptionsMenu * @see #onOptionsItemSelected @@ -1446,10 +1502,10 @@ * dynamically modify the contents. See * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} * for more information. - * + * * @param menu The options menu as last shown or first initialized by * onCreateOptionsMenu(). - * + * * @see #setHasOptionsMenu * @see #onCreateOptionsMenu */ @@ -1465,7 +1521,7 @@ */ public void onDestroyOptionsMenu() { } - + /** * This hook is called whenever an item in your options menu is selected. * The default implementation simply returns false to have the normal @@ -1473,15 +1529,15 @@ * its Handler as appropriate). You can use this method for any items * for which you would like to do processing without those other * facilities. - * + * * <p>Derived classes should call through to the base class for it to * perform the default menu handling. - * + * * @param item The menu item that was selected. - * + * * @return boolean Return false to allow normal menu processing to * proceed, true to consume it here. - * + * * @see #onCreateOptionsMenu */ public boolean onOptionsItemSelected(MenuItem item) { @@ -1491,13 +1547,13 @@ /** * This hook is called whenever the options menu is being closed (either by the user canceling * the menu with the back/menu button, or when an item is selected). - * + * * @param menu The options menu as last shown or first initialized by * onCreateOptionsMenu(). */ public void onOptionsMenuClosed(Menu menu) { } - + /** * Called when a context menu for the {@code view} is about to be shown. * Unlike {@link #onCreateOptionsMenu}, this will be called every @@ -1525,25 +1581,25 @@ * {@link OnCreateContextMenuListener} on the view to this fragment, so * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be * called when it is time to show the context menu. - * + * * @see #unregisterForContextMenu(View) * @param view The view that should show a context menu. */ public void registerForContextMenu(View view) { view.setOnCreateContextMenuListener(this); } - + /** * Prevents a context menu to be shown for the given view. This method will * remove the {@link OnCreateContextMenuListener} on the view. - * + * * @see #registerForContextMenu(View) * @param view The view that should stop showing a context menu. */ public void unregisterForContextMenu(View view) { view.setOnCreateContextMenuListener(null); } - + /** * This hook is called whenever an item in a context menu is selected. The * default implementation simply returns false to have the normal processing @@ -1556,7 +1612,7 @@ * <p> * Derived classes should call through to the base class for it to perform * the default menu handling. - * + * * @param item The context menu item that was selected. * @return boolean Return false to allow normal context menu processing to * proceed, true to consume it here. @@ -1564,7 +1620,298 @@ public boolean onContextItemSelected(MenuItem item) { return false; } - + + /** + * When custom transitions are used with Fragments, the enter transition callback + * is called when this Fragment is attached or detached when not popping the back stack. + * + * @param callback Used to manipulate the shared element transitions on this Fragment + * when added not as a pop from the back stack. + */ + public void setEnterSharedElementCallback(SharedElementCallback callback) { + if (callback == null) { + callback = SharedElementCallback.NULL_CALLBACK; + } + mEnterTransitionCallback = callback; + } + + /** + * @hide + */ + public void setEnterSharedElementTransitionCallback(SharedElementCallback callback) { + setEnterSharedElementCallback(callback); + } + + /** + * When custom transitions are used with Fragments, the exit transition callback + * is called when this Fragment is attached or detached when popping the back stack. + * + * @param callback Used to manipulate the shared element transitions on this Fragment + * when added as a pop from the back stack. + */ + public void setExitSharedElementCallback(SharedElementCallback callback) { + if (callback == null) { + callback = SharedElementCallback.NULL_CALLBACK; + } + mExitTransitionCallback = callback; + } + + /** + * @hide + */ + public void setExitSharedElementTransitionCallback(SharedElementCallback callback) { + setExitSharedElementCallback(callback); + } + + /** + * Sets the Transition that will be used to move Views into the initial scene. The entering + * Views will be those that are regular Views or ViewGroups that have + * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as entering is governed by changing visibility from + * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null, + * entering Views will remain unaffected. + * + * @param transition The Transition to use to move Views into the initial Scene. + * @attr ref android.R.styleable#Fragment_fragmentEnterTransition + */ + public void setEnterTransition(Transition transition) { + mEnterTransition = transition; + } + + /** + * Returns the Transition that will be used to move Views into the initial scene. The entering + * Views will be those that are regular Views or ViewGroups that have + * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as entering is governed by changing visibility from + * {@link View#INVISIBLE} to {@link View#VISIBLE}. + * + * @return the Transition to use to move Views into the initial Scene. + * @attr ref android.R.styleable#Fragment_fragmentEnterTransition + */ + public Transition getEnterTransition() { + return mEnterTransition; + } + + /** + * Sets the Transition that will be used to move Views out of the scene when the Fragment is + * preparing to be removed, hidden, or detached because of popping the back stack. The exiting + * Views will be those that are regular Views or ViewGroups that have + * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as entering is governed by changing visibility from + * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, + * entering Views will remain unaffected. If nothing is set, the default will be to + * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}. + * + * @param transition The Transition to use to move Views out of the Scene when the Fragment + * is preparing to close. + * @attr ref android.R.styleable#Fragment_fragmentExitTransition + */ + public void setReturnTransition(Transition transition) { + mReturnTransition = transition; + } + + /** + * Returns the Transition that will be used to move Views out of the scene when the Fragment is + * preparing to be removed, hidden, or detached because of popping the back stack. The exiting + * Views will be those that are regular Views or ViewGroups that have + * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as entering is governed by changing visibility from + * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, + * entering Views will remain unaffected. + * + * @return the Transition to use to move Views out of the Scene when the Fragment + * is preparing to close. + * @attr ref android.R.styleable#Fragment_fragmentExitTransition + */ + public Transition getReturnTransition() { + return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition() + : mReturnTransition; + } + + /** + * Sets the Transition that will be used to move Views out of the scene when the + * fragment is removed, hidden, or detached when not popping the back stack. + * The exiting Views will be those that are regular Views or ViewGroups that + * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as exiting is governed by changing visibility + * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will + * remain unaffected. + * + * @param transition The Transition to use to move Views out of the Scene when the Fragment + * is being closed not due to popping the back stack. + * @attr ref android.R.styleable#Fragment_fragmentExitTransition + */ + public void setExitTransition(Transition transition) { + mExitTransition = transition; + } + + /** + * Returns the Transition that will be used to move Views out of the scene when the + * fragment is removed, hidden, or detached when not popping the back stack. + * The exiting Views will be those that are regular Views or ViewGroups that + * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as exiting is governed by changing visibility + * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will + * remain unaffected. + * + * @return the Transition to use to move Views out of the Scene when the Fragment + * is being closed not due to popping the back stack. + * @attr ref android.R.styleable#Fragment_fragmentExitTransition + */ + public Transition getExitTransition() { + return mExitTransition; + } + + /** + * Sets the Transition that will be used to move Views in to the scene when returning due + * to popping a back stack. The entering Views will be those that are regular Views + * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions + * will extend {@link android.transition.Visibility} as exiting is governed by changing + * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, + * the views will remain unaffected. If nothing is set, the default will be to use the same + * transition as {@link #setExitTransition(android.transition.Transition)}. + * + * @param transition The Transition to use to move Views into the scene when reentering from a + * previously-started Activity. + * @attr ref android.R.styleable#Fragment_fragmentReenterTransition + */ + public void setReenterTransition(Transition transition) { + mReenterTransition = transition; + } + + /** + * Returns the Transition that will be used to move Views in to the scene when returning due + * to popping a back stack. The entering Views will be those that are regular Views + * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions + * will extend {@link android.transition.Visibility} as exiting is governed by changing + * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, + * the views will remain unaffected. If nothing is set, the default will be to use the same + * transition as {@link #setExitTransition(android.transition.Transition)}. + * + * @return the Transition to use to move Views into the scene when reentering from a + * previously-started Activity. + * @attr ref android.R.styleable#Fragment_fragmentReenterTransition + */ + public Transition getReenterTransition() { + return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition() + : mReenterTransition; + } + + /** + * Sets the Transition that will be used for shared elements transferred into the content + * Scene. Typical Transitions will affect size and location, such as + * {@link android.transition.ChangeBounds}. A null + * value will cause transferred shared elements to blink to the final position. + * + * @param transition The Transition to use for shared elements transferred into the content + * Scene. + * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition + */ + public void setSharedElementEnterTransition(Transition transition) { + mSharedElementEnterTransition = transition; + } + + /** + * Returns the Transition that will be used for shared elements transferred into the content + * Scene. Typical Transitions will affect size and location, such as + * {@link android.transition.ChangeBounds}. A null + * value will cause transferred shared elements to blink to the final position. + * + * @return The Transition to use for shared elements transferred into the content + * Scene. + * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition + */ + public Transition getSharedElementEnterTransition() { + return mSharedElementEnterTransition; + } + + /** + * Sets the Transition that will be used for shared elements transferred back during a + * pop of the back stack. This Transition acts in the leaving Fragment. + * Typical Transitions will affect size and location, such as + * {@link android.transition.ChangeBounds}. A null + * value will cause transferred shared elements to blink to the final position. + * If no value is set, the default will be to use the same value as + * {@link #setSharedElementEnterTransition(android.transition.Transition)}. + * + * @param transition The Transition to use for shared elements transferred out of the content + * Scene. + * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition + */ + public void setSharedElementReturnTransition(Transition transition) { + mSharedElementReturnTransition = transition; + } + + /** + * Return the Transition that will be used for shared elements transferred back during a + * pop of the back stack. This Transition acts in the leaving Fragment. + * Typical Transitions will affect size and location, such as + * {@link android.transition.ChangeBounds}. A null + * value will cause transferred shared elements to blink to the final position. + * If no value is set, the default will be to use the same value as + * {@link #setSharedElementEnterTransition(android.transition.Transition)}. + * + * @return The Transition to use for shared elements transferred out of the content + * Scene. + * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition + */ + public Transition getSharedElementReturnTransition() { + return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION ? + getSharedElementEnterTransition() : mSharedElementReturnTransition; + } + + /** + * Sets whether the the exit transition and enter transition overlap or not. + * When true, the enter transition will start as soon as possible. When false, the + * enter transition will wait until the exit transition completes before starting. + * + * @param allow true to start the enter transition when possible or false to + * wait until the exiting transition completes. + * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap + */ + public void setAllowEnterTransitionOverlap(boolean allow) { + mAllowEnterTransitionOverlap = allow; + } + + /** + * Returns whether the the exit transition and enter transition overlap or not. + * When true, the enter transition will start as soon as possible. When false, the + * enter transition will wait until the exit transition completes before starting. + * + * @return true when the enter transition should start as soon as possible or false to + * when it should wait until the exiting transition completes. + * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap + */ + public boolean getAllowEnterTransitionOverlap() { + return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap; + } + + /** + * Sets whether the the return transition and reenter transition overlap or not. + * When true, the reenter transition will start as soon as possible. When false, the + * reenter transition will wait until the return transition completes before starting. + * + * @param allow true to start the reenter transition when possible or false to wait until the + * return transition completes. + * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap + */ + public void setAllowReturnTransitionOverlap(boolean allow) { + mAllowReturnTransitionOverlap = allow; + } + + /** + * Returns whether the the return transition and reenter transition overlap or not. + * When true, the reenter transition will start as soon as possible. When false, the + * reenter transition will wait until the return transition completes before starting. + * + * @return true to start the reenter transition when possible or false to wait until the + * return transition completes. + * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap + */ + public boolean getAllowReturnTransitionOverlap() { + return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap; + } + /** * Print the Fragments's state into the given stream. * @@ -1576,53 +1923,53 @@ */ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { writer.print(prefix); writer.print("mFragmentId=#"); - writer.print(Integer.toHexString(mFragmentId)); - writer.print(" mContainerId=#"); - writer.print(Integer.toHexString(mContainerId)); - writer.print(" mTag="); writer.println(mTag); + writer.print(Integer.toHexString(mFragmentId)); + writer.print(" mContainerId=#"); + writer.print(Integer.toHexString(mContainerId)); + writer.print(" mTag="); writer.println(mTag); writer.print(prefix); writer.print("mState="); writer.print(mState); - writer.print(" mIndex="); writer.print(mIndex); - writer.print(" mWho="); writer.print(mWho); - writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); + writer.print(" mIndex="); writer.print(mIndex); + writer.print(" mWho="); writer.print(mWho); + writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); - writer.print(" mRemoving="); writer.print(mRemoving); - writer.print(" mResumed="); writer.print(mResumed); - writer.print(" mFromLayout="); writer.print(mFromLayout); - writer.print(" mInLayout="); writer.println(mInLayout); + writer.print(" mRemoving="); writer.print(mRemoving); + writer.print(" mResumed="); writer.print(mResumed); + writer.print(" mFromLayout="); writer.print(mFromLayout); + writer.print(" mInLayout="); writer.println(mInLayout); writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); - writer.print(" mDetached="); writer.print(mDetached); - writer.print(" mMenuVisible="); writer.print(mMenuVisible); - writer.print(" mHasMenu="); writer.println(mHasMenu); + writer.print(" mDetached="); writer.print(mDetached); + writer.print(" mMenuVisible="); writer.print(mMenuVisible); + writer.print(" mHasMenu="); writer.println(mHasMenu); writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance); - writer.print(" mRetaining="); writer.print(mRetaining); - writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); + writer.print(" mRetaining="); writer.print(mRetaining); + writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); if (mFragmentManager != null) { writer.print(prefix); writer.print("mFragmentManager="); - writer.println(mFragmentManager); + writer.println(mFragmentManager); } if (mActivity != null) { writer.print(prefix); writer.print("mActivity="); - writer.println(mActivity); + writer.println(mActivity); } if (mParentFragment != null) { writer.print(prefix); writer.print("mParentFragment="); - writer.println(mParentFragment); + writer.println(mParentFragment); } if (mArguments != null) { writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); } if (mSavedFragmentState != null) { writer.print(prefix); writer.print("mSavedFragmentState="); - writer.println(mSavedFragmentState); + writer.println(mSavedFragmentState); } if (mSavedViewState != null) { writer.print(prefix); writer.print("mSavedViewState="); - writer.println(mSavedViewState); + writer.println(mSavedViewState); } if (mTarget != null) { writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); - writer.print(" mTargetRequestCode="); - writer.println(mTargetRequestCode); + writer.print(" mTargetRequestCode="); + writer.println(mTargetRequestCode); } if (mNextAnim != 0) { writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim); @@ -1636,7 +1983,7 @@ if (mAnimatingAway != null) { writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway); writer.print(prefix); writer.print("mStateAfterAnimating="); - writer.println(mStateAfterAnimating); + writer.println(mStateAfterAnimating); } if (mLoaderManager != null) { writer.print(prefix); writer.println("Loader Manager:"); @@ -1668,6 +2015,11 @@ } return mView.findViewById(id); } + + @Override + public boolean hasView() { + return (mView != null); + } }, this); } @@ -1874,7 +2226,7 @@ throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onStop()"); } - + if (mLoadersStarted) { mLoadersStarted = false; if (!mCheckedForLoaderManager) { @@ -1917,4 +2269,23 @@ + " did not call through to super.onDestroy()"); } } + + private static Transition loadTransition(Context context, TypedArray typedArray, + Transition currentValue, Transition defaultValue, int id) { + if (currentValue != defaultValue) { + return currentValue; + } + int transitionId = typedArray.getResourceId(id, 0); + Transition transition = defaultValue; + if (transitionId != 0 && transitionId != com.android.internal.R.transition.no_transition) { + TransitionInflater inflater = TransitionInflater.from(context); + transition = inflater.inflateTransition(transitionId); + if (transition instanceof TransitionSet && + ((TransitionSet)transition).getTransitionCount() == 0) { + transition = null; + } + } + return transition; + } + }
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java index b810b89..d0aa0fd 100644 --- a/core/java/android/app/FragmentBreadCrumbs.java +++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -37,7 +37,10 @@ * * <p>The default style for this view is * {@link android.R.style#Widget_FragmentBreadCrumbs}. + * + * @deprecated This widget is no longer supported. */ +@Deprecated public class FragmentBreadCrumbs extends ViewGroup implements FragmentManager.OnBackStackChangedListener { Activity mActivity; @@ -55,6 +58,8 @@ private OnBreadCrumbClickListener mOnBreadCrumbClickListener; private int mGravity; + private int mLayoutResId; + private int mTextColor; private static final int DEFAULT_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL; @@ -81,17 +86,31 @@ } public FragmentBreadCrumbs(Context context, AttributeSet attrs) { - this(context, attrs, android.R.style.Widget_FragmentBreadCrumbs); + this(context, attrs, com.android.internal.R.attr.fragmentBreadCrumbsStyle); } - public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); + public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.FragmentBreadCrumbs, defStyle, 0); + /** + * @hide + */ + public FragmentBreadCrumbs( + Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + final TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.FragmentBreadCrumbs, defStyleAttr, defStyleRes); mGravity = a.getInt(com.android.internal.R.styleable.FragmentBreadCrumbs_gravity, DEFAULT_GRAVITY); + mLayoutResId = a.getResourceId( + com.android.internal.R.styleable.FragmentBreadCrumbs_itemLayout, + com.android.internal.R.layout.fragment_bread_crumb_item); + mTextColor = a.getColor( + com.android.internal.R.styleable.FragmentBreadCrumbs_itemColor, + 0); a.recycle(); } @@ -300,12 +319,11 @@ } } if (i >= numViews) { - final View item = mInflater.inflate( - com.android.internal.R.layout.fragment_bread_crumb_item, - this, false); + final View item = mInflater.inflate(mLayoutResId, this, false); final TextView text = (TextView) item.findViewById(com.android.internal.R.id.title); text.setText(bse.getBreadCrumbTitle()); text.setTag(bse); + text.setTextColor(mTextColor); if (i == 0) { item.findViewById(com.android.internal.R.id.left_icon).setVisibility(View.GONE); }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 76f9d97..fc761fe 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java
@@ -19,6 +19,7 @@ import android.animation.Animator; import android.animation.AnimatorInflater; import android.animation.AnimatorListenerAdapter; +import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; import android.os.Bundle; @@ -27,11 +28,13 @@ import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; +import android.util.AttributeSet; import android.util.DebugUtils; import android.util.Log; import android.util.LogWriter; import android.util.SparseArray; import android.util.SuperNotCalledException; +import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -392,12 +395,13 @@ */ interface FragmentContainer { public View findViewById(int id); + public boolean hasView(); } /** * Container for fragments associated with an activity. */ -final class FragmentManagerImpl extends FragmentManager { +final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 { static boolean DEBUG = false; static final String TAG = "FragmentManager"; @@ -432,7 +436,7 @@ boolean mDestroyed; String mNoTransactionsBecause; boolean mHavePendingDeferredStart; - + // Temporary vars for state save and restore. Bundle mStateBundle = null; SparseArray<Parcelable> mStateArray = null; @@ -1494,7 +1498,10 @@ return false; } final BackStackRecord bss = mBackStack.remove(last); - bss.popFromBackStack(true); + SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); + SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); + bss.calculateBackFragments(firstOutFragments, lastInFragments); + bss.popFromBackStack(true, null, firstOutFragments, lastInFragments); reportBackStackChanged(); } else { int index = -1; @@ -1538,9 +1545,16 @@ states.add(mBackStack.remove(i)); } final int LAST = states.size()-1; + SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); + SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); + for (int i=0; i<=LAST; i++) { + states.get(i).calculateBackFragments(firstOutFragments, lastInFragments); + } + BackStackRecord.TransitionState state = null; for (int i=0; i<=LAST; i++) { if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i)); - states.get(i).popFromBackStack(i == LAST); + state = states.get(i).popFromBackStack(i == LAST, state, + firstOutFragments, lastInFragments); } reportBackStackChanged(); } @@ -1744,6 +1758,7 @@ fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader()); f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray( FragmentManagerImpl.VIEW_STATE_TAG); + f.mSavedFragmentState = fs.mSavedFragmentState; } } } @@ -2051,4 +2066,100 @@ } return animAttr; } + + @Override + public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { + if (!"fragment".equals(name)) { + return null; + } + + String fname = attrs.getAttributeValue(null, "class"); + TypedArray a = + context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment); + if (fname == null) { + fname = a.getString(com.android.internal.R.styleable.Fragment_name); + } + int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID); + String tag = a.getString(com.android.internal.R.styleable.Fragment_tag); + a.recycle(); + + int containerId = parent != null ? parent.getId() : 0; + if (containerId == View.NO_ID && id == View.NO_ID && tag == null) { + throw new IllegalArgumentException(attrs.getPositionDescription() + + ": Must specify unique android:id, android:tag, or have a parent with" + + " an id for " + fname); + } + + // If we restored from a previous state, we may already have + // instantiated this fragment from the state and should use + // that instance instead of making a new one. + Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null; + if (fragment == null && tag != null) { + fragment = findFragmentByTag(tag); + } + if (fragment == null && containerId != View.NO_ID) { + fragment = findFragmentById(containerId); + } + + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x" + + Integer.toHexString(id) + " fname=" + fname + + " existing=" + fragment); + if (fragment == null) { + fragment = Fragment.instantiate(context, fname); + fragment.mFromLayout = true; + fragment.mFragmentId = id != 0 ? id : containerId; + fragment.mContainerId = containerId; + fragment.mTag = tag; + fragment.mInLayout = true; + fragment.mFragmentManager = this; + fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState); + addFragment(fragment, true); + } else if (fragment.mInLayout) { + // A fragment already exists and it is not one we restored from + // previous state. + throw new IllegalArgumentException(attrs.getPositionDescription() + + ": Duplicate id 0x" + Integer.toHexString(id) + + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId) + + " with another fragment for " + fname); + } else { + // This fragment was retained from a previous instance; get it + // going now. + fragment.mInLayout = true; + // If this fragment is newly instantiated (either right now, or + // from last saved state), then give it the attributes to + // initialize itself. + if (!fragment.mRetaining) { + fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState); + } + } + + // If we haven't finished entering the CREATED state ourselves yet, + // push the inflated child fragment along. + if (mCurState < Fragment.CREATED && fragment.mFromLayout) { + moveToState(fragment, Fragment.CREATED, 0, 0, false); + } else { + moveToState(fragment); + } + + if (fragment.mView == null) { + throw new IllegalStateException("Fragment " + fname + + " did not create a view."); + } + if (id != 0) { + fragment.mView.setId(id); + } + if (fragment.mView.getTag() == null) { + fragment.mView.setTag(tag); + } + return fragment.mView; + } + + @Override + public View onCreateView(String name, Context context, AttributeSet attrs) { + return null; + } + + LayoutInflater.Factory2 getLayoutInflaterFactory() { + return this; + } }
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index 652ad23..25cd3cc 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java
@@ -1,5 +1,8 @@ package android.app; +import android.util.Pair; +import android.view.View; + /** * API for performing a set of Fragment operations. * @@ -169,6 +172,36 @@ public abstract FragmentTransaction setTransition(int transit); /** + * TODO: remove from API + * @hide + */ + public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) { + return this; + } + + /** + * Used with to map a View from a removed or hidden Fragment to a View from a shown + * or added Fragment. + * @param sharedElement A View in a disappearing Fragment to match with a View in an + * appearing Fragment. + * @param name The transitionName for a View in an appearing Fragment to match to the shared + * element. + */ + public abstract FragmentTransaction addSharedElement(View sharedElement, String name); + + /** + * TODO: remove from API + * @hide + */ + public abstract FragmentTransaction setSharedElement(View sharedElement, String name); + + /** + * TODO: remove from API + * @hide + */ + public abstract FragmentTransaction setSharedElements(Pair<View, String>... sharedElements); + + /** * Set a custom style resource that will be used for resolving transit * animations. */
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 27e97d41..aa5fea0 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java
@@ -36,6 +36,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.Point; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; @@ -45,8 +46,11 @@ import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.StrictMode; +import android.service.voice.IVoiceInteractionSession; +import com.android.internal.app.IVoiceInteractor; import java.util.List; @@ -57,18 +61,19 @@ * {@hide} */ public interface IActivityManager extends IInterface { - public int startActivity(IApplicationThread caller, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options) throws RemoteException; - public int startActivityAsUser(IApplicationThread caller, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException; + public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, + String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, + ProfilerInfo profilerInfo, Bundle options) throws RemoteException; + public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, + String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, + ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException; + public int startActivityAsCaller(IApplicationThread caller, String callingPackage, + Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, + int flags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException; public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException; + int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException; public int startActivityWithConfig(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, Configuration newConfig, @@ -77,12 +82,20 @@ IntentSender intent, Intent fillInIntent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) throws RemoteException; + public int startVoiceActivity(String callingPackage, int callingPid, int callingUid, + Intent intent, String resolvedType, IVoiceInteractionSession session, + IVoiceInteractor interactor, int flags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException; public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent, Bundle options) throws RemoteException; - public boolean finishActivity(IBinder token, int code, Intent data) + public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException; + public boolean finishActivity(IBinder token, int code, Intent data, boolean finishTask) throws RemoteException; public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException; public boolean finishActivityAffinity(IBinder token) throws RemoteException; + public void finishVoiceTask(IVoiceInteractionSession session) throws RemoteException; + public boolean releaseActivityInstance(IBinder token) throws RemoteException; + public void releaseSomeActivities(IApplicationThread app) throws RemoteException; public boolean willActivityBeVisible(IBinder token) throws RemoteException; public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, @@ -100,17 +113,19 @@ boolean stopProfiling) throws RemoteException; public void activityPaused(IBinder token) throws RemoteException; public void activityStopped(IBinder token, Bundle state, - Bitmap thumbnail, CharSequence description) throws RemoteException; + PersistableBundle persistentState, CharSequence description) throws RemoteException; public void activitySlept(IBinder token) throws RemoteException; public void activityDestroyed(IBinder token) throws RemoteException; public String getCallingPackage(IBinder token) throws RemoteException; public ComponentName getCallingActivity(IBinder token) throws RemoteException; - public List<RunningTaskInfo> getTasks(int maxNum, int flags, - IThumbnailReceiver receiver) throws RemoteException; + public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException; + public int addAppTask(IBinder activityToken, Intent intent, + ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException; + public Point getAppTaskThumbnailSize() throws RemoteException; + public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException; public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) throws RemoteException; - public ActivityManager.TaskThumbnails getTaskThumbnails(int taskId) throws RemoteException; - public Bitmap getTaskTopThumbnail(int taskId) throws RemoteException; + public ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) throws RemoteException; public List<RunningServiceInfo> getServices(int maxNum, int flags) throws RemoteException; public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() throws RemoteException; @@ -122,11 +137,9 @@ public void resizeStack(int stackId, Rect bounds) throws RemoteException; public List<StackInfo> getAllStackInfos() throws RemoteException; public StackInfo getStackInfo(int stackId) throws RemoteException; + public boolean isInHomeStack(int taskId) throws RemoteException; public void setFocusedStack(int stackId) throws RemoteException; public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException; - /* oneway */ - public void reportThumbnail(IBinder token, - Bitmap thumbnail, CharSequence description) throws RemoteException; public ContentProviderHolder getContentProvider(IApplicationThread caller, String name, int userId, boolean stable) throws RemoteException; public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token) @@ -207,14 +220,16 @@ public int checkPermission(String permission, int pid, int uid) throws RemoteException; - public int checkUriPermission(Uri uri, int pid, int uid, int mode) + public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId) throws RemoteException; - public void grantUriPermission(IApplicationThread caller, String targetPkg, - Uri uri, int mode) throws RemoteException; - public void revokeUriPermission(IApplicationThread caller, Uri uri, - int mode) throws RemoteException; - public void takePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException; - public void releasePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException; + public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri, + int mode, int userId) throws RemoteException; + public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode, int userId) + throws RemoteException; + public void takePersistableUriPermission(Uri uri, int modeFlags, int userId) + throws RemoteException; + public void releasePersistableUriPermission(Uri uri, int modeFlags, int userId) + throws RemoteException; public ParceledListSlice<UriPermission> getPersistedUriPermissions( String packageName, boolean incoming) throws RemoteException; @@ -242,7 +257,8 @@ public void enterSafeMode() throws RemoteException; - public void noteWakeupAlarm(IIntentSender sender) throws RemoteException; + public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg) + throws RemoteException; public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException; public boolean killProcessesBelowForeground(String reason) throws RemoteException; @@ -250,7 +266,7 @@ // Special low-level communication with activity manager. public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException; - public boolean handleApplicationWtf(IBinder app, String tag, + public boolean handleApplicationWtf(IBinder app, String tag, boolean system, ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException; // A StrictMode violation to be handled. The violationMask is a @@ -277,16 +293,18 @@ throws RemoteException; // Get device configuration public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException; - + // Turn on/off profiling in a particular process. public boolean profileControl(String process, int userId, boolean start, - String path, ParcelFileDescriptor fd, int profileType) throws RemoteException; - + ProfilerInfo profilerInfo, int profileType) throws RemoteException; + public boolean shutdown(int timeout) throws RemoteException; - + public void stopAppSwitches() throws RemoteException; public void resumeAppSwitches() throws RemoteException; - + + public void addPackageDependency(String packageName) throws RemoteException; + public void killApplicationWithAppId(String pkg, int appid, String reason) throws RemoteException; @@ -294,10 +312,10 @@ public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) throws RemoteException; - + public void overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim) throws RemoteException; - + public boolean isUserAMonkey() throws RemoteException; public void setUserIsMonkey(boolean monkey) throws RemoteException; @@ -305,26 +323,30 @@ public void finishHeavyWeightApp() throws RemoteException; public boolean convertFromTranslucent(IBinder token) throws RemoteException; - public boolean convertToTranslucent(IBinder token) throws RemoteException; + public boolean convertToTranslucent(IBinder token, ActivityOptions options) throws RemoteException; public void notifyActivityDrawn(IBinder token) throws RemoteException; + public ActivityOptions getActivityOptions(IBinder token) throws RemoteException; + + public void bootAnimationComplete() throws RemoteException; public void setImmersive(IBinder token, boolean immersive) throws RemoteException; public boolean isImmersive(IBinder token) throws RemoteException; public boolean isTopActivityImmersive() throws RemoteException; - + public boolean isTopOfTask(IBinder token) throws RemoteException; + public void crashApplication(int uid, int initialPid, String packageName, String message) throws RemoteException; public String getProviderMimeType(Uri uri, int userId) throws RemoteException; - + public IBinder newUriPermissionOwner(String name) throws RemoteException; public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg, - Uri uri, int mode) throws RemoteException; + Uri uri, int mode, int sourceUserId, int targetUserId) throws RemoteException; public void revokeUriPermissionFromOwner(IBinder owner, Uri uri, - int mode) throws RemoteException; + int mode, int userId) throws RemoteException; - public int checkGrantUriPermission(int callingUid, String targetPkg, - Uri uri, int modeFlags) throws RemoteException; + public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri, + int modeFlags, int userId) throws RemoteException; // Cause the specified process to dump the specified heap. public boolean dumpHeap(String process, int userId, boolean managed, String path, @@ -345,13 +367,12 @@ // Multi-user APIs public boolean switchUser(int userid) throws RemoteException; + public boolean startUserInBackground(int userid) throws RemoteException; public int stopUser(int userid, IStopUserCallback callback) throws RemoteException; public UserInfo getCurrentUser() throws RemoteException; public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException; public int[] getRunningUserIds() throws RemoteException; - public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException; - public boolean removeTask(int taskId, int flags) throws RemoteException; public void registerProcessObserver(IProcessObserver observer) throws RemoteException; @@ -363,15 +384,17 @@ public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException; + public String getTagForIntentSender(IIntentSender sender, String prefix) throws RemoteException; + public void updatePersistentConfiguration(Configuration values) throws RemoteException; public long[] getProcessPss(int[] pids) throws RemoteException; public void showBootMessage(CharSequence msg, boolean always) throws RemoteException; - public void dismissKeyguardOnNextActivity() throws RemoteException; + public void keyguardWaitingForActivityDrawn() throws RemoteException; - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException; public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData) @@ -404,11 +427,9 @@ public void performIdleMaintenance() throws RemoteException; - /** @hide */ public IActivityContainer createActivityContainer(IBinder parentActivityToken, IActivityContainerCallback callback) throws RemoteException; - /** @hide */ public void deleteActivityContainer(IActivityContainer container) throws RemoteException; public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) @@ -416,11 +437,34 @@ public IBinder getHomeActivityToken() throws RemoteException; + public void startLockTaskModeOnCurrent() throws RemoteException; + + public void startLockTaskMode(int taskId) throws RemoteException; + + public void startLockTaskMode(IBinder token) throws RemoteException; + + public void stopLockTaskMode() throws RemoteException; + + public void stopLockTaskModeOnCurrent() throws RemoteException; + + public boolean isInLockTaskMode() throws RemoteException; + + public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values) + throws RemoteException; + public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException; + + public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException; + public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException; + public void backgroundResourcesReleased(IBinder token) throws RemoteException; + + public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException; + public void notifyEnterAnimationComplete(IBinder token) throws RemoteException; + /* * Private non-Binder interfaces */ /* package */ boolean testIsSystemReady(); - + /** Information you can retrieve about a particular application. */ public static class ContentProviderHolder implements Parcelable { public final ProviderInfo info; @@ -545,7 +589,7 @@ int MOVE_TASK_TO_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24; int MOVE_TASK_BACKWARDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25; int GET_TASK_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26; - int REPORT_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27; + int GET_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28; int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29; int REF_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30; @@ -597,7 +641,7 @@ int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78; int KILL_PIDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79; int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80; - int GET_TASK_THUMBNAILS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81; + int GET_TASK_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81; int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82; int GET_DEVICE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+83; int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84; @@ -610,7 +654,7 @@ int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91; int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92; int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93; - int GET_TASK_TOP_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94; + int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94; int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95; int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96; int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97; @@ -646,7 +690,7 @@ int GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127; int SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128; int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129; - int REMOVE_SUB_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+130; + int ___AVAILABLE_1___ = IBinder.FIRST_CALL_TRANSACTION+130; int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131; int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132; int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133; @@ -654,14 +698,13 @@ int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135; int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136; int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137; - int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138; int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139; int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140; int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141; int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142; int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143; int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144; - int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; + int SHOULD_UP_RECREATE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146; int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147; int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148; @@ -702,4 +745,36 @@ int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183; int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184; int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185; + + + // Start of L transactions + int GET_TAG_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+210; + int START_USER_IN_BACKGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+211; + int IS_IN_HOME_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+212; + int START_LOCK_TASK_BY_TASK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+213; + int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214; + int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215; + int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216; + int SET_TASK_DESCRIPTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217; + int START_VOICE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218; + int GET_ACTIVITY_OPTIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+219; + int GET_APP_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+220; + int START_LOCK_TASK_BY_CURRENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+221; + int STOP_LOCK_TASK_BY_CURRENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+222; + int FINISH_VOICE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+223; + int IS_TOP_OF_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+224; + int REQUEST_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+225; + int IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226; + int BACKGROUND_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227; + int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228; + int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229; + int NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+230; + int KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+231; + int START_ACTIVITY_AS_CALLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+232; + int ADD_APP_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+233; + int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234; + int RELEASE_ACTIVITY_INSTANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+235; + int RELEASE_SOME_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+236; + int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237; + int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238; }
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl index ef9f26e..194082e 100644 --- a/core/java/android/app/IAlarmManager.aidl +++ b/core/java/android/app/IAlarmManager.aidl
@@ -16,6 +16,7 @@ */ package android.app; +import android.app.AlarmManager; import android.app.PendingIntent; import android.os.WorkSource; @@ -27,10 +28,12 @@ interface IAlarmManager { /** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */ void set(int type, long triggerAtTime, long windowLength, - long interval, in PendingIntent operation, in WorkSource workSource); + long interval, in PendingIntent operation, in WorkSource workSource, + in AlarmManager.AlarmClockInfo alarmClock); boolean setTime(long millis); void setTimeZone(String zone); void remove(in PendingIntent operation); + AlarmManager.AlarmClockInfo getNextAlarmClock(int userId); }
diff --git a/core/java/android/app/IAppTask.aidl b/core/java/android/app/IAppTask.aidl new file mode 100644 index 0000000..37fead9 --- /dev/null +++ b/core/java/android/app/IAppTask.aidl
@@ -0,0 +1,31 @@ +/** + * Copyright (c) 2014, 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; + +import android.app.ActivityManager; +import android.content.Intent; +import android.os.Bundle; + +/** @hide */ +interface IAppTask { + void finishAndRemoveTask(); + ActivityManager.RecentTaskInfo getTaskInfo(); + void moveToFront(); + int startActivity(IBinder whoThread, String callingPackage, + in Intent intent, String resolvedType, in Bundle options); + void setExcludeFromRecents(boolean exclude); +}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 3aceff9..f53075c 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java
@@ -25,12 +25,16 @@ import android.content.pm.ServiceInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.net.Uri; import android.os.Bundle; import android.os.Debug; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.IBinder; import android.os.IInterface; +import android.service.voice.IVoiceInteractionSession; +import com.android.internal.app.IVoiceInteractor; import java.io.FileDescriptor; import java.util.List; @@ -45,20 +49,20 @@ */ public interface IApplicationThread extends IInterface { void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, - int configChanges) throws RemoteException; + int configChanges, boolean dontReport) throws RemoteException; void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException; void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException; void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException; - void scheduleResumeActivity(IBinder token, int procState, boolean isForward) + void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs) throws RemoteException; void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException; void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, - int procState, Bundle state, List<ResultInfo> pendingResults, - List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) - throws RemoteException; + IVoiceInteractor voiceInteractor, int procState, Bundle state, + PersistableBundle persistentState, List<ResultInfo> pendingResults, + List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, + ProfilerInfo profilerInfo) throws RemoteException; void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config) throws RemoteException; @@ -89,20 +93,18 @@ static final int DEBUG_ON = 1; static final int DEBUG_WAIT = 2; void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers, - ComponentName testName, String profileName, ParcelFileDescriptor profileFd, - boolean autoStopProfiler, Bundle testArguments, IInstrumentationWatcher testWatcher, - IUiAutomationConnection uiAutomationConnection, int debugMode, - boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, + ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments, + IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, + int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) throws RemoteException; void scheduleExit() throws RemoteException; void scheduleSuicide() throws RemoteException; - void requestThumbnail(IBinder token) throws RemoteException; void scheduleConfigurationChanged(Configuration config) throws RemoteException; void updateTimeZone() throws RemoteException; void clearDnsCache() throws RemoteException; void setHttpProxy(String proxy, String port, String exclList, - String pacFileUrl) throws RemoteException; + Uri pacFileUrl) throws RemoteException; void processInBackground() throws RemoteException; void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) throws RemoteException; @@ -113,7 +115,7 @@ boolean sticky, int sendingUser, int processState) throws RemoteException; void scheduleLowMemory() throws RemoteException; void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException; - void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType) + void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) throws RemoteException; void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException; @@ -136,9 +138,14 @@ throws RemoteException; void scheduleTranslucentConversionComplete(IBinder token, boolean timeout) throws RemoteException; + void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options) + throws RemoteException; void setProcessState(int state) throws RemoteException; void scheduleInstallProvider(ProviderInfo provider) throws RemoteException; void updateTimePrefs(boolean is24Hour) throws RemoteException; + void scheduleCancelVisibleBehind(IBinder token) throws RemoteException; + void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled) throws RemoteException; + void scheduleEnterAnimationComplete(IBinder token) throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -155,7 +162,7 @@ int SCHEDULE_STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+11; int BIND_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+12; int SCHEDULE_EXIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+13; - int REQUEST_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+14; + int SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+15; int SCHEDULE_SERVICE_ARGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+16; int UPDATE_TIME_ZONE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+17; @@ -172,7 +179,7 @@ int SET_SCHEDULING_GROUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28; int SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29; int SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30; - + int SCHEDULE_ON_NEW_ACTIVITY_OPTIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31; int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32; int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33; int SCHEDULE_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34; @@ -193,4 +200,7 @@ int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49; int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50; int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51; + int CANCEL_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+52; + int BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53; + int ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54; }
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl index 087f83c..451af99 100644 --- a/core/java/android/app/IBackupAgent.aidl +++ b/core/java/android/app/IBackupAgent.aidl
@@ -76,8 +76,9 @@ * @param callbackBinder Binder on which to indicate operation completion, * passed here as a convenience to the agent. */ - void doRestore(in ParcelFileDescriptor data, int appVersionCode, - in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder); + void doRestore(in ParcelFileDescriptor data, + int appVersionCode, in ParcelFileDescriptor newState, + int token, IBackupManager callbackBinder); /** * Perform a "full" backup to the given file descriptor. The output file is presumed @@ -112,8 +113,38 @@ * @param path Relative path of the file within its semantic domain. * @param mode Access mode of the file system entity, e.g. 0660. * @param mtime Last modification time of the file system entity. + * @param token Opaque token identifying this transaction. This must + * be echoed back to the backup service binder once the agent is + * finished restoring the application based on the restore data + * contents. + * @param callbackBinder Binder on which to indicate operation completion, + * passed here as a convenience to the agent. */ void doRestoreFile(in ParcelFileDescriptor data, long size, int type, String domain, String path, long mode, long mtime, int token, IBackupManager callbackBinder); + + /** + * Provide the app with a canonical "all data has been delivered" end-of-restore + * callback so that it can do any postprocessing of the restored data that might + * be appropriate. This is issued after both key/value and full data restore + * operations have completed. + * + * @param token Opaque token identifying this transaction. This must + * be echoed back to the backup service binder once the agent is + * finished restoring the application based on the restore data + * contents. + * @param callbackBinder Binder on which to indicate operation completion, + * passed here as a convenience to the agent. + */ + void doRestoreFinished(int token, IBackupManager callbackBinder); + + /** + * Out of band: instruct the agent to crash within the client process. This is used + * when the backup infrastructure detects a semantic error post-hoc and needs to + * pass the problem back to the app. + * + * @param message The message to be passed to the agent's application in an exception. + */ + void fail(String message); }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 9911467..bdcff38 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl
@@ -18,11 +18,18 @@ package android.app; import android.app.ITransientNotification; -import android.service.notification.StatusBarNotification; import android.app.Notification; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.ParceledListSlice; +import android.net.Uri; +import android.os.Bundle; +import android.service.notification.Condition; +import android.service.notification.IConditionListener; +import android.service.notification.IConditionProvider; import android.service.notification.INotificationListener; +import android.service.notification.StatusBarNotification; +import android.service.notification.ZenModeConfig; /** {@hide} */ interface INotificationManager @@ -31,13 +38,21 @@ void enqueueToast(String pkg, ITransientNotification callback, int duration); void cancelToast(String pkg, ITransientNotification callback); - void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id, + void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id, in Notification notification, inout int[] idReceived, int userId); void cancelNotificationWithTag(String pkg, String tag, int id, int userId); void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled); boolean areNotificationsEnabledForPackage(String pkg, int uid); + void setPackagePriority(String pkg, int uid, int priority); + int getPackagePriority(String pkg, int uid); + + void setPackageVisibilityOverride(String pkg, int uid, int visibility); + int getPackageVisibilityOverride(String pkg, int uid); + + // TODO: Remove this when callers have been migrated to the equivalent + // INotificationListener method. StatusBarNotification[] getActiveNotifications(String callingPkg); StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count); @@ -47,6 +62,21 @@ void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id); void cancelNotificationsFromListener(in INotificationListener token, in String[] keys); - StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys); - String[] getActiveNotificationKeysFromListener(in INotificationListener token); -} \ No newline at end of file + ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys, int trim); + void requestHintsFromListener(in INotificationListener token, int hints); + int getHintsFromListener(in INotificationListener token); + void requestInterruptionFilterFromListener(in INotificationListener token, int interruptionFilter); + int getInterruptionFilterFromListener(in INotificationListener token); + void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim); + + ComponentName getEffectsSuppressor(); + boolean matchesCallFilter(in Bundle extras); + + ZenModeConfig getZenModeConfig(); + boolean setZenModeConfig(in ZenModeConfig config); + oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions); + oneway void requestZenModeConditions(in IConditionListener callback, int relevance); + oneway void setZenModeCondition(in Condition condition); + oneway void setAutomaticZenModeConditions(in Uri[] conditionIds); + Condition[] getAutomaticZenModeConditions(); +}
diff --git a/core/java/android/app/IProcessObserver.aidl b/core/java/android/app/IProcessObserver.aidl index e587912..ecf2c73 100644 --- a/core/java/android/app/IProcessObserver.aidl +++ b/core/java/android/app/IProcessObserver.aidl
@@ -20,7 +20,7 @@ oneway interface IProcessObserver { void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities); - void onImportanceChanged(int pid, int uid, int importance); + void onProcessStateChanged(int pid, int uid, int procState); void onProcessDied(int pid, int uid); }
diff --git a/core/java/android/app/IThumbnailReceiver.aidl b/core/java/android/app/IThumbnailReceiver.aidl deleted file mode 100644 index 7943f2c..0000000 --- a/core/java/android/app/IThumbnailReceiver.aidl +++ /dev/null
@@ -1,30 +0,0 @@ -/* //device/java/android/android/app/IThumbnailReceiver.aidl -** -** Copyright 2006, 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; - -import android.graphics.Bitmap; - -/** - * System private API for receiving updated thumbnails from a checkpoint. - * - * {@hide} - */ -oneway interface IThumbnailReceiver { - void newThumbnail(int id, in Bitmap thumbnail, CharSequence description); - void finished(); -} -
diff --git a/core/java/android/app/IThumbnailRetriever.aidl b/core/java/android/app/IThumbnailRetriever.aidl deleted file mode 100644 index 410cc20..0000000 --- a/core/java/android/app/IThumbnailRetriever.aidl +++ /dev/null
@@ -1,25 +0,0 @@ -/* Copyright 2011, 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; - -import android.graphics.Bitmap; - -/** - * System private API for retrieving thumbnails - * {@hide} - */ -interface IThumbnailRetriever { - Bitmap getThumbnail(int index); -}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index 09bf829..8ab9ac3 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -19,6 +19,8 @@ import android.accessibilityservice.IAccessibilityServiceClient; import android.graphics.Bitmap; import android.view.InputEvent; +import android.view.WindowContentFrameStats; +import android.view.WindowAnimationFrameStats; import android.os.ParcelFileDescriptor; /** @@ -26,7 +28,7 @@ * on behalf of an instrumentation that it runs. These operations require * special permissions which the shell user has but the instrumentation does * not. Running privileged operations by the shell user on behalf of an - * instrumentation is needed for running UiTestCases. + * instrumentation is needed for running UiTestCases. * * {@hide} */ @@ -37,4 +39,9 @@ boolean setRotation(int rotation); Bitmap takeScreenshot(int width, int height); void shutdown(); + boolean clearWindowContentFrameStats(int windowId); + WindowContentFrameStats getWindowContentFrameStats(int windowId); + void clearWindowAnimationFrameStats(); + WindowAnimationFrameStats getWindowAnimationFrameStats(); + void executeShellCommand(String command, in ParcelFileDescriptor fd); }
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 181eb63..3b5900b 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl
@@ -16,6 +16,7 @@ package android.app; +import android.graphics.Rect; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.app.IWallpaperManagerCallback; @@ -73,6 +74,11 @@ int getHeightHint(); /** + * Sets extra padding that we would like the wallpaper to have outside of the display. + */ + void setDisplayPadding(in Rect padding); + + /** * Returns the name of the wallpaper. Private API. */ String getName();
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 028fa68..ba3a234 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java
@@ -30,6 +30,7 @@ import android.os.Looper; import android.os.MessageQueue; import android.os.PerformanceCollector; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -187,6 +188,9 @@ endPerformanceSnapshot(); } if (mPerfMetrics != null) { + if (results == null) { + results = new Bundle(); + } results.putAll(mPerfMetrics); } if (mUiAutomation != null) { @@ -1035,10 +1039,10 @@ IllegalAccessException { Activity activity = (Activity)clazz.newInstance(); ActivityThread aThread = null; - activity.attach(context, aThread, this, token, application, intent, + activity.attach(context, aThread, this, token, 0, application, intent, info, title, parent, id, (Activity.NonConfigurationInstances)lastNonConfigurationInstance, - new Configuration()); + new Configuration(), null); return activity; } @@ -1061,15 +1065,7 @@ return (Activity)cl.loadClass(className).newInstance(); } - /** - * Perform calling of an activity's {@link Activity#onCreate} - * method. The default implementation simply calls through to that method. - * - * @param activity The activity being created. - * @param icicle The previously frozen state (or null) to pass through to - * onCreate(). - */ - public void callActivityOnCreate(Activity activity, Bundle icicle) { + private void prePerformCreate(Activity activity) { if (mWaitingActivities != null) { synchronized (mSync) { final int N = mWaitingActivities.size(); @@ -1083,9 +1079,9 @@ } } } - - activity.performCreate(icicle); - + } + + private void postPerformCreate(Activity activity) { if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); @@ -1096,6 +1092,33 @@ } } } + + /** + * Perform calling of an activity's {@link Activity#onCreate} + * method. The default implementation simply calls through to that method. + * + * @param activity The activity being created. + * @param icicle The previously frozen state (or null) to pass through to onCreate(). + */ + public void callActivityOnCreate(Activity activity, Bundle icicle) { + prePerformCreate(activity); + activity.performCreate(icicle); + postPerformCreate(activity); + } + + /** + * Perform calling of an activity's {@link Activity#onCreate} + * method. The default implementation simply calls through to that method. + * @param activity The activity being created. + * @param icicle The previously frozen state (or null) to pass through to + * @param persistentState The previously persisted state (or null) + */ + public void callActivityOnCreate(Activity activity, Bundle icicle, + PersistableBundle persistentState) { + prePerformCreate(activity); + activity.performCreate(icicle, persistentState); + postPerformCreate(activity); + } public void callActivityOnDestroy(Activity activity) { // TODO: the following block causes intermittent hangs when using startActivity @@ -1130,7 +1153,7 @@ /** * Perform calling of an activity's {@link Activity#onRestoreInstanceState} * method. The default implementation simply calls through to that method. - * + * * @param activity The activity being restored. * @param savedInstanceState The previously saved state being restored. */ @@ -1139,9 +1162,22 @@ } /** + * Perform calling of an activity's {@link Activity#onRestoreInstanceState} + * method. The default implementation simply calls through to that method. + * + * @param activity The activity being restored. + * @param savedInstanceState The previously saved state being restored. + * @param persistentState The previously persisted state (or null) + */ + public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState, + PersistableBundle persistentState) { + activity.performRestoreInstanceState(savedInstanceState, persistentState); + } + + /** * Perform calling of an activity's {@link Activity#onPostCreate} method. * The default implementation simply calls through to that method. - * + * * @param activity The activity being created. * @param icicle The previously frozen state (or null) to pass through to * onPostCreate(). @@ -1151,6 +1187,19 @@ } /** + * Perform calling of an activity's {@link Activity#onPostCreate} method. + * The default implementation simply calls through to that method. + * + * @param activity The activity being created. + * @param icicle The previously frozen state (or null) to pass through to + * onPostCreate(). + */ + public void callActivityOnPostCreate(Activity activity, Bundle icicle, + PersistableBundle persistentState) { + activity.onPostCreate(icicle, persistentState); + } + + /** * Perform calling of an activity's {@link Activity#onNewIntent} * method. The default implementation simply calls through to that method. * @@ -1215,7 +1264,7 @@ /** * Perform calling of an activity's {@link Activity#onSaveInstanceState} * method. The default implementation simply calls through to that method. - * + * * @param activity The activity being saved. * @param outState The bundle to pass to the call. */ @@ -1224,6 +1273,18 @@ } /** + * Perform calling of an activity's {@link Activity#onSaveInstanceState} + * method. The default implementation simply calls through to that method. + * @param activity The activity being saved. + * @param outState The bundle to pass to the call. + * @param outPersistentState The persistent bundle to pass to the call. + */ + public void callActivityOnSaveInstanceState(Activity activity, Bundle outState, + PersistableBundle outPersistentState) { + activity.performSaveInstanceState(outState, outPersistentState); + } + + /** * Perform calling of an activity's {@link Activity#onPause} method. The * default implementation simply calls through to that method. * @@ -1420,7 +1481,7 @@ .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, null, options); + requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } @@ -1428,7 +1489,7 @@ } /** - * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)}, + * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, * but accepts an array of activities to be started. Note that active * {@link ActivityMonitor} objects only match against the first activity in * the array. @@ -1442,7 +1503,7 @@ } /** - * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)}, + * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, * but accepts an array of activities to be started. Note that active * {@link ActivityMonitor} objects only match against the first activity in * the array. @@ -1537,7 +1598,7 @@ .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mWho : null, - requestCode, 0, null, null, options); + requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } @@ -1545,7 +1606,7 @@ } /** - * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)}, + * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, * but for starting as a particular user. * * @param who The Context from which the activity is being started. @@ -1597,13 +1658,84 @@ .startActivityAsUser(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, null, options, user.getIdentifier()); + requestCode, 0, null, options, user.getIdentifier()); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; } + /** + * Special version! + * @hide + */ + public ActivityResult execStartActivityAsCaller( + Context who, IBinder contextThread, IBinder token, Activity target, + Intent intent, int requestCode, Bundle options) { + IApplicationThread whoThread = (IApplicationThread) contextThread; + if (mActivityMonitors != null) { + synchronized (mSync) { + final int N = mActivityMonitors.size(); + for (int i=0; i<N; i++) { + final ActivityMonitor am = mActivityMonitors.get(i); + if (am.match(who, null, intent)) { + am.mHits++; + if (am.isBlocking()) { + return requestCode >= 0 ? am.getResult() : null; + } + break; + } + } + } + } + try { + intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); + int result = ActivityManagerNative.getDefault() + .startActivityAsCaller(whoThread, who.getBasePackageName(), intent, + intent.resolveTypeIfNeeded(who.getContentResolver()), + token, target != null ? target.mEmbeddedID : null, + requestCode, 0, null, options); + checkStartActivityResult(result, intent); + } catch (RemoteException e) { + } + return null; + } + + /** + * Special version! + * @hide + */ + public void execStartActivityFromAppTask( + Context who, IBinder contextThread, IAppTask appTask, + Intent intent, Bundle options) { + IApplicationThread whoThread = (IApplicationThread) contextThread; + if (mActivityMonitors != null) { + synchronized (mSync) { + final int N = mActivityMonitors.size(); + for (int i=0; i<N; i++) { + final ActivityMonitor am = mActivityMonitors.get(i); + if (am.match(who, null, intent)) { + am.mHits++; + if (am.isBlocking()) { + return; + } + break; + } + } + } + } + try { + intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); + int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(), + intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options); + checkStartActivityResult(result, intent); + } catch (RemoteException e) { + } + return; + } + /*package*/ final void init(ActivityThread thread, Context instrContext, Context appContext, ComponentName component, IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) { @@ -1616,7 +1748,8 @@ mUiAutomationConnection = uiAutomationConnection; } - /*package*/ static void checkStartActivityResult(int res, Object intent) { + /** @hide */ + public static void checkStartActivityResult(int res, Object intent) { if (res >= ActivityManager.START_SUCCESS) { return; } @@ -1640,6 +1773,9 @@ case ActivityManager.START_NOT_ACTIVITY: throw new IllegalArgumentException( "PendingIntent is not an activity"); + case ActivityManager.START_NOT_VOICE_COMPATIBLE: + throw new SecurityException( + "Starting under voice control not allowed for: " + intent); default: throw new AndroidRuntimeException("Unknown error code " + res + " when starting " + intent);
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java new file mode 100644 index 0000000..09038d5 --- /dev/null +++ b/core/java/android/app/JobSchedulerImpl.java
@@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 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. + */ + +// in android.app so ContextImpl has package access +package android.app; + +import android.app.job.JobInfo; +import android.app.job.JobScheduler; +import android.app.job.IJobScheduler; +import android.os.RemoteException; + +import java.util.List; + + +/** + * Concrete implementation of the JobScheduler interface + * @hide + */ +public class JobSchedulerImpl extends JobScheduler { + IJobScheduler mBinder; + + /* package */ JobSchedulerImpl(IJobScheduler binder) { + mBinder = binder; + } + + @Override + public int schedule(JobInfo job) { + try { + return mBinder.schedule(job); + } catch (RemoteException e) { + return JobScheduler.RESULT_FAILURE; + } + } + + @Override + public void cancel(int jobId) { + try { + mBinder.cancel(jobId); + } catch (RemoteException e) {} + + } + + @Override + public void cancelAll() { + try { + mBinder.cancelAll(); + } catch (RemoteException e) {} + + } + + @Override + public List<JobInfo> getAllPendingJobs() { + try { + return mBinder.getAllPendingJobs(); + } catch (RemoteException e) { + return null; + } + } +}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index aab6ed8..cc9aed8 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java
@@ -16,6 +16,7 @@ package android.app; +import android.content.Intent; import android.os.Binder; import android.os.RemoteException; import android.os.IBinder; @@ -24,7 +25,7 @@ import android.view.WindowManagerGlobal; /** - * Class that can be used to lock and unlock the keyboard. Get an instance of this + * Class that can be used to lock and unlock the keyboard. Get an instance of this * class by calling {@link android.content.Context#getSystemService(java.lang.String)} * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The * actual class to control the keyboard locking is @@ -34,6 +35,45 @@ private IWindowManager mWM; /** + * Intent used to prompt user for device credentials. + * @hide + */ + public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL = + "android.app.action.CONFIRM_DEVICE_CREDENTIAL"; + + /** + * A CharSequence dialog title to show to the user when used with a + * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. + * @hide + */ + public static final String EXTRA_TITLE = "android.app.extra.TITLE"; + + /** + * A CharSequence description to show to the user when used with + * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. + * @hide + */ + public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION"; + + /** + * Get an intent to prompt the user to confirm credentials (pin, pattern or password) + * for the current user of the device. The caller is expected to launch this activity using + * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for + * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. + * + * @return the intent for launching the activity or null if no password is required. + **/ + public Intent createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) { + if (!isKeyguardSecure()) return null; + Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL); + intent.putExtra(EXTRA_TITLE, title); + intent.putExtra(EXTRA_DESCRIPTION, description); + // For security reasons, only allow this to come from system settings. + intent.setPackage("com.android.settings"); + return intent; + } + + /** * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD} * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} * instead; this allows you to seamlessly hide the keyguard as your application @@ -44,8 +84,8 @@ * you to disable / reenable the keyguard. */ public class KeyguardLock { - private IBinder mToken = new Binder(); - private String mTag; + private final IBinder mToken = new Binder(); + private final String mTag; KeyguardLock(String tag) { mTag = tag; @@ -58,7 +98,7 @@ * * A good place to call this is from {@link android.app.Activity#onResume()} * - * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} + * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} * is enabled that requires a password. * * <p>This method requires the caller to hold the permission @@ -121,7 +161,7 @@ * permissions be requested. * * Enables you to lock or unlock the keyboard. Get an instance of this class by - * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. + * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}. * @param tag A tag that informally identifies who you are (for debugging who * is disabling he keyguard).
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index d409352..d143b86 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java
@@ -16,8 +16,8 @@ package android.app; +import android.text.TextUtils; import android.util.ArrayMap; -import com.android.internal.util.ArrayUtils; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -40,16 +40,24 @@ import android.os.Trace; import android.os.UserHandle; import android.util.AndroidRuntimeException; +import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import android.view.DisplayAdjustments; import android.view.Display; +import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; +import java.util.Objects; final class IntentReceiverLeaked extends AndroidRuntimeException { public IntentReceiverLeaked(String msg) { @@ -76,6 +84,8 @@ final String mPackageName; private final String mAppDir; private final String mResDir; + private final String[] mSplitAppDirs; + private final String[] mSplitResDirs; private final String[] mOverlayDirs; private final String[] mSharedLibraries; private final String mDataDir; @@ -84,6 +94,7 @@ private final ClassLoader mBaseClassLoader; private final boolean mSecurityViolation; private final boolean mIncludeCode; + private final boolean mRegisterPackage; private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments(); Resources mResources; private ClassLoader mClassLoader; @@ -112,14 +123,17 @@ */ public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, - boolean securityViolation, boolean includeCode) { + boolean securityViolation, boolean includeCode, boolean registerPackage) { + final int myUid = Process.myUid(); + aInfo = adjustNativeLibraryPaths(aInfo); + mActivityThread = activityThread; mApplicationInfo = aInfo; mPackageName = aInfo.packageName; mAppDir = aInfo.sourceDir; - final int myUid = Process.myUid(); - mResDir = aInfo.uid == myUid ? aInfo.sourceDir - : aInfo.publicSourceDir; + mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir; + mSplitAppDirs = aInfo.splitSourceDirs; + mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs; mOverlayDirs = aInfo.resourceDirs; if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) { aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid), @@ -132,9 +146,31 @@ mBaseClassLoader = baseLoader; mSecurityViolation = securityViolation; mIncludeCode = includeCode; + mRegisterPackage = registerPackage; mDisplayAdjustments.setCompatibilityInfo(compatInfo); } + private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) { + // If we're dealing with a multi-arch application that has both + // 32 and 64 bit shared libraries, we might need to choose the secondary + // depending on what the current runtime's instruction set is. + if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) { + final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet(); + final String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi); + + // If the runtimeIsa is the same as the primary isa, then we do nothing. + // Everything will be set up correctly because info.nativeLibraryDir will + // correspond to the right ISA. + if (runtimeIsa.equals(secondaryIsa)) { + final ApplicationInfo modified = new ApplicationInfo(info); + modified.nativeLibraryDir = modified.secondaryNativeLibraryDir; + return modified; + } + } + + return info; + } + /** * Create information about the system package. * Must call {@link #installSystemApplicationInfo} later. @@ -146,6 +182,8 @@ mPackageName = "android"; mAppDir = null; mResDir = null; + mSplitAppDirs = null; + mSplitResDirs = null; mOverlayDirs = null; mSharedLibraries = null; mDataDir = null; @@ -154,6 +192,7 @@ mBaseClassLoader = null; mSecurityViolation = false; mIncludeCode = true; + mRegisterPackage = false; mClassLoader = ClassLoader.getSystemClassLoader(); mResources = Resources.getSystem(); } @@ -161,9 +200,10 @@ /** * Sets application info about the system package. */ - void installSystemApplicationInfo(ApplicationInfo info) { + void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { assert info.packageName.equals("android"); mApplicationInfo = info; + mClassLoader = classLoader; } public String getPackageName() { @@ -211,53 +251,6 @@ return ai.sharedLibraryFiles; } - /** - * Combines two arrays (of library names) such that they are - * concatenated in order but are devoid of duplicates. The - * result is a single string with the names of the libraries - * separated by colons, or <code>null</code> if both lists - * were <code>null</code> or empty. - * - * @param list1 null-ok; the first list - * @param list2 null-ok; the second list - * @return null-ok; the combination - */ - private static String combineLibs(String[] list1, String[] list2) { - StringBuilder result = new StringBuilder(300); - boolean first = true; - - if (list1 != null) { - for (String s : list1) { - if (first) { - first = false; - } else { - result.append(':'); - } - result.append(s); - } - } - - // Only need to check for duplicates if list1 was non-empty. - boolean dupCheck = !first; - - if (list2 != null) { - for (String s : list2) { - if (dupCheck && ArrayUtils.contains(list1, s)) { - continue; - } - - if (first) { - first = false; - } else { - result.append(':'); - } - result.append(s); - } - } - - return result.toString(); - } - public ClassLoader getClassLoader() { synchronized (this) { if (mClassLoader != null) { @@ -265,8 +258,34 @@ } if (mIncludeCode && !mPackageName.equals("android")) { - String zip = mAppDir; - String libraryPath = mLibDir; + // Avoid the binder call when the package is the current application package. + // The activity manager will perform ensure that dexopt is performed before + // spinning up the process. + if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) { + final String isa = VMRuntime.getRuntime().vmInstructionSet(); + try { + ActivityThread.getPackageManager().performDexOptIfNeeded(mPackageName, isa); + } catch (RemoteException re) { + // Ignored. + } + } + + final ArrayList<String> zipPaths = new ArrayList<>(); + final ArrayList<String> libPaths = new ArrayList<>(); + + if (mRegisterPackage) { + try { + ActivityManagerNative.getDefault().addPackageDependency(mPackageName); + } catch (RemoteException e) { + } + } + + zipPaths.add(mAppDir); + if (mSplitAppDirs != null) { + Collections.addAll(zipPaths, mSplitAppDirs); + } + + libPaths.add(mLibDir); /* * The following is a bit of a hack to inject @@ -277,50 +296,70 @@ * concatenation of both apps' shared library lists. */ - String instrumentationAppDir = - mActivityThread.mInstrumentationAppDir; - String instrumentationAppLibraryDir = - mActivityThread.mInstrumentationAppLibraryDir; - String instrumentationAppPackage = - mActivityThread.mInstrumentationAppPackage; - String instrumentedAppDir = - mActivityThread.mInstrumentedAppDir; - String instrumentedAppLibraryDir = - mActivityThread.mInstrumentedAppLibraryDir; + String instrumentationPackageName = mActivityThread.mInstrumentationPackageName; + String instrumentationAppDir = mActivityThread.mInstrumentationAppDir; + String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs; + String instrumentationLibDir = mActivityThread.mInstrumentationLibDir; + + String instrumentedAppDir = mActivityThread.mInstrumentedAppDir; + String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs; + String instrumentedLibDir = mActivityThread.mInstrumentedLibDir; String[] instrumentationLibs = null; if (mAppDir.equals(instrumentationAppDir) || mAppDir.equals(instrumentedAppDir)) { - zip = instrumentationAppDir + ":" + instrumentedAppDir; - libraryPath = instrumentationAppLibraryDir + ":" + instrumentedAppLibraryDir; - if (! instrumentedAppDir.equals(instrumentationAppDir)) { - instrumentationLibs = - getLibrariesFor(instrumentationAppPackage); + zipPaths.clear(); + zipPaths.add(instrumentationAppDir); + if (instrumentationSplitAppDirs != null) { + Collections.addAll(zipPaths, instrumentationSplitAppDirs); + } + zipPaths.add(instrumentedAppDir); + if (instrumentedSplitAppDirs != null) { + Collections.addAll(zipPaths, instrumentedSplitAppDirs); + } + + libPaths.clear(); + libPaths.add(instrumentationLibDir); + libPaths.add(instrumentedLibDir); + + if (!instrumentedAppDir.equals(instrumentationAppDir)) { + instrumentationLibs = getLibrariesFor(instrumentationPackageName); } } - if ((mSharedLibraries != null) || - (instrumentationLibs != null)) { - zip = - combineLibs(mSharedLibraries, instrumentationLibs) - + ':' + zip; + if (mSharedLibraries != null) { + for (String lib : mSharedLibraries) { + if (!zipPaths.contains(lib)) { + zipPaths.add(0, lib); + } + } } + if (instrumentationLibs != null) { + for (String lib : instrumentationLibs) { + if (!zipPaths.contains(lib)) { + zipPaths.add(0, lib); + } + } + } + + final String zip = TextUtils.join(File.pathSeparator, zipPaths); + final String lib = TextUtils.join(File.pathSeparator, libPaths); + /* * With all the combination done (if necessary, actually * create the class loader. */ if (ActivityThread.localLOGV) - Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + libraryPath); + Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + lib); // Temporarily disable logging of disk reads on the Looper thread // as this is early and necessary. StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - mClassLoader = - ApplicationLoaders.getDefault().getClassLoader( - zip, libraryPath, mBaseClassLoader); + mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib, + mBaseClassLoader); initializeJavaContextClassLoader(); StrictMode.setThreadPolicy(oldPolicy); @@ -466,6 +505,14 @@ return mResDir; } + public String[] getSplitAppDirs() { + return mSplitAppDirs; + } + + public String[] getSplitResDirs() { + return mSplitResDirs; + } + public String[] getOverlayDirs() { return mOverlayDirs; } @@ -484,8 +531,8 @@ public Resources getResources(ActivityThread mainThread) { if (mResources == null) { - mResources = mainThread.getTopLevelResources(mResDir, mOverlayDirs, - Display.DEFAULT_DISPLAY, null, this); + mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs, + mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this); } return mResources; } @@ -530,10 +577,56 @@ } } } - + + // Rewrite the R 'constants' for all library apks. + SparseArray<String> packageIdentifiers = getAssets(mActivityThread) + .getAssignedPackageIdentifiers(); + final int N = packageIdentifiers.size(); + for (int i = 0; i < N; i++) { + final int id = packageIdentifiers.keyAt(i); + if (id == 0x01 || id == 0x7f) { + continue; + } + + rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id); + } + return app; } + private void rewriteRValues(ClassLoader cl, String packageName, int id) { + final Class<?> rClazz; + try { + rClazz = cl.loadClass(packageName + ".R"); + } catch (ClassNotFoundException e) { + // This is not necessarily an error, as some packages do not ship with resources + // (or they do not need rewriting). + Log.i(TAG, "No resource references to update in package " + packageName); + return; + } + + final Method callback; + try { + callback = rClazz.getMethod("onResourcesLoaded", int.class); + } catch (NoSuchMethodException e) { + // No rewriting to be done. + return; + } + + Throwable cause; + try { + callback.invoke(null, id); + return; + } catch (IllegalAccessException e) { + cause = e; + } catch (InvocationTargetException e) { + cause = e.getCause(); + } + + throw new RuntimeException("Failed to rewrite resource references for " + packageName, + cause); + } + public void removeContextRegistrations(Context context, String who, String what) { final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java index a7982f4..fa2813e 100644 --- a/core/java/android/app/MediaRouteButton.java +++ b/core/java/android/app/MediaRouteButton.java
@@ -73,13 +73,18 @@ } public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); + this(context, attrs, defStyleAttr, 0); + } + + public MediaRouteButton( + Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE); mCallback = new MediaRouterCallback(); - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0); + final TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, defStyleRes); setRemoteIndicatorDrawable(a.getDrawable( com.android.internal.R.styleable.MediaRouteButton_externalRouteEnabledDrawable)); mMinWidth = a.getDimensionPixelSize(
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index d51c397..4b3aefe 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java
@@ -16,13 +16,23 @@ package android.app; +import android.annotation.IntDef; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.media.AudioAttributes; import android.media.AudioManager; +import android.media.session.MediaSession; import android.net.Uri; import android.os.BadParcelableException; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -30,6 +40,7 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; +import android.util.MathUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -37,7 +48,11 @@ import android.widget.RemoteViews; import com.android.internal.R; +import com.android.internal.util.NotificationColorUtil; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Constructor; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; @@ -63,6 +78,15 @@ private static final String TAG = "Notification"; /** + * An activity that provides a user interface for adjusting notification preferences for its + * containing application. Optional but recommended for apps that post + * {@link android.app.Notification Notifications}. + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String INTENT_CATEGORY_NOTIFICATION_PREFERENCES + = "android.intent.category.NOTIFICATION_PREFERENCES"; + + /** * Use all default values (where applicable). */ public static final int DEFAULT_ALL = ~0; @@ -71,7 +95,10 @@ * Use the default notification sound. This will ignore any given * {@link #sound}. * - + * <p> + * A notification that is noisy is more likely to be presented as a heads-up notification. + * </p> + * * @see #defaults */ @@ -82,6 +109,10 @@ * {@link #vibrate}. Using phone vibration requires the * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. * + * <p> + * A notification that vibrates is more likely to be presented as a heads-up notification. + * </p> + * * @see #defaults */ @@ -98,6 +129,14 @@ public static final int DEFAULT_LIGHTS = 4; /** + * Maximum length of CharSequences accepted by Builder and friends. + * + * <p> + * Avoids spamming the system with overly large strings such as full e-mails. + */ + private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024; + + /** * A timestamp related to this notification, in milliseconds since the epoch. * * Default value: {@link System#currentTimeMillis() Now}. @@ -175,22 +214,32 @@ /** * An intent to launch instead of posting the notification to the status bar. * + * <p> + * The system UI may choose to display a heads-up notification, instead of + * launching this intent, while the user is using the device. + * </p> + * * @see Notification.Builder#setFullScreenIntent */ public PendingIntent fullScreenIntent; /** - * Text to scroll across the screen when this item is added to - * the status bar on large and smaller devices. + * Text that summarizes this notification for accessibility services. + * + * As of the L release, this text is no longer shown on screen, but it is still useful to + * accessibility services (where it serves as an audible announcement of the notification's + * appearance). * * @see #tickerView */ public CharSequence tickerText; /** - * The view to show as the ticker in the status bar when the notification - * is posted. + * Formerly, a view showing the {@link #tickerText}. + * + * No longer displayed in the status bar as of API 21. */ + @Deprecated public RemoteViews tickerView; /** @@ -205,6 +254,15 @@ */ public RemoteViews bigContentView; + + /** + * A medium-format version of {@link #contentView}, providing the Notification an + * opportunity to add action buttons to contentView. At its discretion, the system UI may + * choose to show this as a heads-up notification, which will pop up so the user can see + * it without leaving their current activity. + */ + public RemoteViews headsUpContentView; + /** * The bitmap that may escape the bounds of the panel and bar. */ @@ -214,6 +272,10 @@ * The sound to play. * * <p> + * A notification that is noisy is more likely to be presented as a heads-up notification. + * </p> + * + * <p> * To play the default notification sound, see {@link #defaults}. * </p> */ @@ -223,23 +285,46 @@ * Use this constant as the value for audioStreamType to request that * the default stream type for notifications be used. Currently the * default stream type is {@link AudioManager#STREAM_NOTIFICATION}. + * + * @deprecated Use {@link #audioAttributes} instead. */ + @Deprecated public static final int STREAM_DEFAULT = -1; /** * The audio stream type to use when playing the sound. * Should be one of the STREAM_ constants from * {@link android.media.AudioManager}. + * + * @deprecated Use {@link #audioAttributes} instead. */ + @Deprecated public int audioStreamType = STREAM_DEFAULT; /** + * The default value of {@link #audioAttributes}. + */ + public static final AudioAttributes AUDIO_ATTRIBUTES_DEFAULT = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .build(); + + /** + * The {@link AudioAttributes audio attributes} to use when playing the sound. + */ + public AudioAttributes audioAttributes = AUDIO_ATTRIBUTES_DEFAULT; + + /** * The pattern with which to vibrate. * * <p> * To vibrate the default pattern, see {@link #defaults}. * </p> * + * <p> + * A notification that vibrates is more likely to be presented as a heads-up notification. + * </p> + * * @see android.os.Vibrator#vibrate(long[],int) */ public long[] vibrate; @@ -369,6 +454,11 @@ public int flags; + /** @hide */ + @IntDef({PRIORITY_DEFAULT,PRIORITY_LOW,PRIORITY_MIN,PRIORITY_HIGH,PRIORITY_MAX}) + @Retention(RetentionPolicy.SOURCE) + public @interface Priority {} + /** * Default notification {@link #priority}. If your application does not prioritize its own * notifications, use this value for all notifications. @@ -409,78 +499,131 @@ * situations, while the user might be interrupted for a higher-priority notification. The * system will make a determination about how to interpret this priority when presenting * the notification. + * + * <p> + * A notification that is at least {@link #PRIORITY_HIGH} is more likely to be presented + * as a heads-up notification. + * </p> + * */ + @Priority public int priority; /** + * Accent color (an ARGB integer like the constants in {@link android.graphics.Color}) + * to be applied by the standard Style templates when presenting this notification. + * + * The current template design constructs a colorful header image by overlaying the + * {@link #icon} image (stenciled in white) atop a field of this color. Alpha components are + * ignored. + */ + public int color = COLOR_DEFAULT; + + /** + * Special value of {@link #color} telling the system not to decorate this notification with + * any special color but instead use default colors when presenting this notification. + */ + public static final int COLOR_DEFAULT = 0; // AKA Color.TRANSPARENT + + /** + * Sphere of visibility of this notification, which affects how and when the SystemUI reveals + * the notification's presence and contents in untrusted situations (namely, on the secure + * lockscreen). + * + * The default level, {@link #VISIBILITY_PRIVATE}, behaves exactly as notifications have always + * done on Android: The notification's {@link #icon} and {@link #tickerText} (if available) are + * shown in all situations, but the contents are only available if the device is unlocked for + * the appropriate user. + * + * A more permissive policy can be expressed by {@link #VISIBILITY_PUBLIC}; such a notification + * can be read even in an "insecure" context (that is, above a secure lockscreen). + * To modify the public version of this notification—for example, to redact some portions—see + * {@link Builder#setPublicVersion(Notification)}. + * + * Finally, a notification can be made {@link #VISIBILITY_SECRET}, which will suppress its icon + * and ticker until the user has bypassed the lockscreen. + */ + public int visibility; + + /** + * Notification visibility: Show this notification in its entirety on all lockscreens. + * + * {@see #visibility} + */ + public static final int VISIBILITY_PUBLIC = 1; + + /** + * Notification visibility: Show this notification on all lockscreens, but conceal sensitive or + * private information on secure lockscreens. + * + * {@see #visibility} + */ + public static final int VISIBILITY_PRIVATE = 0; + + /** + * Notification visibility: Do not reveal any part of this notification on a secure lockscreen. + * + * {@see #visibility} + */ + public static final int VISIBILITY_SECRET = -1; + + /** * Notification category: incoming call (voice or video) or similar synchronous communication request. - * @hide */ public static final String CATEGORY_CALL = "call"; /** * Notification category: incoming direct message (SMS, instant message, etc.). - * @hide */ public static final String CATEGORY_MESSAGE = "msg"; /** * Notification category: asynchronous bulk message (email). - * @hide */ public static final String CATEGORY_EMAIL = "email"; /** * Notification category: calendar event. - * @hide */ public static final String CATEGORY_EVENT = "event"; /** * Notification category: promotion or advertisement. - * @hide */ public static final String CATEGORY_PROMO = "promo"; /** * Notification category: alarm or timer. - * @hide */ public static final String CATEGORY_ALARM = "alarm"; /** * Notification category: progress of a long-running background operation. - * @hide */ public static final String CATEGORY_PROGRESS = "progress"; /** * Notification category: social network or sharing update. - * @hide */ public static final String CATEGORY_SOCIAL = "social"; /** * Notification category: error in background operation or authentication status. - * @hide */ public static final String CATEGORY_ERROR = "err"; /** * Notification category: media transport control for playback. - * @hide */ public static final String CATEGORY_TRANSPORT = "transport"; /** * Notification category: system or device status update. Reserved for system use. - * @hide */ public static final String CATEGORY_SYSTEM = "sys"; /** * Notification category: indication of running background service. - * @hide */ public static final String CATEGORY_SERVICE = "service"; @@ -488,20 +631,17 @@ * Notification category: a specific, timely recommendation for a single thing. * For example, a news app might want to recommend a news story it believes the user will * want to read next. - * @hide */ public static final String CATEGORY_RECOMMENDATION = "recommendation"; /** * Notification category: ongoing information about device or contextual status. - * @hide */ public static final String CATEGORY_STATUS = "status"; /** * One of the predefined notification categories (see the <code>CATEGORY_*</code> constants) * that best describes this Notification. May be used by the system for ranking and filtering. - * @hide */ public String category; @@ -581,6 +721,13 @@ public static final String EXTRA_SUMMARY_TEXT = "android.summaryText"; /** + * {@link #extras} key: this is the longer text shown in the big form of a + * {@link BigTextStyle} notification, as supplied to + * {@link BigTextStyle#bigText(CharSequence)}. + */ + public static final String EXTRA_BIG_TEXT = "android.bigText"; + + /** * {@link #extras} key: this is the resource ID of the notification's main small icon, as * supplied to {@link Builder#setSmallIcon(int)}. */ @@ -645,20 +792,20 @@ public static final String EXTRA_TEXT_LINES = "android.textLines"; /** - * {@link #extras} key: An array of people that this notification relates to, specified - * by contacts provider contact URI. + * {@link #extras} key: A string representing the name of the specific + * {@link android.app.Notification.Style} used to create this notification. + */ + public static final String EXTRA_TEMPLATE = "android.template"; + + /** + * {@link #extras} key: A String array containing the people that this notification relates to, + * each of which was supplied to {@link Builder#addPerson(String)}. */ public static final String EXTRA_PEOPLE = "android.people"; /** - * @hide - * Extra added by NotificationManagerService to indicate whether a NotificationScorer - * modified the Notifications's score. - */ - public static final String EXTRA_SCORE_MODIFIED = "android.scoreModified"; - - /** - * Not used. + * {@link #extras} key: used to provide hints about the appropriateness of + * displaying this notification as a heads-up notification. * @hide */ public static final String EXTRA_AS_HEADS_UP = "headsup"; @@ -671,19 +818,58 @@ public static final String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup"; /** - * Value for {@link #EXTRA_AS_HEADS_UP}. + * {@link #extras} key: A + * {@link android.content.ContentUris content URI} pointing to an image that can be displayed + * in the background when the notification is selected. The URI must point to an image stream + * suitable for passing into + * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream) + * BitmapFactory.decodeStream}; all other content types will be ignored. The content provider + * URI used for this purpose must require no permissions to read the image data. + */ + public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri"; + + /** + * {@link #extras} key: A + * {@link android.media.session.MediaSession.Token} associated with a + * {@link android.app.Notification.MediaStyle} notification. + */ + public static final String EXTRA_MEDIA_SESSION = "android.mediaSession"; + + /** + * {@link #extras} key: the indices of actions to be shown in the compact view, + * as supplied to (e.g.) {@link MediaStyle#setShowActionsInCompactView(int...)}. + */ + public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions"; + + /** + * {@link #extras} key: the user that built the notification. + * + * @hide + */ + public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId"; + + /** + * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be + * displayed in the heads up space. + * + * <p> + * If this notification has a {@link #fullScreenIntent}, then it will always launch the + * full-screen intent when posted. + * </p> * @hide */ public static final int HEADS_UP_NEVER = 0; /** - * Default value for {@link #EXTRA_AS_HEADS_UP}. + * Default value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification may be + * displayed as a heads up. * @hide */ public static final int HEADS_UP_ALLOWED = 1; /** - * Value for {@link #EXTRA_AS_HEADS_UP}. + * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification is a + * good candidate for display as a heads up. * @hide */ public static final int HEADS_UP_REQUESTED = 2; @@ -1019,6 +1205,13 @@ public Action[] actions; /** + * Replacement version of this notification whose content will be shown + * in an insecure context such as atop a secure keyguard. See {@link #visibility} + * and {@link #VISIBILITY_PUBLIC}. + */ + public Notification publicVersion; + + /** * Constructs a Notification object with default values. * You might want to consider using {@link Builder} instead. */ @@ -1096,6 +1289,9 @@ } audioStreamType = parcel.readInt(); + if (parcel.readInt() != 0) { + audioAttributes = AudioAttributes.CREATOR.createFromParcel(parcel); + } vibrate = parcel.createLongArray(); ledARGB = parcel.readInt(); ledOnMS = parcel.readInt(); @@ -1121,6 +1317,18 @@ if (parcel.readInt() != 0) { bigContentView = RemoteViews.CREATOR.createFromParcel(parcel); } + + if (parcel.readInt() != 0) { + headsUpContentView = RemoteViews.CREATOR.createFromParcel(parcel); + } + + visibility = parcel.readInt(); + + if (parcel.readInt() != 0) { + publicVersion = Notification.CREATOR.createFromParcel(parcel); + } + + color = parcel.readInt(); } @Override @@ -1160,6 +1368,9 @@ that.iconLevel = this.iconLevel; that.sound = this.sound; // android.net.Uri is immutable that.audioStreamType = this.audioStreamType; + if (this.audioAttributes != null) { + that.audioAttributes = new AudioAttributes.Builder(this.audioAttributes).build(); + } final long[] vibrate = this.vibrate; if (vibrate != null) { @@ -1205,6 +1416,19 @@ that.bigContentView = this.bigContentView.clone(); } + if (heavy && this.headsUpContentView != null) { + that.headsUpContentView = this.headsUpContentView.clone(); + } + + that.visibility = this.visibility; + + if (this.publicVersion != null) { + that.publicVersion = new Notification(); + this.publicVersion.cloneInto(that.publicVersion, heavy); + } + + that.color = this.color; + if (!heavy) { that.lightenPayload(); // will clean out extras } @@ -1219,11 +1443,15 @@ tickerView = null; contentView = null; bigContentView = null; + headsUpContentView = null; largeIcon = null; if (extras != null) { extras.remove(Notification.EXTRA_LARGE_ICON); extras.remove(Notification.EXTRA_LARGE_ICON_BIG); extras.remove(Notification.EXTRA_PICTURE); + extras.remove(Notification.EXTRA_BIG_TEXT); + // Prevent light notifications from being rebuilt. + extras.remove(Builder.EXTRA_NEEDS_REBUILD); } } @@ -1233,6 +1461,10 @@ * @hide */ public static CharSequence safeCharSequence(CharSequence cs) { + if (cs == null) return cs; + if (cs.length() > MAX_CHARSEQUENCE_LENGTH) { + cs = cs.subSequence(0, MAX_CHARSEQUENCE_LENGTH); + } if (cs instanceof Parcelable) { Log.e(TAG, "warning: " + cs.getClass().getCanonicalName() + " instance is a custom Parcelable and not allowed in Notification"); @@ -1303,6 +1535,14 @@ parcel.writeInt(0); } parcel.writeInt(audioStreamType); + + if (audioAttributes != null) { + parcel.writeInt(1); + audioAttributes.writeToParcel(parcel, 0); + } else { + parcel.writeInt(0); + } + parcel.writeLongArray(vibrate); parcel.writeInt(ledARGB); parcel.writeInt(ledOnMS); @@ -1334,6 +1574,24 @@ } else { parcel.writeInt(0); } + + if (headsUpContentView != null) { + parcel.writeInt(1); + headsUpContentView.writeToParcel(parcel, 0); + } else { + parcel.writeInt(0); + } + + parcel.writeInt(visibility); + + if (publicVersion != null) { + parcel.writeInt(1); + publicVersion.writeToParcel(parcel, 0); + } else { + parcel.writeInt(0); + } + + parcel.writeInt(color); } /** @@ -1383,6 +1641,7 @@ builder.setPriority(this.priority); builder.setTicker(this.tickerText); builder.setNumber(this.number); + builder.setColor(this.color); builder.mFlags = this.flags; builder.setSound(this.sound, this.audioStreamType); builder.setDefaults(this.defaults); @@ -1412,7 +1671,6 @@ } else { sb.append("null"); } - // TODO(dsandler): defaults take precedence over local values, so reorder the branches below sb.append(" vibrate="); if ((this.defaults & DEFAULT_VIBRATE) != 0) { sb.append("default"); @@ -1442,6 +1700,7 @@ sb.append(Integer.toHexString(this.defaults)); sb.append(" flags=0x"); sb.append(Integer.toHexString(this.flags)); + sb.append(String.format(" color=0x%08x", this.color)); if (this.category != null) { sb.append(" category="); sb.append(this.category); @@ -1455,29 +1714,56 @@ sb.append(this.mSortKey); } if (actions != null) { - sb.append(" "); + sb.append(" actions="); sb.append(actions.length); - sb.append(" action"); - if (actions.length > 1) sb.append("s"); + } + sb.append(" vis="); + sb.append(visibilityToString(this.visibility)); + if (this.publicVersion != null) { + sb.append(" publicVersion="); + sb.append(publicVersion.toString()); } sb.append(")"); return sb.toString(); } - /** {@hide} */ - public void setUser(UserHandle user) { - if (user.getIdentifier() == UserHandle.USER_ALL) { - user = UserHandle.OWNER; + /** + * {@hide} + */ + public static String visibilityToString(int vis) { + switch (vis) { + case VISIBILITY_PRIVATE: + return "PRIVATE"; + case VISIBILITY_PUBLIC: + return "PUBLIC"; + case VISIBILITY_SECRET: + return "SECRET"; + default: + return "UNKNOWN(" + String.valueOf(vis) + ")"; } - if (tickerView != null) { - tickerView.setUser(user); - } - if (contentView != null) { - contentView.setUser(user); - } - if (bigContentView != null) { - bigContentView.setUser(user); - } + } + + /** + * @hide + */ + public boolean isValid() { + // Would like to check for icon!=0 here, too, but NotificationManagerService accepts that + // for legacy reasons. + return contentView != null || extras.getBoolean(Builder.EXTRA_REBUILD_CONTENT_VIEW); + } + + /** + * @hide + */ + public boolean isGroupSummary() { + return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) != 0; + } + + /** + * @hide + */ + public boolean isGroupChild() { + return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) == 0; } /** @@ -1503,6 +1789,58 @@ */ public static class Builder { private static final int MAX_ACTION_BUTTONS = 3; + private static final float LARGE_TEXT_SCALE = 1.3f; + + /** + * @hide + */ + public static final String EXTRA_NEEDS_REBUILD = "android.rebuild"; + + /** + * @hide + */ + public static final String EXTRA_REBUILD_LARGE_ICON = "android.rebuild.largeIcon"; + /** + * @hide + */ + public static final String EXTRA_REBUILD_CONTENT_VIEW = "android.rebuild.contentView"; + /** + * @hide + */ + public static final String EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT = + "android.rebuild.contentViewActionCount"; + /** + * @hide + */ + public static final String EXTRA_REBUILD_BIG_CONTENT_VIEW + = "android.rebuild.bigView"; + /** + * @hide + */ + public static final String EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT + = "android.rebuild.bigViewActionCount"; + /** + * @hide + */ + public static final String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW + = "android.rebuild.hudView"; + /** + * @hide + */ + public static final String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT + = "android.rebuild.hudViewActionCount"; + + /** + * The ApplicationInfo of the package that created the notification, used to create + * a context to rebuild the notification via a Builder. + * @hide + */ + private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO = + "android.rebuild.applicationInfo"; + + // Whether to enable stripping (at post time) & rebuilding (at listener receive time) of + // memory intensive resources. + private static final boolean STRIP_AND_REBUILD = true; private Context mContext; @@ -1523,6 +1861,7 @@ private Bitmap mLargeIcon; private Uri mSound; private int mAudioStreamType; + private AudioAttributes mAudioAttributes; private long[] mVibrate; private int mLedArgb; private int mLedOnMs; @@ -1541,6 +1880,35 @@ private boolean mUseChronometer; private Style mStyle; private boolean mShowWhen = true; + private int mVisibility = VISIBILITY_PRIVATE; + private Notification mPublicVersion = null; + private final NotificationColorUtil mColorUtil; + private ArrayList<String> mPeople; + private int mColor = COLOR_DEFAULT; + + /** + * The user that built the notification originally. + */ + private int mOriginatingUserId; + + /** + * Contains extras related to rebuilding during the build phase. + */ + private Bundle mRebuildBundle = new Bundle(); + /** + * Contains the notification to rebuild when this Builder is in "rebuild" mode. + * Null otherwise. + */ + private Notification mRebuildNotification = null; + + /** + * Whether the build notification has three lines. This is used to make the top padding for + * both the contracted and expanded layout consistent. + * + * <p> + * This field is only valid during the build phase. + */ + private boolean mHasThreeLines; /** * Constructs a new Builder with the defaults: @@ -1562,12 +1930,60 @@ * object. */ public Builder(Context context) { + /* + * Important compatibility note! + * Some apps out in the wild create a Notification.Builder in their Activity subclass + * constructor for later use. At this point Activities - themselves subclasses of + * ContextWrapper - do not have their inner Context populated yet. This means that + * any calls to Context methods from within this constructor can cause NPEs in existing + * apps. Any data populated from mContext should therefore be populated lazily to + * preserve compatibility. + */ mContext = context; // Set defaults to match the defaults of a Notification mWhen = System.currentTimeMillis(); mAudioStreamType = STREAM_DEFAULT; + mAudioAttributes = AUDIO_ATTRIBUTES_DEFAULT; mPriority = PRIORITY_DEFAULT; + mPeople = new ArrayList<String>(); + + mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L ? + NotificationColorUtil.getInstance(mContext) : null; + } + + /** + * Creates a Builder for rebuilding the given Notification. + * <p> + * Call {@link #rebuild()} to retrieve the rebuilt version of 'n'. + */ + private Builder(Context context, Notification n) { + this(context); + mRebuildNotification = n; + restoreFromNotification(n); + + Style style = null; + Bundle extras = n.extras; + String templateClass = extras.getString(EXTRA_TEMPLATE); + if (!TextUtils.isEmpty(templateClass)) { + Class<? extends Style> styleClass = getNotificationStyleClass(templateClass); + if (styleClass == null) { + Log.d(TAG, "Unknown style class: " + styleClass); + return; + } + + try { + Constructor<? extends Style> constructor = styleClass.getConstructor(); + style = constructor.newInstance(); + style.restoreFromExtras(extras); + } catch (Throwable t) { + Log.e(TAG, "Could not create Style", t); + return; + } + } + if (style != null) { + setStyle(style); + } } /** @@ -1747,6 +2163,11 @@ * to turn it off and use a normal notification, as this can be extremely * disruptive. * + * <p> + * The system UI may choose to display a heads-up notification, instead of + * launching this intent, while the user is using the device. + * </p> + * * @param intent The pending intent to launch. * @param highPriority Passing true will cause this notification to be sent * even if other notifications are suppressed. @@ -1760,8 +2181,7 @@ } /** - * Set the "ticker" text which is displayed in the status bar when the notification first - * arrives. + * Set the "ticker" text which is sent to accessibility services. * * @see Notification#tickerText */ @@ -1771,16 +2191,13 @@ } /** - * Set the text that is displayed in the status bar when the notification first - * arrives, and also a RemoteViews object that may be displayed instead on some - * devices. + * Obsolete version of {@link #setTicker(CharSequence)}. * - * @see Notification#tickerText - * @see Notification#tickerView */ + @Deprecated public Builder setTicker(CharSequence tickerText, RemoteViews views) { mTickerText = safeCharSequence(tickerText); - mTickerView = views; + mTickerView = views; // we'll save it for you anyway return this; } @@ -1800,13 +2217,18 @@ /** * Set the sound to play. * - * It will be played on the {@link #STREAM_DEFAULT default stream} for notifications. + * It will be played using the {@link #AUDIO_ATTRIBUTES_DEFAULT default audio attributes} + * for notifications. + * + * <p> + * A notification that is noisy is more likely to be presented as a heads-up notification. + * </p> * * @see Notification#sound */ public Builder setSound(Uri sound) { mSound = sound; - mAudioStreamType = STREAM_DEFAULT; + mAudioAttributes = AUDIO_ATTRIBUTES_DEFAULT; return this; } @@ -1815,8 +2237,13 @@ * * See {@link android.media.AudioManager} for the <code>STREAM_</code> constants. * + * <p> + * A notification that is noisy is more likely to be presented as a heads-up notification. + * </p> + * @deprecated use {@link #setSound(Uri, AudioAttributes)} instead. * @see Notification#sound */ + @Deprecated public Builder setSound(Uri sound, int streamType) { mSound = sound; mAudioStreamType = streamType; @@ -1824,13 +2251,31 @@ } /** + * Set the sound to play, along with specific {@link AudioAttributes audio attributes} to + * use during playback. + * + * <p> + * A notification that is noisy is more likely to be presented as a heads-up notification. + * </p> + * + * @see Notification#sound + */ + public Builder setSound(Uri sound, AudioAttributes audioAttributes) { + mSound = sound; + mAudioAttributes = audioAttributes; + return this; + } + + /** * Set the vibration pattern to use. * - * See {@link android.os.Vibrator#vibrate(long[], int)} for a discussion of the * <code>pattern</code> parameter. * - + * <p> + * A notification that vibrates is more likely to be presented as a heads-up notification. + * </p> + * * @see Notification#vibrate */ public Builder setVibrate(long[] pattern) { @@ -1930,7 +2375,7 @@ * * @see Notification#priority */ - public Builder setPriority(int pri) { + public Builder setPriority(@Priority int pri) { mPriority = pri; return this; } @@ -1939,7 +2384,6 @@ * Set the notification category. * * @see Notification#category - * @hide */ public Builder setCategory(String category) { mCategory = category; @@ -1947,6 +2391,33 @@ } /** + * Add a person that is relevant to this notification. + * + * <P> + * Depending on user preferences, this annotation may allow the notification to pass + * through interruption filters, and to appear more prominently in the user interface. + * </P> + * + * <P> + * The person should be specified by the {@code String} representation of a + * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}. + * </P> + * + * <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema + * URIs. The path part of these URIs must exist in the contacts database, in the + * appropriate column, or the reference will be discarded as invalid. Telephone schema + * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}. + * </P> + * + * @param uri A URI for the person. + * @see Notification#EXTRA_PEOPLE + */ + public Builder addPerson(String uri) { + mPeople.add(uri); + return this; + } + + /** * Set this notification to be part of a group of notifications sharing the same key. * Grouped notifications may display in a cluster or stack on devices which * support such rendering. @@ -2101,6 +2572,30 @@ } /** + * Specify the value of {@link #visibility}. + * + * @param visibility One of {@link #VISIBILITY_PRIVATE} (the default), + * {@link #VISIBILITY_SECRET}, or {@link #VISIBILITY_PUBLIC}. + * + * @return The same Builder. + */ + public Builder setVisibility(int visibility) { + mVisibility = visibility; + return this; + } + + /** + * Supply a replacement Notification whose contents should be shown in insecure contexts + * (i.e. atop the secure lockscreen). See {@link #visibility} and {@link #VISIBILITY_PUBLIC}. + * @param n A replacement notification, presumably with some or all info redacted. + * @return The same Builder. + */ + public Builder setPublicVersion(Notification n) { + mPublicVersion = n; + return this; + } + + /** * Apply an extender to this notification builder. Extenders may be used to add * metadata or change options on this builder. */ @@ -2117,47 +2612,143 @@ } } - private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) { - RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); + /** + * Sets {@link Notification#color}. + * + * @param argb The accent color to use + * + * @return The same Builder. + */ + public Builder setColor(int argb) { + mColor = argb; + return this; + } + + private Drawable getProfileBadgeDrawable() { + // Note: This assumes that the current user can read the profile badge of the + // originating user. + return mContext.getPackageManager().getUserBadgeForDensity( + new UserHandle(mOriginatingUserId), 0); + } + + private Bitmap getProfileBadge() { + Drawable badge = getProfileBadgeDrawable(); + if (badge == null) { + return null; + } + final int size = mContext.getResources().getDimensionPixelSize( + R.dimen.notification_badge_size); + Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + badge.setBounds(0, 0, size, size); + badge.draw(canvas); + return bitmap; + } + + private boolean addProfileBadge(RemoteViews contentView, int resId) { + Bitmap profileBadge = getProfileBadge(); + + contentView.setViewVisibility(R.id.profile_badge_large_template, View.GONE); + contentView.setViewVisibility(R.id.profile_badge_line2, View.GONE); + contentView.setViewVisibility(R.id.profile_badge_line3, View.GONE); + + if (profileBadge != null) { + contentView.setImageViewBitmap(resId, profileBadge); + contentView.setViewVisibility(resId, View.VISIBLE); + + // Make sure Line 3 is visible. As badge will be here if there + // is no text to display. + if (resId == R.id.profile_badge_line3) { + contentView.setViewVisibility(R.id.line3, View.VISIBLE); + } + return true; + } + return false; + } + + private void shrinkLine3Text(RemoteViews contentView) { + float subTextSize = mContext.getResources().getDimensionPixelSize( + R.dimen.notification_subtext_size); + contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize); + } + + private void unshrinkLine3Text(RemoteViews contentView) { + float regularTextSize = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.notification_text_size); + contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, regularTextSize); + } + + private void resetStandardTemplate(RemoteViews contentView) { + removeLargeIconBackground(contentView); + contentView.setViewPadding(R.id.icon, 0, 0, 0, 0); + contentView.setImageViewResource(R.id.icon, 0); + contentView.setInt(R.id.icon, "setBackgroundResource", 0); + contentView.setViewVisibility(R.id.right_icon, View.GONE); + contentView.setInt(R.id.right_icon, "setBackgroundResource", 0); + contentView.setImageViewResource(R.id.right_icon, 0); + contentView.setImageViewResource(R.id.icon, 0); + contentView.setTextViewText(R.id.title, null); + contentView.setTextViewText(R.id.text, null); + unshrinkLine3Text(contentView); + contentView.setTextViewText(R.id.text2, null); + contentView.setViewVisibility(R.id.text2, View.GONE); + contentView.setViewVisibility(R.id.info, View.GONE); + contentView.setViewVisibility(R.id.time, View.GONE); + contentView.setViewVisibility(R.id.line3, View.GONE); + contentView.setViewVisibility(R.id.overflow_divider, View.GONE); + contentView.setViewVisibility(R.id.progress, View.GONE); + contentView.setViewVisibility(R.id.chronometer, View.GONE); + contentView.setViewVisibility(R.id.time, View.GONE); + } + + private RemoteViews applyStandardTemplate(int resId) { + return applyStandardTemplate(resId, true /* hasProgress */); + } + + /** + * @param hasProgress whether the progress bar should be shown and set + */ + private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) { + RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId); + + resetStandardTemplate(contentView); + boolean showLine3 = false; boolean showLine2 = false; - int smallIconImageViewId = R.id.icon; + boolean contentTextInLine2 = false; + if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); - smallIconImageViewId = R.id.right_icon; - } - if (mPriority < PRIORITY_LOW) { - contentView.setInt(R.id.icon, - "setBackgroundResource", R.drawable.notification_template_icon_low_bg); - contentView.setInt(R.id.status_bar_latest_event_content, - "setBackgroundResource", R.drawable.notification_bg_low); - } - if (mSmallIcon != 0) { - contentView.setImageViewResource(smallIconImageViewId, mSmallIcon); - contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE); - } else { - contentView.setViewVisibility(smallIconImageViewId, View.GONE); + processLargeLegacyIcon(mLargeIcon, contentView); + contentView.setImageViewResource(R.id.right_icon, mSmallIcon); + contentView.setViewVisibility(R.id.right_icon, View.VISIBLE); + processSmallRightIcon(mSmallIcon, contentView); + } else { // small icon at left + contentView.setImageViewResource(R.id.icon, mSmallIcon); + contentView.setViewVisibility(R.id.icon, View.VISIBLE); + processSmallIconAsLarge(mSmallIcon, contentView); } if (mContentTitle != null) { - contentView.setTextViewText(R.id.title, mContentTitle); + contentView.setTextViewText(R.id.title, processLegacyText(mContentTitle)); } if (mContentText != null) { - contentView.setTextViewText(R.id.text, mContentText); + contentView.setTextViewText(R.id.text, processLegacyText(mContentText)); showLine3 = true; } if (mContentInfo != null) { - contentView.setTextViewText(R.id.info, mContentInfo); + contentView.setTextViewText(R.id.info, processLegacyText(mContentInfo)); contentView.setViewVisibility(R.id.info, View.VISIBLE); showLine3 = true; } else if (mNumber > 0) { final int tooBig = mContext.getResources().getInteger( R.integer.status_bar_notification_info_maxnum); if (mNumber > tooBig) { - contentView.setTextViewText(R.id.info, mContext.getResources().getString( - R.string.status_bar_notification_info_overflow)); + contentView.setTextViewText(R.id.info, processLegacyText( + mContext.getResources().getString( + R.string.status_bar_notification_info_overflow))); } else { NumberFormat f = NumberFormat.getIntegerInstance(); - contentView.setTextViewText(R.id.info, f.format(mNumber)); + contentView.setTextViewText(R.id.info, processLegacyText(f.format(mNumber))); } contentView.setViewVisibility(R.id.info, View.VISIBLE); showLine3 = true; @@ -2167,38 +2758,33 @@ // Need to show three lines? if (mSubText != null) { - contentView.setTextViewText(R.id.text, mSubText); + contentView.setTextViewText(R.id.text, processLegacyText(mSubText)); if (mContentText != null) { - contentView.setTextViewText(R.id.text2, mContentText); + contentView.setTextViewText(R.id.text2, processLegacyText(mContentText)); contentView.setViewVisibility(R.id.text2, View.VISIBLE); showLine2 = true; + contentTextInLine2 = true; } else { contentView.setViewVisibility(R.id.text2, View.GONE); } } else { contentView.setViewVisibility(R.id.text2, View.GONE); - if (mProgressMax != 0 || mProgressIndeterminate) { + if (hasProgress && (mProgressMax != 0 || mProgressIndeterminate)) { + contentView.setViewVisibility(R.id.progress, View.VISIBLE); contentView.setProgressBar( R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); - contentView.setViewVisibility(R.id.progress, View.VISIBLE); showLine2 = true; } else { contentView.setViewVisibility(R.id.progress, View.GONE); } } if (showLine2) { - if (fitIn1U) { - // need to shrink all the type to make sure everything fits - final Resources res = mContext.getResources(); - final float subTextSize = res.getDimensionPixelSize( - R.dimen.notification_subtext_size); - contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize); - } - // vertical centering - contentView.setViewPadding(R.id.line1, 0, 0, 0, 0); + + // need to shrink all the type to make sure everything fits + shrinkLine3Text(contentView); } - if (mWhen != 0 && mShowWhen) { + if (showsTimeOrChronometer()) { if (mUseChronometer) { contentView.setViewVisibility(R.id.chronometer, View.VISIBLE); contentView.setLong(R.id.chronometer, "setBase", @@ -2208,28 +2794,92 @@ contentView.setViewVisibility(R.id.time, View.VISIBLE); contentView.setLong(R.id.time, "setTime", mWhen); } - } else { - contentView.setViewVisibility(R.id.time, View.GONE); } + // Adjust padding depending on line count and font size. + contentView.setViewPadding(R.id.line1, 0, calculateTopPadding(mContext, + mHasThreeLines, mContext.getResources().getConfiguration().fontScale), + 0, 0); + + // We want to add badge to first line of text. + boolean addedBadge = addProfileBadge(contentView, + contentTextInLine2 ? R.id.profile_badge_line2 : R.id.profile_badge_line3); + // If we added the badge to line 3 then we should show line 3. + if (addedBadge && !contentTextInLine2) { + showLine3 = true; + } + + // Note getStandardView may hide line 3 again. contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE); contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE); return contentView; } + /** + * @return true if the built notification will show the time or the chronometer; false + * otherwise + */ + private boolean showsTimeOrChronometer() { + return mWhen != 0 && mShowWhen; + } + + /** + * Logic to find out whether the notification is going to have three lines in the contracted + * layout. This is used to adjust the top padding. + * + * @return true if the notification is going to have three lines; false if the notification + * is going to have one or two lines + */ + private boolean hasThreeLines() { + boolean contentTextInLine2 = mSubText != null && mContentText != null; + boolean hasProgress = mStyle == null || mStyle.hasProgress(); + // If we have content text in line 2, badge goes into line 2, or line 3 otherwise + boolean badgeInLine3 = getProfileBadgeDrawable() != null && !contentTextInLine2; + boolean hasLine3 = mContentText != null || mContentInfo != null || mNumber > 0 + || badgeInLine3; + boolean hasLine2 = (mSubText != null && mContentText != null) || + (hasProgress && mSubText == null + && (mProgressMax != 0 || mProgressIndeterminate)); + return hasLine2 && hasLine3; + } + + /** + * @hide + */ + public static int calculateTopPadding(Context ctx, boolean hasThreeLines, + float fontScale) { + int padding = ctx.getResources().getDimensionPixelSize(hasThreeLines + ? R.dimen.notification_top_pad_narrow + : R.dimen.notification_top_pad); + int largePadding = ctx.getResources().getDimensionPixelSize(hasThreeLines + ? R.dimen.notification_top_pad_large_text_narrow + : R.dimen.notification_top_pad_large_text); + float largeFactor = (MathUtils.constrain(fontScale, 1.0f, LARGE_TEXT_SCALE) - 1f) + / (LARGE_TEXT_SCALE - 1f); + + // Linearly interpolate the padding between large and normal with the font scale ranging + // from 1f to LARGE_TEXT_SCALE + return Math.round((1 - largeFactor) * padding + largeFactor * largePadding); + } + + private void resetStandardTemplateWithActions(RemoteViews big) { + big.setViewVisibility(R.id.actions, View.GONE); + big.setViewVisibility(R.id.action_divider, View.GONE); + big.removeAllViews(R.id.actions); + } + private RemoteViews applyStandardTemplateWithActions(int layoutId) { - RemoteViews big = applyStandardTemplate(layoutId, false); + RemoteViews big = applyStandardTemplate(layoutId); + + resetStandardTemplateWithActions(big); int N = mActions.size(); if (N > 0) { - // Log.d("Notification", "has actions: " + mContentText); big.setViewVisibility(R.id.actions, View.VISIBLE); big.setViewVisibility(R.id.action_divider, View.VISIBLE); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; - big.removeAllViews(R.id.actions); for (int i=0; i<N; i++) { final RemoteViews button = generateActionButton(mActions.get(i)); - //Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title); big.addView(R.id.actions, button); } } @@ -2240,45 +2890,154 @@ if (mContentView != null) { return mContentView; } else { - return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor + return applyStandardTemplate(getBaseLayoutResource()); } } private RemoteViews makeTickerView() { if (mTickerView != null) { return mTickerView; - } else { - if (mContentView == null) { - return applyStandardTemplate(mLargeIcon == null - ? R.layout.status_bar_latest_event_ticker - : R.layout.status_bar_latest_event_ticker_large_icon, true); - } else { - return null; - } } + return null; // tickers are not created by default anymore } private RemoteViews makeBigContentView() { if (mActions.size() == 0) return null; - return applyStandardTemplateWithActions(R.layout.notification_template_big_base); + return applyStandardTemplateWithActions(getBigBaseLayoutResource()); } + private RemoteViews makeHeadsUpContentView() { + if (mActions.size() == 0) return null; + + return applyStandardTemplateWithActions(getBigBaseLayoutResource()); + } + + private RemoteViews generateActionButton(Action action) { final boolean tombstone = (action.actionIntent == null); RemoteViews button = new RemoteViews(mContext.getPackageName(), - tombstone ? R.layout.notification_action_tombstone - : R.layout.notification_action); + tombstone ? getActionTombstoneLayoutResource() + : getActionLayoutResource()); button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0); - button.setTextViewText(R.id.action0, action.title); + button.setTextViewText(R.id.action0, processLegacyText(action.title)); if (!tombstone) { button.setOnClickPendingIntent(R.id.action0, action.actionIntent); } button.setContentDescription(R.id.action0, action.title); + processLegacyAction(action, button); return button; } /** + * @return Whether we are currently building a notification from a legacy (an app that + * doesn't create material notifications by itself) app. + */ + private boolean isLegacy() { + return mColorUtil != null; + } + + private void processLegacyAction(Action action, RemoteViews button) { + if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, action.icon)) { + button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0, + mContext.getResources().getColor(R.color.notification_action_color_filter), + PorterDuff.Mode.MULTIPLY); + } + } + + private CharSequence processLegacyText(CharSequence charSequence) { + if (isLegacy()) { + return mColorUtil.invertCharSequenceColors(charSequence); + } else { + return charSequence; + } + } + + /** + * Apply any necessary background to smallIcons being used in the largeIcon spot. + */ + private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) { + if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) { + applyLargeIconBackground(contentView); + } + } + + /** + * Apply any necessary background to a largeIcon if it's a fake smallIcon (that is, + * if it's grayscale). + */ + // TODO: also check bounds, transparency, that sort of thing. + private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) { + if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) { + applyLargeIconBackground(contentView); + } else { + removeLargeIconBackground(contentView); + } + } + + /** + * Add a colored circle behind the largeIcon slot. + */ + private void applyLargeIconBackground(RemoteViews contentView) { + contentView.setInt(R.id.icon, "setBackgroundResource", + R.drawable.notification_icon_legacy_bg); + + contentView.setDrawableParameters( + R.id.icon, + true, + -1, + resolveColor(), + PorterDuff.Mode.SRC_ATOP, + -1); + + int padding = mContext.getResources().getDimensionPixelSize( + R.dimen.notification_large_icon_circle_padding); + contentView.setViewPadding(R.id.icon, padding, padding, padding, padding); + } + + private void removeLargeIconBackground(RemoteViews contentView) { + contentView.setInt(R.id.icon, "setBackgroundResource", 0); + } + + /** + * Recolor small icons when used in the R.id.right_icon slot. + */ + private void processSmallRightIcon(int smallIconDrawableId, + RemoteViews contentView) { + if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) { + contentView.setDrawableParameters(R.id.right_icon, false, -1, + 0xFFFFFFFF, + PorterDuff.Mode.SRC_ATOP, -1); + + contentView.setInt(R.id.right_icon, + "setBackgroundResource", + R.drawable.notification_icon_legacy_bg); + + contentView.setDrawableParameters( + R.id.right_icon, + true, + -1, + resolveColor(), + PorterDuff.Mode.SRC_ATOP, + -1); + } + } + + private int sanitizeColor() { + if (mColor != COLOR_DEFAULT) { + mColor |= 0xFF000000; // no alpha for custom colors + } + return mColor; + } + + private int resolveColor() { + if (mColor == COLOR_DEFAULT) { + return mContext.getResources().getColor(R.color.notification_icon_bg_color); + } + return mColor; + } + + /** * Apply the unstyled operations and return a new {@link Notification} object. * @hide */ @@ -2288,7 +3047,10 @@ n.icon = mSmallIcon; n.iconLevel = mSmallIconLevel; n.number = mNumber; - n.contentView = makeContentView(); + + n.color = sanitizeColor(); + + setBuilderContentView(n, makeContentView()); n.contentIntent = mContentIntent; n.deleteIntent = mDeleteIntent; n.fullScreenIntent = mFullScreenIntent; @@ -2297,13 +3059,15 @@ n.largeIcon = mLargeIcon; n.sound = mSound; n.audioStreamType = mAudioStreamType; + n.audioAttributes = mAudioAttributes; n.vibrate = mVibrate; n.ledARGB = mLedArgb; n.ledOnMS = mLedOnMs; n.ledOffMS = mLedOffMs; n.defaults = mDefaults; n.flags = mFlags; - n.bigContentView = makeBigContentView(); + setBuilderBigContentView(n, makeBigContentView()); + setBuilderHeadsUpContentView(n, makeHeadsUpContentView()); if (mLedOnMs != 0 || mLedOffMs != 0) { n.flags |= FLAG_SHOW_LIGHTS; } @@ -2318,6 +3082,13 @@ n.actions = new Action[mActions.size()]; mActions.toArray(n.actions); } + n.visibility = mVisibility; + + if (mPublicVersion != null) { + n.publicVersion = new Notification(); + mPublicVersion.cloneInto(n.publicVersion, true); + } + // Note: If you're adding new fields, also update restoreFromNotitification(). return n; } @@ -2328,6 +3099,9 @@ */ public void populateExtras(Bundle extras) { // Store original information used in the construction of this object + extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId); + extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO, + mContext.getApplicationInfo()); extras.putCharSequence(EXTRA_TITLE, mContentTitle); extras.putCharSequence(EXTRA_TEXT, mContentText); extras.putCharSequence(EXTRA_SUB_TEXT, mSubText); @@ -2341,6 +3115,240 @@ if (mLargeIcon != null) { extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon); } + if (!mPeople.isEmpty()) { + extras.putStringArray(EXTRA_PEOPLE, mPeople.toArray(new String[mPeople.size()])); + } + // NOTE: If you're adding new extras also update restoreFromNotification(). + } + + + /** + * @hide + */ + public static void stripForDelivery(Notification n) { + if (!STRIP_AND_REBUILD) { + return; + } + + String templateClass = n.extras.getString(EXTRA_TEMPLATE); + // Only strip views for known Styles because we won't know how to + // re-create them otherwise. + boolean stripViews = TextUtils.isEmpty(templateClass) || + getNotificationStyleClass(templateClass) != null; + + boolean isStripped = false; + + if (n.largeIcon != null && n.extras.containsKey(EXTRA_LARGE_ICON)) { + // TODO: Would like to check for equality here, but if the notification + // has been cloned, we can't. + n.largeIcon = null; + n.extras.putBoolean(EXTRA_REBUILD_LARGE_ICON, true); + isStripped = true; + } + // Get rid of unmodified BuilderRemoteViews. + + if (stripViews && + n.contentView instanceof BuilderRemoteViews && + n.extras.getInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, -1) == + n.contentView.getSequenceNumber()) { + n.contentView = null; + n.extras.putBoolean(EXTRA_REBUILD_CONTENT_VIEW, true); + n.extras.remove(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT); + isStripped = true; + } + if (stripViews && + n.bigContentView instanceof BuilderRemoteViews && + n.extras.getInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT, -1) == + n.bigContentView.getSequenceNumber()) { + n.bigContentView = null; + n.extras.putBoolean(EXTRA_REBUILD_BIG_CONTENT_VIEW, true); + n.extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT); + isStripped = true; + } + if (stripViews && + n.headsUpContentView instanceof BuilderRemoteViews && + n.extras.getInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT, -1) == + n.headsUpContentView.getSequenceNumber()) { + n.headsUpContentView = null; + n.extras.putBoolean(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW, true); + n.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT); + isStripped = true; + } + + if (isStripped) { + n.extras.putBoolean(EXTRA_NEEDS_REBUILD, true); + } + } + + /** + * @hide + */ + public static Notification rebuild(Context context, Notification n) { + Bundle extras = n.extras; + if (!extras.getBoolean(EXTRA_NEEDS_REBUILD)) return n; + extras.remove(EXTRA_NEEDS_REBUILD); + + // Re-create notification context so we can access app resources. + ApplicationInfo applicationInfo = extras.getParcelable( + EXTRA_REBUILD_CONTEXT_APPLICATION_INFO); + Context builderContext; + try { + builderContext = context.createApplicationContext(applicationInfo, + Context.CONTEXT_RESTRICTED); + } catch (NameNotFoundException e) { + Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found"); + builderContext = context; // try with our context + } + + Builder b = new Builder(builderContext, n); + return b.rebuild(); + } + + /** + * Rebuilds the notification passed in to the rebuild-constructor + * {@link #Builder(Context, Notification)}. + * + * <p> + * Throws IllegalStateException when invoked on a Builder that isn't in rebuild mode. + * + * @hide + */ + private Notification rebuild() { + if (mRebuildNotification == null) { + throw new IllegalStateException("rebuild() only valid when in 'rebuild' mode."); + } + mHasThreeLines = hasThreeLines(); + + Bundle extras = mRebuildNotification.extras; + + if (extras.getBoolean(EXTRA_REBUILD_LARGE_ICON)) { + mRebuildNotification.largeIcon = extras.getParcelable(EXTRA_LARGE_ICON); + } + extras.remove(EXTRA_REBUILD_LARGE_ICON); + + if (extras.getBoolean(EXTRA_REBUILD_CONTENT_VIEW)) { + setBuilderContentView(mRebuildNotification, makeContentView()); + if (mStyle != null) { + mStyle.populateContentView(mRebuildNotification); + } + } + extras.remove(EXTRA_REBUILD_CONTENT_VIEW); + + if (extras.getBoolean(EXTRA_REBUILD_BIG_CONTENT_VIEW)) { + setBuilderBigContentView(mRebuildNotification, makeBigContentView()); + if (mStyle != null) { + mStyle.populateBigContentView(mRebuildNotification); + } + } + extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW); + + if (extras.getBoolean(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW)) { + setBuilderHeadsUpContentView(mRebuildNotification, makeHeadsUpContentView()); + if (mStyle != null) { + mStyle.populateHeadsUpContentView(mRebuildNotification); + } + } + extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW); + + mHasThreeLines = false; + return mRebuildNotification; + } + + private static Class<? extends Style> getNotificationStyleClass(String templateClass) { + Class<? extends Style>[] classes = new Class[]{ + BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class}; + for (Class<? extends Style> innerClass : classes) { + if (templateClass.equals(innerClass.getName())) { + return innerClass; + } + } + return null; + } + + private void setBuilderContentView(Notification n, RemoteViews contentView) { + n.contentView = contentView; + if (contentView instanceof BuilderRemoteViews) { + mRebuildBundle.putInt(Builder.EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, + contentView.getSequenceNumber()); + } + } + + private void setBuilderBigContentView(Notification n, RemoteViews bigContentView) { + n.bigContentView = bigContentView; + if (bigContentView instanceof BuilderRemoteViews) { + mRebuildBundle.putInt(Builder.EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT, + bigContentView.getSequenceNumber()); + } + } + + private void setBuilderHeadsUpContentView(Notification n, + RemoteViews headsUpContentView) { + n.headsUpContentView = headsUpContentView; + if (headsUpContentView instanceof BuilderRemoteViews) { + mRebuildBundle.putInt(Builder.EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT, + headsUpContentView.getSequenceNumber()); + } + } + + private void restoreFromNotification(Notification n) { + + // Notification fields. + mWhen = n.when; + mSmallIcon = n.icon; + mSmallIconLevel = n.iconLevel; + mNumber = n.number; + + mColor = n.color; + + mContentView = n.contentView; + mDeleteIntent = n.deleteIntent; + mFullScreenIntent = n.fullScreenIntent; + mTickerText = n.tickerText; + mTickerView = n.tickerView; + mLargeIcon = n.largeIcon; + mSound = n.sound; + mAudioStreamType = n.audioStreamType; + mAudioAttributes = n.audioAttributes; + + mVibrate = n.vibrate; + mLedArgb = n.ledARGB; + mLedOnMs = n.ledOnMS; + mLedOffMs = n.ledOffMS; + mDefaults = n.defaults; + mFlags = n.flags; + + mCategory = n.category; + mGroupKey = n.mGroupKey; + mSortKey = n.mSortKey; + mPriority = n.priority; + mActions.clear(); + if (n.actions != null) { + Collections.addAll(mActions, n.actions); + } + mVisibility = n.visibility; + + mPublicVersion = n.publicVersion; + + // Extras. + Bundle extras = n.extras; + mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID); + mContentTitle = extras.getCharSequence(EXTRA_TITLE); + mContentText = extras.getCharSequence(EXTRA_TEXT); + mSubText = extras.getCharSequence(EXTRA_SUB_TEXT); + mContentInfo = extras.getCharSequence(EXTRA_INFO_TEXT); + mSmallIcon = extras.getInt(EXTRA_SMALL_ICON); + mProgress = extras.getInt(EXTRA_PROGRESS); + mProgressMax = extras.getInt(EXTRA_PROGRESS_MAX); + mProgressIndeterminate = extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE); + mUseChronometer = extras.getBoolean(EXTRA_SHOW_CHRONOMETER); + mShowWhen = extras.getBoolean(EXTRA_SHOW_WHEN); + if (extras.containsKey(EXTRA_LARGE_ICON)) { + mLargeIcon = extras.getParcelable(EXTRA_LARGE_ICON); + } + if (extras.containsKey(EXTRA_PEOPLE)) { + mPeople.clear(); + Collections.addAll(mPeople, extras.getStringArray(EXTRA_PEOPLE)); + } } /** @@ -2356,19 +3364,30 @@ * object. */ public Notification build() { + mOriginatingUserId = mContext.getUserId(); + mHasThreeLines = hasThreeLines(); + Notification n = buildUnstyled(); if (mStyle != null) { n = mStyle.buildStyled(n); } - n.extras = mExtras != null ? new Bundle(mExtras) : new Bundle(); + if (mExtras != null) { + n.extras.putAll(mExtras); + } + + if (mRebuildBundle.size() > 0) { + n.extras.putAll(mRebuildBundle); + mRebuildBundle.clear(); + } populateExtras(n.extras); if (mStyle != null) { mStyle.addExtras(n.extras); } + mHasThreeLines = false; return n; } @@ -2381,6 +3400,34 @@ build().cloneInto(n, true); return n; } + + private int getBaseLayoutResource() { + return R.layout.notification_template_material_base; + } + + private int getBigBaseLayoutResource() { + return R.layout.notification_template_material_big_base; + } + + private int getBigPictureLayoutResource() { + return R.layout.notification_template_material_big_picture; + } + + private int getBigTextLayoutResource() { + return R.layout.notification_template_material_big_text; + } + + private int getInboxLayoutResource() { + return R.layout.notification_template_material_inbox; + } + + private int getActionLayoutResource() { + return R.layout.notification_material_action; + } + + private int getActionTombstoneLayoutResource() { + return R.layout.notification_material_action_tombstone; + } } /** @@ -2389,8 +3436,16 @@ */ public static abstract class Style { private CharSequence mBigContentTitle; - private CharSequence mSummaryText = null; - private boolean mSummaryTextSet = false; + + /** + * @hide + */ + protected CharSequence mSummaryText = null; + + /** + * @hide + */ + protected boolean mSummaryTextSet = false; protected Builder mBuilder; @@ -2428,12 +3483,16 @@ protected RemoteViews getStandardView(int layoutId) { checkBuilder(); + // Nasty. + CharSequence oldBuilderContentTitle = mBuilder.mContentTitle; if (mBigContentTitle != null) { mBuilder.setContentTitle(mBigContentTitle); } RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId); + mBuilder.mContentTitle = oldBuilderContentTitle; + if (mBigContentTitle != null && mBigContentTitle.equals("")) { contentView.setViewVisibility(R.id.line1, View.GONE); } else { @@ -2445,10 +3504,12 @@ mSummaryTextSet ? mSummaryText : mBuilder.mSubText; if (overflowText != null) { - contentView.setTextViewText(R.id.text, overflowText); + contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(overflowText)); contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE); contentView.setViewVisibility(R.id.line3, View.VISIBLE); } else { + // Clear text in case we use the line to show the profile badge. + contentView.setTextViewText(R.id.text, ""); contentView.setViewVisibility(R.id.overflow_divider, View.GONE); contentView.setViewVisibility(R.id.line3, View.GONE); } @@ -2457,6 +3518,19 @@ } /** + * Changes the padding of the first line such that the big and small content view have the + * same top padding. + * + * @hide + */ + protected void applyTopPadding(RemoteViews contentView) { + int topPadding = Builder.calculateTopPadding(mBuilder.mContext, + mBuilder.mHasThreeLines, + mBuilder.mContext.getResources().getConfiguration().fontScale); + contentView.setViewPadding(R.id.line1, 0, topPadding, 0, 0); + } + + /** * @hide */ public void addExtras(Bundle extras) { @@ -2466,12 +3540,53 @@ if (mBigContentTitle != null) { extras.putCharSequence(EXTRA_TITLE_BIG, mBigContentTitle); } + extras.putString(EXTRA_TEMPLATE, this.getClass().getName()); } /** * @hide */ - public abstract Notification buildStyled(Notification wip); + protected void restoreFromExtras(Bundle extras) { + if (extras.containsKey(EXTRA_SUMMARY_TEXT)) { + mSummaryText = extras.getCharSequence(EXTRA_SUMMARY_TEXT); + mSummaryTextSet = true; + } + if (extras.containsKey(EXTRA_TITLE_BIG)) { + mBigContentTitle = extras.getCharSequence(EXTRA_TITLE_BIG); + } + } + + + /** + * @hide + */ + public Notification buildStyled(Notification wip) { + populateTickerView(wip); + populateContentView(wip); + populateBigContentView(wip); + populateHeadsUpContentView(wip); + return wip; + } + + // The following methods are split out so we can re-create notification partially. + /** + * @hide + */ + protected void populateTickerView(Notification wip) {} + /** + * @hide + */ + protected void populateContentView(Notification wip) {} + + /** + * @hide + */ + protected void populateBigContentView(Notification wip) {} + + /** + * @hide + */ + protected void populateHeadsUpContentView(Notification wip) {} /** * Calls {@link android.app.Notification.Builder#build()} on the Builder this Style is @@ -2483,6 +3598,15 @@ checkBuilder(); return mBuilder.build(); } + + /** + * @hide + * @return true if the style positions the progress bar on the second line; false if the + * style hides the progress bar + */ + protected boolean hasProgress() { + return true; + } } /** @@ -2549,10 +3673,15 @@ } private RemoteViews makeBigContentView() { - RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture); + RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource()); contentView.setImageViewBitmap(R.id.big_picture, mPicture); + applyTopPadding(contentView); + + boolean twoTextLines = mBuilder.mSubText != null && mBuilder.mContentText != null; + mBuilder.addProfileBadge(contentView, + twoTextLines ? R.id.profile_badge_line2 : R.id.profile_badge_line3); return contentView; } @@ -2572,12 +3701,21 @@ * @hide */ @Override - public Notification buildStyled(Notification wip) { - if (mBigLargeIconSet ) { - mBuilder.mLargeIcon = mBigLargeIcon; + protected void restoreFromExtras(Bundle extras) { + super.restoreFromExtras(extras); + + if (extras.containsKey(EXTRA_LARGE_ICON_BIG)) { + mBigLargeIcon = extras.getParcelable(EXTRA_LARGE_ICON_BIG); } - wip.bigContentView = makeBigContentView(); - return wip; + mPicture = extras.getParcelable(EXTRA_PICTURE); + } + + /** + * @hide + */ + @Override + public void populateBigContentView(Notification wip) { + mBuilder.setBuilderBigContentView(wip, makeBigContentView()); } } @@ -2599,6 +3737,11 @@ * @see Notification#bigContentView */ public static class BigTextStyle extends Style { + + private static final int MAX_LINES = 13; + private static final int LINES_CONSUMED_BY_ACTIONS = 3; + private static final int LINES_CONSUMED_BY_SUMMARY = 2; + private CharSequence mBigText; public BigTextStyle() { @@ -2640,38 +3783,67 @@ public void addExtras(Bundle extras) { super.addExtras(extras); - extras.putCharSequence(EXTRA_TEXT, mBigText); - } - - private RemoteViews makeBigContentView() { - // Remove the content text so line3 only shows if you have a summary - final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null); - mBuilder.mContentText = null; - - RemoteViews contentView = getStandardView(R.layout.notification_template_big_text); - - if (hadThreeLines) { - // vertical centering - contentView.setViewPadding(R.id.line1, 0, 0, 0, 0); - } - - contentView.setTextViewText(R.id.big_text, mBigText); - contentView.setViewVisibility(R.id.big_text, View.VISIBLE); - contentView.setViewVisibility(R.id.text2, View.GONE); - - return contentView; + extras.putCharSequence(EXTRA_BIG_TEXT, mBigText); } /** * @hide */ @Override - public Notification buildStyled(Notification wip) { - wip.bigContentView = makeBigContentView(); + protected void restoreFromExtras(Bundle extras) { + super.restoreFromExtras(extras); - wip.extras.putCharSequence(EXTRA_TEXT, mBigText); + mBigText = extras.getCharSequence(EXTRA_BIG_TEXT); + } - return wip; + private RemoteViews makeBigContentView() { + + // Nasty + CharSequence oldBuilderContentText = mBuilder.mContentText; + mBuilder.mContentText = null; + + RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource()); + + mBuilder.mContentText = oldBuilderContentText; + + contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText)); + contentView.setViewVisibility(R.id.big_text, View.VISIBLE); + contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines()); + contentView.setViewVisibility(R.id.text2, View.GONE); + + applyTopPadding(contentView); + + mBuilder.shrinkLine3Text(contentView); + + mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template); + + return contentView; + } + + private int calculateMaxLines() { + int lineCount = MAX_LINES; + boolean hasActions = mBuilder.mActions.size() > 0; + boolean hasSummary = (mSummaryTextSet ? mSummaryText : mBuilder.mSubText) != null; + if (hasActions) { + lineCount -= LINES_CONSUMED_BY_ACTIONS; + } + if (hasSummary) { + lineCount -= LINES_CONSUMED_BY_SUMMARY; + } + + // If we have less top padding at the top, we can fit less lines. + if (!mBuilder.mHasThreeLines) { + lineCount--; + } + return lineCount; + } + + /** + * @hide + */ + @Override + public void populateBigContentView(Notification wip) { + mBuilder.setBuilderBigContentView(wip, makeBigContentView()); } } @@ -2735,14 +3907,34 @@ */ public void addExtras(Bundle extras) { super.addExtras(extras); + CharSequence[] a = new CharSequence[mTexts.size()]; extras.putCharSequenceArray(EXTRA_TEXT_LINES, mTexts.toArray(a)); } + /** + * @hide + */ + @Override + protected void restoreFromExtras(Bundle extras) { + super.restoreFromExtras(extras); + + mTexts.clear(); + if (extras.containsKey(EXTRA_TEXT_LINES)) { + Collections.addAll(mTexts, extras.getCharSequenceArray(EXTRA_TEXT_LINES)); + } + } + private RemoteViews makeBigContentView() { // Remove the content text so line3 disappears unless you have a summary + + // Nasty + CharSequence oldBuilderContentText = mBuilder.mContentText; mBuilder.mContentText = null; - RemoteViews contentView = getStandardView(R.layout.notification_template_inbox); + + RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource()); + + mBuilder.mContentText = oldBuilderContentText; contentView.setViewVisibility(R.id.text2, View.GONE); @@ -2754,13 +3946,20 @@ contentView.setViewVisibility(rowId, View.GONE); } - + final boolean largeText = + mBuilder.mContext.getResources().getConfiguration().fontScale > 1f; + final float subTextSize = mBuilder.mContext.getResources().getDimensionPixelSize( + R.dimen.notification_subtext_size); int i=0; while (i < mTexts.size() && i < rowIds.length) { CharSequence str = mTexts.get(i); if (str != null && !str.equals("")) { contentView.setViewVisibility(rowIds[i], View.VISIBLE); - contentView.setTextViewText(rowIds[i], str); + contentView.setTextViewText(rowIds[i], mBuilder.processLegacyText(str)); + if (largeText) { + contentView.setTextViewTextSize(rowIds[i], TypedValue.COMPLEX_UNIT_PX, + subTextSize); + } } i++; } @@ -2771,6 +3970,12 @@ contentView.setViewVisibility(R.id.inbox_more, mTexts.size() > rowIds.length ? View.VISIBLE : View.GONE); + applyTopPadding(contentView); + + mBuilder.shrinkLine3Text(contentView); + + mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template); + return contentView; } @@ -2778,14 +3983,247 @@ * @hide */ @Override - public Notification buildStyled(Notification wip) { - wip.bigContentView = makeBigContentView(); - - return wip; + public void populateBigContentView(Notification wip) { + mBuilder.setBuilderBigContentView(wip, makeBigContentView()); } } /** + * Notification style for media playback notifications. + * + * In the expanded form, {@link Notification#bigContentView}, up to 5 + * {@link Notification.Action}s specified with + * {@link Notification.Builder#addAction(int, CharSequence, PendingIntent) addAction} will be + * shown as icon-only pushbuttons, suitable for transport controls. The Bitmap given to + * {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap) setLargeIcon()} will be + * treated as album artwork. + * + * Unlike the other styles provided here, MediaStyle can also modify the standard-size + * {@link Notification#contentView}; by providing action indices to + * {@link #setShowActionsInCompactView(int...)} you can promote up to 2 actions to be displayed + * in the standard view alongside the usual content. + * + * Notifications created with MediaStyle will have their category set to + * {@link Notification#CATEGORY_TRANSPORT CATEGORY_TRANSPORT} unless you set a different + * category using {@link Notification.Builder#setCategory(String) setCategory()}. + * + * Finally, if you attach a {@link android.media.session.MediaSession.Token} using + * {@link android.app.Notification.MediaStyle#setMediaSession(MediaSession.Token)}, + * the System UI can identify this as a notification representing an active media session + * and respond accordingly (by showing album artwork in the lockscreen, for example). + * + * To use this style with your Notification, feed it to + * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so: + * <pre class="prettyprint"> + * Notification noti = new Notification.Builder() + * .setSmallIcon(R.drawable.ic_stat_player) + * .setContentTitle("Track title") // these three lines are optional + * .setContentText("Artist - Album") // if you use + * .setLargeIcon(albumArtBitmap)) // setMediaSession(token) + * .setStyle(<b>new Notification.MediaStyle()</b> + * .setMediaSession(mySession)) + * .build(); + * </pre> + * + * @see Notification#bigContentView + */ + public static class MediaStyle extends Style { + static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3; + static final int MAX_MEDIA_BUTTONS = 5; + + private int[] mActionsToShowInCompact = null; + private MediaSession.Token mToken; + + public MediaStyle() { + } + + public MediaStyle(Builder builder) { + setBuilder(builder); + } + + /** + * Request up to 3 actions (by index in the order of addition) to be shown in the compact + * notification view. + * + * @param actions the indices of the actions to show in the compact notification view + */ + public MediaStyle setShowActionsInCompactView(int...actions) { + mActionsToShowInCompact = actions; + return this; + } + + /** + * Attach a {@link android.media.session.MediaSession.Token} to this Notification + * to provide additional playback information and control to the SystemUI. + */ + public MediaStyle setMediaSession(MediaSession.Token token) { + mToken = token; + return this; + } + + /** + * @hide + */ + @Override + public Notification buildStyled(Notification wip) { + super.buildStyled(wip); + if (wip.category == null) { + wip.category = Notification.CATEGORY_TRANSPORT; + } + return wip; + } + + /** + * @hide + */ + @Override + public void populateContentView(Notification wip) { + mBuilder.setBuilderContentView(wip, makeMediaContentView()); + } + + /** + * @hide + */ + @Override + public void populateBigContentView(Notification wip) { + mBuilder.setBuilderBigContentView(wip, makeMediaBigContentView()); + } + + /** @hide */ + @Override + public void addExtras(Bundle extras) { + super.addExtras(extras); + + if (mToken != null) { + extras.putParcelable(EXTRA_MEDIA_SESSION, mToken); + } + if (mActionsToShowInCompact != null) { + extras.putIntArray(EXTRA_COMPACT_ACTIONS, mActionsToShowInCompact); + } + } + + /** + * @hide + */ + @Override + protected void restoreFromExtras(Bundle extras) { + super.restoreFromExtras(extras); + + if (extras.containsKey(EXTRA_MEDIA_SESSION)) { + mToken = extras.getParcelable(EXTRA_MEDIA_SESSION); + } + if (extras.containsKey(EXTRA_COMPACT_ACTIONS)) { + mActionsToShowInCompact = extras.getIntArray(EXTRA_COMPACT_ACTIONS); + } + } + + private RemoteViews generateMediaActionButton(Action action) { + final boolean tombstone = (action.actionIntent == null); + RemoteViews button = new RemoteViews(mBuilder.mContext.getPackageName(), + R.layout.notification_material_media_action); + button.setImageViewResource(R.id.action0, action.icon); + button.setDrawableParameters(R.id.action0, false, -1, + 0xFFFFFFFF, + PorterDuff.Mode.SRC_ATOP, -1); + if (!tombstone) { + button.setOnClickPendingIntent(R.id.action0, action.actionIntent); + } + button.setContentDescription(R.id.action0, action.title); + return button; + } + + private RemoteViews makeMediaContentView() { + RemoteViews view = mBuilder.applyStandardTemplate( + R.layout.notification_template_material_media, false /* hasProgress */); + + final int numActions = mBuilder.mActions.size(); + final int N = mActionsToShowInCompact == null + ? 0 + : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT); + if (N > 0) { + view.removeAllViews(com.android.internal.R.id.media_actions); + for (int i = 0; i < N; i++) { + if (i >= numActions) { + throw new IllegalArgumentException(String.format( + "setShowActionsInCompactView: action %d out of bounds (max %d)", + i, numActions - 1)); + } + + final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]); + final RemoteViews button = generateMediaActionButton(action); + view.addView(com.android.internal.R.id.media_actions, button); + } + } + styleText(view); + hideRightIcon(view); + return view; + } + + private RemoteViews makeMediaBigContentView() { + final int actionCount = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS); + RemoteViews big = mBuilder.applyStandardTemplate(getBigLayoutResource(actionCount), + false /* hasProgress */); + + if (actionCount > 0) { + big.removeAllViews(com.android.internal.R.id.media_actions); + for (int i = 0; i < actionCount; i++) { + final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i)); + big.addView(com.android.internal.R.id.media_actions, button); + } + } + styleText(big); + hideRightIcon(big); + applyTopPadding(big); + big.setViewVisibility(android.R.id.progress, View.GONE); + return big; + } + + private int getBigLayoutResource(int actionCount) { + if (actionCount <= 3) { + return R.layout.notification_template_material_big_media_narrow; + } else { + return R.layout.notification_template_material_big_media; + } + } + + private void hideRightIcon(RemoteViews contentView) { + contentView.setViewVisibility(R.id.right_icon, View.GONE); + } + + /** + * Applies the special text colors for media notifications to all text views. + */ + private void styleText(RemoteViews contentView) { + int primaryColor = mBuilder.mContext.getResources().getColor( + R.color.notification_media_primary_color); + int secondaryColor = mBuilder.mContext.getResources().getColor( + R.color.notification_media_secondary_color); + contentView.setTextColor(R.id.title, primaryColor); + if (mBuilder.showsTimeOrChronometer()) { + if (mBuilder.mUseChronometer) { + contentView.setTextColor(R.id.chronometer, secondaryColor); + } else { + contentView.setTextColor(R.id.time, secondaryColor); + } + } + contentView.setTextColor(R.id.text2, secondaryColor); + contentView.setTextColor(R.id.text, secondaryColor); + contentView.setTextColor(R.id.info, secondaryColor); + } + + /** + * @hide + */ + @Override + protected boolean hasProgress() { + return false; + } + } + + // When adding a new Style subclass here, don't forget to update + // Builder.getNotificationStyleClass. + + /** * Extender interface for use with {@link Builder#extend}. Extenders may be used to add * metadata or change options on a notification builder. */ @@ -3452,4 +4890,24 @@ bundle.putParcelableArray(key, typedArray); return typedArray; } + + private static class BuilderRemoteViews extends RemoteViews { + public BuilderRemoteViews(Parcel parcel) { + super(parcel); + } + + public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) { + super(appInfo, layoutId); + } + + @Override + public BuilderRemoteViews clone() { + Parcel p = Parcel.obtain(); + writeToParcel(p, 0); + p.setDataPosition(0); + BuilderRemoteViews brv = new BuilderRemoteViews(p); + p.recycle(); + return brv; + } + } }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 3ee4306..7dc1ad64 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java
@@ -16,7 +16,11 @@ package android.app; +import android.annotation.SdkConstant; +import android.app.Notification.Builder; +import android.content.ComponentName; import android.content.Context; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; @@ -71,6 +75,16 @@ private static String TAG = "NotificationManager"; private static boolean localLOGV = false; + /** + * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes. + * This broadcast is only sent to registered receivers. + * + * @hide + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED + = "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED"; + private static INotificationManager sService; /** @hide */ @@ -132,9 +146,11 @@ } } if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); + Notification stripped = notification.clone(); + Builder.stripForDelivery(stripped); try { service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id, - notification, idOut, UserHandle.myUserId()); + stripped, idOut, UserHandle.myUserId()); if (id != idOut[0]) { Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]); } @@ -157,9 +173,11 @@ } } if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); + Notification stripped = notification.clone(); + Builder.stripForDelivery(stripped); try { service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id, - notification, idOut, user.getIdentifier()); + stripped, idOut, user.getIdentifier()); if (id != idOut[0]) { Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]); } @@ -222,5 +240,29 @@ } } + /** + * @hide + */ + public ComponentName getEffectsSuppressor() { + INotificationManager service = getService(); + try { + return service.getEffectsSuppressor(); + } catch (RemoteException e) { + return null; + } + } + + /** + * @hide + */ + public boolean matchesCallFilter(Bundle extras) { + INotificationManager service = getService(); + try { + return service.matchesCallFilter(extras); + } catch (RemoteException e) { + return false; + } + } + private Context mContext; }
diff --git a/core/java/android/app/OnActivityPausedListener.java b/core/java/android/app/OnActivityPausedListener.java index 379f133..5003973 100644 --- a/core/java/android/app/OnActivityPausedListener.java +++ b/core/java/android/app/OnActivityPausedListener.java
@@ -5,7 +5,7 @@ * 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 + * 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,
diff --git a/core/java/android/app/PackageDeleteObserver.java b/core/java/android/app/PackageDeleteObserver.java new file mode 100644 index 0000000..9b83ec1 --- /dev/null +++ b/core/java/android/app/PackageDeleteObserver.java
@@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Intent; +import android.content.pm.IPackageDeleteObserver2; + +/** {@hide} */ +public class PackageDeleteObserver { + private final IPackageDeleteObserver2.Stub mBinder = new IPackageDeleteObserver2.Stub() { + @Override + public void onUserActionRequired(Intent intent) { + PackageDeleteObserver.this.onUserActionRequired(intent); + } + + @Override + public void onPackageDeleted(String basePackageName, int returnCode, String msg) { + PackageDeleteObserver.this.onPackageDeleted(basePackageName, returnCode, msg); + } + }; + + /** {@hide} */ + public IPackageDeleteObserver2 getBinder() { + return mBinder; + } + + public void onUserActionRequired(Intent intent) { + } + + public void onPackageDeleted(String basePackageName, int returnCode, String msg) { + } +}
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java new file mode 100644 index 0000000..ff28679 --- /dev/null +++ b/core/java/android/app/PackageInstallObserver.java
@@ -0,0 +1,65 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Intent; +import android.content.pm.IPackageInstallObserver2; +import android.os.Bundle; + +/** {@hide} */ +public class PackageInstallObserver { + private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() { + @Override + public void onUserActionRequired(Intent intent) { + PackageInstallObserver.this.onUserActionRequired(intent); + } + + @Override + public void onPackageInstalled(String basePackageName, int returnCode, + String msg, Bundle extras) { + PackageInstallObserver.this.onPackageInstalled(basePackageName, returnCode, msg, + extras); + } + }; + + /** {@hide} */ + public IPackageInstallObserver2 getBinder() { + return mBinder; + } + + public void onUserActionRequired(Intent intent) { + } + + /** + * This method will be called to report the result of the package + * installation attempt. + * + * @param basePackageName Name of the package whose installation was + * attempted + * @param extras If non-null, this Bundle contains extras providing + * additional information about an install failure. See + * {@link android.content.pm.PackageManager} for documentation + * about which extras apply to various failures; in particular + * the strings named EXTRA_FAILURE_*. + * @param returnCode The numeric success or failure code indicating the + * basic outcome + * @hide + */ + public void onPackageInstalled(String basePackageName, int returnCode, String msg, + Bundle extras) { + } +}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 7129e9e..cf14202 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java
@@ -16,6 +16,9 @@ package android.app; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.Intent; import android.content.IIntentReceiver; @@ -30,6 +33,9 @@ import android.os.UserHandle; import android.util.AndroidException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * A description of an Intent and target action to perform with it. Instances * of this class are created with {@link #getActivity}, {@link #getActivities}, @@ -86,6 +92,26 @@ public final class PendingIntent implements Parcelable { private final IIntentSender mTarget; + /** @hide */ + @IntDef(flag = true, + value = { + FLAG_ONE_SHOT, + FLAG_NO_CREATE, + FLAG_CANCEL_CURRENT, + FLAG_UPDATE_CURRENT, + + Intent.FILL_IN_ACTION, + Intent.FILL_IN_DATA, + Intent.FILL_IN_CATEGORIES, + Intent.FILL_IN_COMPONENT, + Intent.FILL_IN_PACKAGE, + Intent.FILL_IN_SOURCE_BOUNDS, + Intent.FILL_IN_SELECTOR, + Intent.FILL_IN_CLIP_DATA + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Flags {} + /** * Flag indicating that this PendingIntent can be used only once. * For use with {@link #getActivity}, {@link #getBroadcast}, and @@ -222,7 +248,7 @@ * supplied. */ public static PendingIntent getActivity(Context context, int requestCode, - Intent intent, int flags) { + Intent intent, @Flags int flags) { return getActivity(context, requestCode, intent, flags, null); } @@ -255,7 +281,7 @@ * supplied. */ public static PendingIntent getActivity(Context context, int requestCode, - Intent intent, int flags, Bundle options) { + @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; @@ -280,7 +306,7 @@ * activity is started, not when the pending intent is created. */ public static PendingIntent getActivityAsUser(Context context, int requestCode, - Intent intent, int flags, Bundle options, UserHandle user) { + @NonNull Intent intent, int flags, Bundle options, UserHandle user) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; @@ -345,7 +371,7 @@ * supplied. */ public static PendingIntent getActivities(Context context, int requestCode, - Intent[] intents, int flags) { + @NonNull Intent[] intents, @Flags int flags) { return getActivities(context, requestCode, intents, flags, null); } @@ -395,7 +421,7 @@ * supplied. */ public static PendingIntent getActivities(Context context, int requestCode, - Intent[] intents, int flags, Bundle options) { + @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options) { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { @@ -421,7 +447,7 @@ * activity is started, not when the pending intent is created. */ public static PendingIntent getActivitiesAsUser(Context context, int requestCode, - Intent[] intents, int flags, Bundle options, UserHandle user) { + @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { @@ -465,7 +491,7 @@ * supplied. */ public static PendingIntent getBroadcast(Context context, int requestCode, - Intent intent, int flags) { + Intent intent, @Flags int flags) { return getBroadcastAsUser(context, requestCode, intent, flags, new UserHandle(UserHandle.myUserId())); } @@ -519,7 +545,7 @@ * supplied. */ public static PendingIntent getService(Context context, int requestCode, - Intent intent, int flags) { + @NonNull Intent intent, @Flags int flags) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; @@ -749,6 +775,7 @@ * @return The package name of the PendingIntent, or null if there is * none associated with it. */ + @Nullable public String getCreatorPackage() { try { return ActivityManagerNative.getDefault() @@ -807,6 +834,7 @@ * @return The user handle of the PendingIntent, or null if there is * none associated with it. */ + @Nullable public UserHandle getCreatorUserHandle() { try { int uid = ActivityManagerNative.getDefault() @@ -861,6 +889,20 @@ } /** + * @hide + * Return descriptive tag for this PendingIntent. + */ + public String getTag(String prefix) { + try { + return ActivityManagerNative.getDefault() + .getTagForIntentSender(mTarget, prefix); + } catch (RemoteException e) { + // Should never happen. + return null; + } + } + + /** * Comparison operator on two PendingIntent objects, such that true * is returned then they both represent the same operation from the * same package. This allows you to use {@link #getActivity}, @@ -922,8 +964,8 @@ * @param sender The PendingIntent to write, or null. * @param out Where to write the PendingIntent. */ - public static void writePendingIntentOrNullToParcel(PendingIntent sender, - Parcel out) { + public static void writePendingIntentOrNullToParcel(@Nullable PendingIntent sender, + @NonNull Parcel out) { out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() : null); } @@ -938,7 +980,8 @@ * @return Returns the Messenger read from the Parcel, or null if null had * been written. */ - public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) { + @Nullable + public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) { IBinder b = in.readStrongBinder(); return b != null ? new PendingIntent(b) : null; }
diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java new file mode 100644 index 0000000..cea7c3c --- /dev/null +++ b/core/java/android/app/ProfilerInfo.java
@@ -0,0 +1,86 @@ +/* + * Copyright (C) 2014 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; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.ParcelFileDescriptor; + +/** + * System private API for passing profiler settings. + * + * {@hide} + */ +public class ProfilerInfo implements Parcelable { + + /* Name of profile output file. */ + public final String profileFile; + + /* File descriptor for profile output file, can be null. */ + public ParcelFileDescriptor profileFd; + + /* Indicates sample profiling when nonzero, interval in microseconds. */ + public final int samplingInterval; + + /* Automatically stop the profiler when the app goes idle. */ + public final boolean autoStopProfiler; + + public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop) { + profileFile = filename; + profileFd = fd; + samplingInterval = interval; + autoStopProfiler = autoStop; + } + + public int describeContents() { + if (profileFd != null) { + return profileFd.describeContents(); + } else { + return 0; + } + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(profileFile); + if (profileFd != null) { + out.writeInt(1); + profileFd.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + out.writeInt(samplingInterval); + out.writeInt(autoStopProfiler ? 1 : 0); + } + + public static final Parcelable.Creator<ProfilerInfo> CREATOR = + new Parcelable.Creator<ProfilerInfo>() { + public ProfilerInfo createFromParcel(Parcel in) { + return new ProfilerInfo(in); + } + + public ProfilerInfo[] newArray(int size) { + return new ProfilerInfo[size]; + } + }; + + private ProfilerInfo(Parcel in) { + profileFile = in.readString(); + profileFd = in.readInt() != 0 ? ParcelFileDescriptor.CREATOR.createFromParcel(in) : null; + samplingInterval = in.readInt(); + autoStopProfiler = in.readInt() != 0; + } +}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 728f372..1691d8e 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java
@@ -144,14 +144,16 @@ * Creates the top level Resources for applications with the given compatibility info. * * @param resDir the resource directory. + * @param overlayDirs the resource overlay directories. + * @param libDirs the shared library resource dirs this app references. * @param compatInfo the compability info. Must not be null. * @param token the application token for determining stack bounds. */ - public Resources getTopLevelResources(String resDir, String[] overlayDirs, int displayId, + public Resources getTopLevelResources(String resDir, String[] splitResDirs, + String[] overlayDirs, String[] libDirs, int displayId, Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) { final float scale = compatInfo.applicationScale; - ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, - token); + ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, token); Resources r; synchronized (this) { // Resources is app scale dependent. @@ -176,8 +178,21 @@ //} AssetManager assets = new AssetManager(); - if (assets.addAssetPath(resDir) == 0) { - return null; + // resDir can be null if the 'android' package is creating a new Resources object. + // This is fine, since each AssetManager automatically loads the 'android' package + // already. + if (resDir != null) { + if (assets.addAssetPath(resDir) == 0) { + return null; + } + } + + if (splitResDirs != null) { + for (String splitResDir : splitResDirs) { + if (assets.addAssetPath(splitResDir) == 0) { + return null; + } + } } if (overlayDirs != null) { @@ -186,6 +201,15 @@ } } + if (libDirs != null) { + for (String libDir : libDirs) { + if (assets.addAssetPath(libDir) == 0) { + Slog.w(TAG, "Asset path '" + libDir + + "' does not exist or contains no resources."); + } + } + } + //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); DisplayMetrics dm = getDisplayMetricsLocked(displayId); Configuration config;
diff --git a/core/java/android/app/ResultInfo.java b/core/java/android/app/ResultInfo.java index 48a0fc2..5e0867c 100644 --- a/core/java/android/app/ResultInfo.java +++ b/core/java/android/app/ResultInfo.java
@@ -17,12 +17,8 @@ package android.app; import android.content.Intent; -import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; -import android.os.Bundle; - -import java.util.Map; /** * {@hide}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index d04e9db..af1810b 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java
@@ -188,8 +188,7 @@ mSearchView.findViewById(com.android.internal.R.id.search_src_text); mAppIcon = (ImageView) findViewById(com.android.internal.R.id.search_app_icon); mSearchPlate = mSearchView.findViewById(com.android.internal.R.id.search_plate); - mWorkingSpinner = getContext().getResources(). - getDrawable(com.android.internal.R.drawable.search_spinner); + mWorkingSpinner = getContext().getDrawable(com.android.internal.R.drawable.search_spinner); // TODO: Restore the spinner for slow suggestion lookups // mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds( // null, null, mWorkingSpinner, null); @@ -458,7 +457,7 @@ // optionally show one or the other. if (mSearchable.useBadgeIcon()) { - icon = mActivityContext.getResources().getDrawable(mSearchable.getIconId()); + icon = mActivityContext.getDrawable(mSearchable.getIconId()); visibility = View.VISIBLE; if (DBG) Log.d(LOG_TAG, "Using badge icon: " + mSearchable.getIconId()); } else if (mSearchable.useBadgeLabel()) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index f9c245e..261b15d 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java
@@ -22,7 +22,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Rect; @@ -34,7 +33,6 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; -import android.util.Slog; import android.view.KeyEvent; import java.util.List; @@ -255,6 +253,7 @@ * for more information on these schemes. */ public final static String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1"; + /** * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, * then all suggestions will be provided in a format that includes space for two small icons, @@ -271,6 +270,24 @@ * for more information on these schemes. */ public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, + * then the image will be displayed when forming the suggestion. The suggested dimension for + * the image is 270x400 px for portrait mode and 400x225 px for landscape mode. The data in the + * column must be a resource ID of a drawable, or a URI in one of the following formats: + * + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * + * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} + * for more information on these schemes. + */ + public final static String SUGGEST_COLUMN_RESULT_CARD_IMAGE = "suggest_result_card_image"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the action that will be used when @@ -281,6 +298,7 @@ * it from the cursor. */ public final static String SUGGEST_COLUMN_INTENT_ACTION = "suggest_intent_action"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the data that will be used when @@ -291,6 +309,7 @@ * it is more efficient to specify it using XML metadata and omit it from the cursor. */ public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the data that will be used when @@ -299,6 +318,7 @@ * an extra under the key {@link #EXTRA_DATA_KEY}. */ public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, then "/" and this value will be appended to the data @@ -306,6 +326,7 @@ * appropriate base string. */ public final static String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id"; + /** * Column name for suggestions cursor. <i>Required if action is * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</i> If this @@ -333,6 +354,89 @@ "suggest_spinner_while_refreshing"; /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is media type, you + * should provide this column so search app could understand more about your content. The data + * in the column must specify the MIME type of the content. + */ + public final static String SUGGEST_COLUMN_CONTENT_TYPE = "suggest_content_type"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is media type, you + * should provide this column to specify whether your content is live media such as live video + * or live audio. The value in the column is of integer type with value of either 0 indicating + * non-live content or 1 indicating live content. + */ + public final static String SUGGEST_COLUMN_IS_LIVE = "suggest_is_live"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video, you should + * provide this column to specify the number of vertical lines. The data in the column is of + * integer type. + */ + public final static String SUGGEST_COLUMN_VIDEO_WIDTH = "suggest_video_width"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video, you should + * provide this column to specify the number of horizontal lines. The data in the column is of + * integer type. + */ + public final static String SUGGEST_COLUMN_VIDEO_HEIGHT = "suggest_video_height"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content contains audio, you + * should provide this column to specify the audio channel configuration. The data in the + * column is string with format like "channels.subchannels" such as "1.0" or "5.1". + */ + public final static String SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG = "suggest_audio_channel_config"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is purchasable, you + * should provide this column to specify the displayable string representation of the purchase + * price of your content including the currency and the amount. If it's free, you should + * provide localized string to specify that it's free. This column can be omitted if the content + * is not applicable to purchase. + */ + public final static String SUGGEST_COLUMN_PURCHASE_PRICE = "suggest_purchase_price"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is rentable, you + * should provide this column to specify the displayable string representation of the rental + * price of your content including the currency and the amount. If it's free, you should + * provide localized string to specify that it's free. This column can be ommitted if the + * content is not applicable to rent. + */ + public final static String SUGGEST_COLUMN_RENTAL_PRICE = "suggest_rental_price"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content has a rating, you + * should provide this column to specify the rating style of your content. The data in the + * column must be one of the constant values specified in {@link android.media.Rating} + */ + public final static String SUGGEST_COLUMN_RATING_STYLE = "suggest_rating_style"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content has a rating, you + * should provide this column to specify the rating score of your content. The data in the + * column is of float type. See {@link android.media.Rating} about valid rating scores for each + * rating style. + */ + public final static String SUGGEST_COLUMN_RATING_SCORE = "suggest_rating_score"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video or audio and + * has a known production year, you should provide this column to specify the production year + * of your content. The data in the column is of integer type. + */ + public final static String SUGGEST_COLUMN_PRODUCTION_YEAR = "suggest_production_year"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video or audio, you + * should provide this column to specify the duration of your content in milliseconds. The data + * in the column is of long type. + */ + public final static String SUGGEST_COLUMN_DURATION = "suggest_duration"; + + /** * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify * additional flags per item. Multiple flags can be specified. * <p>
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 3967740..ec9960d 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java
@@ -401,7 +401,7 @@ /** * This flag is set in {@link #onStartCommand} if the Intent is a - * a retry because the original attempt never got to or returned from + * retry because the original attempt never got to or returned from * {@link #onStartCommand(Intent, int, int)}. */ public static final int START_FLAG_RETRY = 0x0002;
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java new file mode 100644 index 0000000..060bbe6 --- /dev/null +++ b/core/java/android/app/SharedElementCallback.java
@@ -0,0 +1,180 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; +import android.os.Parcelable; +import android.transition.TransitionUtils; +import android.view.View; + +import java.util.List; +import java.util.Map; + +/** + * Listener provided in + * {@link Activity#setEnterSharedElementCallback(SharedElementCallback)} and + * {@link Activity#setExitSharedElementCallback(SharedElementCallback)} as well as + * {@link Fragment#setEnterSharedElementCallback(SharedElementCallback)} and + * {@link Fragment#setExitSharedElementCallback(SharedElementCallback)} + * to monitor the Shared element transitions. The events can be used to customize Activity + * and Fragment Transition behavior. + */ +public abstract class SharedElementCallback { + private Matrix mTempMatrix; + + static final SharedElementCallback NULL_CALLBACK = new SharedElementCallback() { + }; + + /** + * Called immediately after the start state is set for the shared element. + * The shared element will start at the size and position of the shared element + * in the launching Activity or Fragment. + * + * @param sharedElementNames The names of the shared elements that were accepted into + * the View hierarchy. + * @param sharedElements The shared elements that are part of the View hierarchy. + * @param sharedElementSnapshots The Views containing snap shots of the shared element + * from the launching Window. These elements will not + * be part of the scene, but will be positioned relative + * to the Window decor View. This list is null for Fragment + * Transitions. + */ + public void onSharedElementStart(List<String> sharedElementNames, + List<View> sharedElements, List<View> sharedElementSnapshots) {} + + /** + * Called after the end state is set for the shared element, but before the end state + * is captured by the shared element transition. + * <p> + * Any customization done in + * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} + * may need to be modified to the final state of the shared element if it is not + * automatically corrected by layout. For example, rotation or scale will not + * be affected by layout and if changed in {@link #onSharedElementStart(java.util.List, + * java.util.List, java.util.List)}, it will also have to be set here again to correct + * the end state. + * </p> + * + * @param sharedElementNames The names of the shared elements that were accepted into + * the View hierarchy. + * @param sharedElements The shared elements that are part of the View hierarchy. + * @param sharedElementSnapshots The Views containing snap shots of the shared element + * from the launching Window. These elements will not + * be part of the scene, but will be positioned relative + * to the Window decor View. This list will be null for + * Fragment Transitions. + */ + public void onSharedElementEnd(List<String> sharedElementNames, + List<View> sharedElements, List<View> sharedElementSnapshots) {} + + /** + * Called after {@link #onMapSharedElements(java.util.List, java.util.Map)} when + * transferring shared elements in. Any shared elements that have no mapping will be in + * <var>rejectedSharedElements</var>. The elements remaining in + * <var>rejectedSharedElements</var> will be transitioned out of the Scene. If a + * View is removed from <var>rejectedSharedElements</var>, it must be handled by the + * <code>SharedElementCallback</code>. + * <p> + * Views in rejectedSharedElements will have their position and size set to the + * position of the calling shared element, relative to the Window decor View and contain + * snapshots of the View from the calling Activity or Fragment. This + * view may be safely added to the decor View's overlay to remain in position. + * </p> + * <p>This method is not called for Fragment Transitions. All rejected shared elements + * will be handled by the exit transition.</p> + * + * @param rejectedSharedElements Views containing visual information of shared elements + * that are not part of the entering scene. These Views + * are positioned relative to the Window decor View. A + * View removed from this list will not be transitioned + * automatically. + */ + public void onRejectSharedElements(List<View> rejectedSharedElements) {} + + /** + * Lets the SharedElementCallback adjust the mapping of shared element names to + * Views. + * + * @param names The names of all shared elements transferred from the calling Activity + * or Fragment in the order they were provided. + * @param sharedElements The mapping of shared element names to Views. The best guess + * will be filled into sharedElements based on the transitionNames. + */ + public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {} + + /** + * Creates a snapshot of a shared element to be used by the remote Activity and reconstituted + * with {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)}. A + * null return value will mean that the remote Activity will have a null snapshot View in + * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and + * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}. + * + * <p>This is not called for Fragment Transitions.</p> + * + * @param sharedElement The shared element View to create a snapshot for. + * @param viewToGlobalMatrix A matrix containing a transform from the view to the screen + * coordinates. + * @param screenBounds The bounds of shared element in screen coordinate space. This is + * the bounds of the view with the viewToGlobalMatrix applied. + * @return A snapshot to send to the remote Activity to be reconstituted with + * {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)} and passed + * into {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and + * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}. + */ + public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix, + RectF screenBounds) { + if (mTempMatrix == null) { + mTempMatrix = new Matrix(viewToGlobalMatrix); + } else { + mTempMatrix.set(viewToGlobalMatrix); + } + return TransitionUtils.createViewBitmap(sharedElement, mTempMatrix, screenBounds); + } + + /** + * Reconstitutes a snapshot View from a Parcelable returned in + * {@link #onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, + * android.graphics.RectF)} to be used in {@link #onSharedElementStart(java.util.List, + * java.util.List, java.util.List)} and {@link #onSharedElementEnd(java.util.List, + * java.util.List, java.util.List)}. The returned View will be sized and positioned after + * this call so that it is ready to be added to the decor View's overlay. + * + * <p>This is not called for Fragment Transitions.</p> + * + * @param context The Context used to create the snapshot View. + * @param snapshot The Parcelable returned by {@link #onCaptureSharedElementSnapshot( + * android.view.View, android.graphics.Matrix, android.graphics.RectF)}. + * @return A View to be sent in {@link #onSharedElementStart(java.util.List, java.util.List, + * java.util.List)} and {@link #onSharedElementEnd(java.util.List, java.util.List, + * java.util.List)}. A null value will produce a null snapshot value for those two methods. + */ + public View onCreateSnapshotView(Context context, Parcelable snapshot) { + View view = null; + if (snapshot instanceof Bitmap) { + Bitmap bitmap = (Bitmap) snapshot; + view = new View(context); + Resources resources = context.getResources(); + view.setBackground(new BitmapDrawable(resources, bitmap)); + } + return view; + } +}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index a8896c2..4427ce1 100644 --- a/core/java/android/app/SharedPreferencesImpl.java +++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -45,7 +45,6 @@ import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; import libcore.io.IoUtils;
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 2045ed8..ce5306f 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java
@@ -38,6 +38,7 @@ public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS; public static final int DISABLE_NOTIFICATION_ALERTS = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS; + @Deprecated public static final int DISABLE_NOTIFICATION_TICKER = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO; @@ -59,6 +60,7 @@ | DISABLE_SEARCH; public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0; + public static final int NAVIGATION_HINT_IME_SHOWN = 1 << 1; public static final int WINDOW_STATUS_BAR = 1; public static final int WINDOW_NAVIGATION_BAR = 2;
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java index 3e0ac7e..0077db1 100644 --- a/core/java/android/app/TaskStackBuilder.java +++ b/core/java/android/app/TaskStackBuilder.java
@@ -16,6 +16,7 @@ package android.app; +import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -244,7 +245,7 @@ * * @return The obtained PendingIntent */ - public PendingIntent getPendingIntent(int requestCode, int flags) { + public PendingIntent getPendingIntent(int requestCode, @PendingIntent.Flags int flags) { return getPendingIntent(requestCode, flags, null); } @@ -263,7 +264,8 @@ * * @return The obtained PendingIntent */ - public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options) { + public PendingIntent getPendingIntent(int requestCode, @PendingIntent.Flags int flags, + Bundle options) { if (mIntents.isEmpty()) { throw new IllegalStateException( "No intents added to TaskStackBuilder; cannot getPendingIntent"); @@ -294,6 +296,7 @@ * * @return An array containing the intents added to this builder. */ + @NonNull public Intent[] getIntents() { Intent[] intents = new Intent[mIntents.size()]; if (intents.length == 0) return intents;
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java index 952227f..64543673 100644 --- a/core/java/android/app/TimePickerDialog.java +++ b/core/java/android/app/TimePickerDialog.java
@@ -16,16 +16,19 @@ package android.app; -import com.android.internal.R; - import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.Bundle; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; +import android.widget.Button; import android.widget.TimePicker; import android.widget.TimePicker.OnTimeChangedListener; +import android.widget.TimePicker.ValidationCallback; + +import com.android.internal.R; /** * A dialog that prompts the user for the time of day using a {@link TimePicker}. @@ -33,12 +36,23 @@ * <p>See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> * guide.</p> */ -public class TimePickerDialog extends AlertDialog - implements OnClickListener, OnTimeChangedListener { +public class TimePickerDialog extends AlertDialog implements OnClickListener, + OnTimeChangedListener { + + private static final String HOUR = "hour"; + private static final String MINUTE = "minute"; + private static final String IS_24_HOUR = "is24hour"; + + private final TimePicker mTimePicker; + private final OnTimeSetListener mTimeSetCallback; + + private final int mInitialHourOfDay; + private final int mInitialMinute; + private final boolean mIs24HourView; /** * The callback interface used to indicate the user is done filling in - * the time (they clicked on the 'Set' button). + * the time (they clicked on the 'Done' button). */ public interface OnTimeSetListener { @@ -50,17 +64,6 @@ void onTimeSet(TimePicker view, int hourOfDay, int minute); } - private static final String HOUR = "hour"; - private static final String MINUTE = "minute"; - private static final String IS_24_HOUR = "is24hour"; - - private final TimePicker mTimePicker; - private final OnTimeSetListener mCallback; - - int mInitialHourOfDay; - int mInitialMinute; - boolean mIs24HourView; - /** * @param context Parent. * @param callBack How parent is notified. @@ -74,6 +77,16 @@ this(context, 0, callBack, hourOfDay, minute, is24HourView); } + static int resolveDialogTheme(Context context, int resid) { + if (resid == 0) { + final TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(R.attr.timePickerDialogTheme, outValue, true); + return outValue.resourceId; + } else { + return resid; + } + } + /** * @param context Parent. * @param theme the theme to apply to this dialog @@ -82,65 +95,62 @@ * @param minute The initial minute. * @param is24HourView Whether this is a 24 hour view, or AM/PM. */ - public TimePickerDialog(Context context, - int theme, - OnTimeSetListener callBack, - int hourOfDay, int minute, boolean is24HourView) { - super(context, theme); - mCallback = callBack; + public TimePickerDialog(Context context, int theme, OnTimeSetListener callBack, int hourOfDay, + int minute, boolean is24HourView) { + super(context, resolveDialogTheme(context, theme)); + + mTimeSetCallback = callBack; mInitialHourOfDay = hourOfDay; mInitialMinute = minute; mIs24HourView = is24HourView; - setIcon(0); - setTitle(R.string.time_picker_dialog_title); - - Context themeContext = getContext(); - setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_done), this); - - LayoutInflater inflater = - (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = inflater.inflate(R.layout.time_picker_dialog, null); + final Context themeContext = getContext(); + final LayoutInflater inflater = LayoutInflater.from(themeContext); + final View view = inflater.inflate(R.layout.time_picker_dialog, null); setView(view); - mTimePicker = (TimePicker) view.findViewById(R.id.timePicker); + setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this); + setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this); + setButtonPanelLayoutHint(LAYOUT_HINT_SIDE); - // initialize state + mTimePicker = (TimePicker) view.findViewById(R.id.timePicker); mTimePicker.setIs24HourView(mIs24HourView); mTimePicker.setCurrentHour(mInitialHourOfDay); mTimePicker.setCurrentMinute(mInitialMinute); mTimePicker.setOnTimeChangedListener(this); + mTimePicker.setValidationCallback(mValidationCallback); } - public void onClick(DialogInterface dialog, int which) { - tryNotifyTimeSet(); - } - - public void updateTime(int hourOfDay, int minutOfHour) { - mTimePicker.setCurrentHour(hourOfDay); - mTimePicker.setCurrentMinute(minutOfHour); - } - + @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { /* do nothing */ } - private void tryNotifyTimeSet() { - if (mCallback != null) { - mTimePicker.clearFocus(); - mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(), - mTimePicker.getCurrentMinute()); + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case BUTTON_POSITIVE: + if (mTimeSetCallback != null) { + mTimeSetCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(), + mTimePicker.getCurrentMinute()); + } + break; } } - @Override - protected void onStop() { - tryNotifyTimeSet(); - super.onStop(); + /** + * Sets the current time. + * + * @param hourOfDay The current hour within the day. + * @param minuteOfHour The current minute within the hour. + */ + public void updateTime(int hourOfDay, int minuteOfHour) { + mTimePicker.setCurrentHour(hourOfDay); + mTimePicker.setCurrentMinute(minuteOfHour); } @Override public Bundle onSaveInstanceState() { - Bundle state = super.onSaveInstanceState(); + final Bundle state = super.onSaveInstanceState(); state.putInt(HOUR, mTimePicker.getCurrentHour()); state.putInt(MINUTE, mTimePicker.getCurrentMinute()); state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView()); @@ -150,10 +160,20 @@ @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); - int hour = savedInstanceState.getInt(HOUR); - int minute = savedInstanceState.getInt(MINUTE); + final int hour = savedInstanceState.getInt(HOUR); + final int minute = savedInstanceState.getInt(MINUTE); mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR)); mTimePicker.setCurrentHour(hour); mTimePicker.setCurrentMinute(minute); } + + private final ValidationCallback mValidationCallback = new ValidationCallback() { + @Override + public void onValidationChanged(boolean valid) { + final Button positive = getButton(BUTTON_POSITIVE); + if (positive != null) { + positive.setEnabled(valid); + } + } + }; }
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 498fa42..4aec9e0 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java
@@ -26,6 +26,7 @@ import android.graphics.Point; import android.hardware.display.DisplayManagerGlobal; import android.os.Looper; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; import android.util.Log; @@ -33,12 +34,18 @@ import android.view.InputEvent; import android.view.KeyEvent; import android.view.Surface; +import android.view.WindowAnimationFrameStats; +import android.view.WindowContentFrameStats; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.IAccessibilityInteractionConnection; +import libcore.io.IoUtils; +import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeoutException; /** @@ -269,10 +276,10 @@ * @param action The action to perform. * @return Whether the action was successfully performed. * - * @see AccessibilityService#GLOBAL_ACTION_BACK - * @see AccessibilityService#GLOBAL_ACTION_HOME - * @see AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS - * @see AccessibilityService#GLOBAL_ACTION_RECENTS + * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK + * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_HOME + * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS + * @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_RECENTS */ public final boolean performGlobalAction(int action) { final IAccessibilityServiceConnection connection; @@ -293,6 +300,28 @@ } /** + * Find the view that has the specified focus type. The search is performed + * across all windows. + * <p> + * <strong>Note:</strong> In order to access the windows you have to opt-in + * to retrieve the interactive windows by setting the + * {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} flag. + * Otherwise, the search will be performed only in the active window. + * </p> + * + * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or + * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. + * @return The node info of the focused view or null. + * + * @see AccessibilityNodeInfo#FOCUS_INPUT + * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY + */ + public AccessibilityNodeInfo findFocus(int focus) { + return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, + AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus); + } + + /** * Gets the an {@link AccessibilityServiceInfo} describing this UiAutomation. * This method is useful if one wants to change some of the dynamically * configurable properties at runtime. @@ -346,6 +375,33 @@ } /** + * Gets the windows on the screen. This method returns only the windows + * that a sighted user can interact with, as opposed to all windows. + * For example, if there is a modal dialog shown and the user cannot touch + * anything behind it, then only the modal window will be reported + * (assuming it is the top one). For convenience the returned windows + * are ordered in a descending layer order, which is the windows that + * are higher in the Z-order are reported first. + * <p> + * <strong>Note:</strong> In order to access the windows you have to opt-in + * to retrieve the interactive windows by setting the + * {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} flag. + * </p> + * + * @return The windows if there are windows such, otherwise an empty list. + */ + public List<AccessibilityWindowInfo> getWindows() { + final int connectionId; + synchronized (mLock) { + throwIfNotConnectedLocked(); + connectionId = mConnectionId; + } + // Calling out without a lock held. + return AccessibilityInteractionClient.getInstance() + .getWindows(connectionId); + } + + /** * Gets the root {@link AccessibilityNodeInfo} in the active window. * * @return The root info. @@ -617,6 +673,7 @@ canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2); canvas.drawBitmap(screenShot, 0, 0, null); canvas.setBitmap(null); + screenShot.recycle(); screenShot = unrotatedScreenShot; } @@ -632,7 +689,7 @@ * potentially undesirable actions such as calling 911 or posting on public forums etc. * * @param enable whether to run in a "monkey" mode or not. Default is not. - * @see {@link ActivityManager#isUserAMonkey()} + * @see {@link android.app.ActivityManager#isUserAMonkey()} */ public void setRunAsMonkey(boolean enable) { synchronized (mLock) { @@ -645,6 +702,186 @@ } } + /** + * Clears the frame statistics for the content of a given window. These + * statistics contain information about the most recently rendered content + * frames. + * + * @param windowId The window id. + * @return Whether the window is present and its frame statistics + * were cleared. + * + * @see android.view.WindowContentFrameStats + * @see #getWindowContentFrameStats(int) + * @see #getWindows() + * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId() + */ + public boolean clearWindowContentFrameStats(int windowId) { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + if (DEBUG) { + Log.i(LOG_TAG, "Clearing content frame stats for window: " + windowId); + } + // Calling out without a lock held. + return mUiAutomationConnection.clearWindowContentFrameStats(windowId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error clearing window content frame stats!", re); + } + return false; + } + + /** + * Gets the frame statistics for a given window. These statistics contain + * information about the most recently rendered content frames. + * <p> + * A typical usage requires clearing the window frame statistics via {@link + * #clearWindowContentFrameStats(int)} followed by an interaction with the UI and + * finally getting the window frame statistics via calling this method. + * </p> + * <pre> + * // Assume we have at least one window. + * final int windowId = getWindows().get(0).getId(); + * + * // Start with a clean slate. + * uiAutimation.clearWindowContentFrameStats(windowId); + * + * // Do stuff with the UI. + * + * // Get the frame statistics. + * WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId); + * </pre> + * + * @param windowId The window id. + * @return The window frame statistics, or null if the window is not present. + * + * @see android.view.WindowContentFrameStats + * @see #clearWindowContentFrameStats(int) + * @see #getWindows() + * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId() + */ + public WindowContentFrameStats getWindowContentFrameStats(int windowId) { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + if (DEBUG) { + Log.i(LOG_TAG, "Getting content frame stats for window: " + windowId); + } + // Calling out without a lock held. + return mUiAutomationConnection.getWindowContentFrameStats(windowId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error getting window content frame stats!", re); + } + return null; + } + + /** + * Clears the window animation rendering statistics. These statistics contain + * information about the most recently rendered window animation frames, i.e. + * for window transition animations. + * + * @see android.view.WindowAnimationFrameStats + * @see #getWindowAnimationFrameStats() + * @see android.R.styleable#WindowAnimation + */ + public void clearWindowAnimationFrameStats() { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + if (DEBUG) { + Log.i(LOG_TAG, "Clearing window animation frame stats"); + } + // Calling out without a lock held. + mUiAutomationConnection.clearWindowAnimationFrameStats(); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error clearing window animation frame stats!", re); + } + } + + /** + * Gets the window animation frame statistics. These statistics contain + * information about the most recently rendered window animation frames, i.e. + * for window transition animations. + * + * <p> + * A typical usage requires clearing the window animation frame statistics via + * {@link #clearWindowAnimationFrameStats()} followed by an interaction that causes + * a window transition which uses a window animation and finally getting the window + * animation frame statistics by calling this method. + * </p> + * <pre> + * // Start with a clean slate. + * uiAutimation.clearWindowAnimationFrameStats(); + * + * // Do stuff to trigger a window transition. + * + * // Get the frame statistics. + * WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats(); + * </pre> + * + * @return The window animation frame statistics. + * + * @see android.view.WindowAnimationFrameStats + * @see #clearWindowAnimationFrameStats() + * @see android.R.styleable#WindowAnimation + */ + public WindowAnimationFrameStats getWindowAnimationFrameStats() { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + if (DEBUG) { + Log.i(LOG_TAG, "Getting window animation frame stats"); + } + // Calling out without a lock held. + return mUiAutomationConnection.getWindowAnimationFrameStats(); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error getting window animation frame stats!", re); + } + return null; + } + + /** + * Executes a shell command. This method returs a file descriptor that points + * to the standard output stream. The command execution is similar to running + * "adb shell <command>" from a host connected to the device. + * <p> + * <strong>Note:</strong> It is your responsibility to close the retunred file + * descriptor once you are done reading. + * </p> + * + * @param command The command to execute. + * @return A file descriptor to the standard output stream. + */ + public ParcelFileDescriptor executeShellCommand(String command) { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + + ParcelFileDescriptor source = null; + ParcelFileDescriptor sink = null; + + try { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + source = pipe[0]; + sink = pipe[1]; + + // Calling out without a lock held. + mUiAutomationConnection.executeShellCommand(command, sink); + } catch (IOException ioe) { + Log.e(LOG_TAG, "Error executing shell command!", ioe); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error executing shell command!", re); + } finally { + IoUtils.closeQuietly(sink); + } + + return source; + } + private static float getDegreesForRotation(int value) { switch (value) { case Surface.ROTATION_90: {
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 91b0d7c..81bcb39 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java
@@ -22,14 +22,24 @@ import android.graphics.Bitmap; import android.hardware.input.InputManager; import android.os.Binder; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.view.IWindowManager; import android.view.InputEvent; import android.view.SurfaceControl; +import android.view.WindowAnimationFrameStats; +import android.view.WindowContentFrameStats; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.IAccessibilityManager; +import libcore.io.IoUtils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; /** * This is a remote object that is passed from the shell to an instrumentation @@ -47,6 +57,9 @@ private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Service.WINDOW_SERVICE)); + private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub + .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE)); + private final Object mLock = new Object(); private final Binder mToken = new Binder(); @@ -144,6 +157,111 @@ } @Override + public boolean clearWindowContentFrameStats(int windowId) throws RemoteException { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + final long identity = Binder.clearCallingIdentity(); + try { + IBinder token = mAccessibilityManager.getWindowToken(windowId); + if (token == null) { + return false; + } + return mWindowManager.clearWindowContentFrameStats(token); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + final long identity = Binder.clearCallingIdentity(); + try { + IBinder token = mAccessibilityManager.getWindowToken(windowId); + if (token == null) { + return null; + } + return mWindowManager.getWindowContentFrameStats(token); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void clearWindowAnimationFrameStats() { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + final long identity = Binder.clearCallingIdentity(); + try { + SurfaceControl.clearAnimationFrameStats(); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public WindowAnimationFrameStats getWindowAnimationFrameStats() { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + final long identity = Binder.clearCallingIdentity(); + try { + WindowAnimationFrameStats stats = new WindowAnimationFrameStats(); + SurfaceControl.getAnimationFrameStats(stats); + return stats; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void executeShellCommand(String command, ParcelFileDescriptor sink) + throws RemoteException { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + + InputStream in = null; + OutputStream out = null; + + try { + java.lang.Process process = Runtime.getRuntime().exec(command); + + in = process.getInputStream(); + out = new FileOutputStream(sink.getFileDescriptor()); + + final byte[] buffer = new byte[8192]; + while (true) { + final int readByteCount = in.read(buffer); + if (readByteCount < 0) { + break; + } + out.write(buffer, 0, readByteCount); + } + } catch (IOException ioe) { + throw new RuntimeException("Error running shell command", ioe); + } finally { + IoUtils.closeQuietly(in); + IoUtils.closeQuietly(out); + IoUtils.closeQuietly(sink); + } + } + + @Override public void shutdown() { synchronized (mLock) { if (isConnectedLocked()) {
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index c6731c9..0a255f7 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java
@@ -123,7 +123,18 @@ * will switch to the car home activity even if we are already in car mode. */ public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 0x0001; - + + /** + * Flag for use with {@link #enableCarMode(int)}: allow sleep mode while in car mode. + * By default, when this flag is not set, the system may hold a full wake lock to keep the + * screen turned on and prevent the system from entering sleep mode while in car mode. + * Setting this flag disables such behavior and the system may enter sleep mode + * if there is no other user activity and no other wake lock held. + * Setting this flag can be relevant for a car dock application that does not require the + * screen kept on. + */ + public static final int ENABLE_CAR_MODE_ALLOW_SLEEP = 0x0002; + /** * Force device into car mode, like it had been placed in the car dock. * This will cause the device to switch to the car home UI as part of
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java new file mode 100644 index 0000000..723cb9b --- /dev/null +++ b/core/java/android/app/VoiceInteractor.java
@@ -0,0 +1,445 @@ +/* + * Copyright (C) 2014 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; + +import android.annotation.SystemApi; +import android.content.Context; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.Log; +import com.android.internal.app.IVoiceInteractor; +import com.android.internal.app.IVoiceInteractorCallback; +import com.android.internal.app.IVoiceInteractorRequest; +import com.android.internal.os.HandlerCaller; +import com.android.internal.os.SomeArgs; + +import java.util.ArrayList; + +/** + * @hide + * Interface for an {@link Activity} to interact with the user through voice. Use + * {@link android.app.Activity#getVoiceInteractor() Activity.getVoiceInteractor} + * to retrieve the interface, if the activity is currently involved in a voice interaction. + * + * <p>The voice interactor revolves around submitting voice interaction requests to the + * back-end voice interaction service that is working with the user. These requests are + * submitted with {@link #submitRequest}, providing a new instance of a + * {@link Request} subclass describing the type of operation to perform -- currently the + * possible requests are {@link ConfirmationRequest} and {@link CommandRequest}. + * + * <p>Once a request is submitted, the voice system will process it and eventually deliver + * the result to the request object. The application can cancel a pending request at any + * time. + * + * <p>The VoiceInteractor is integrated with Activity's state saving mechanism, so that + * if an activity is being restarted with retained state, it will retain the current + * VoiceInteractor and any outstanding requests. Because of this, you should always use + * {@link Request#getActivity() Request.getActivity} to get back to the activity of a + * request, rather than holding on to the activity instance yourself, either explicitly + * or implicitly through a non-static inner class. + */ +@SystemApi +public class VoiceInteractor { + static final String TAG = "VoiceInteractor"; + static final boolean DEBUG = true; + + final IVoiceInteractor mInteractor; + + Context mContext; + Activity mActivity; + + final HandlerCaller mHandlerCaller; + final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() { + @Override + public void executeMessage(Message msg) { + SomeArgs args = (SomeArgs)msg.obj; + Request request; + switch (msg.what) { + case MSG_CONFIRMATION_RESULT: + request = pullRequest((IVoiceInteractorRequest)args.arg1, true); + if (DEBUG) Log.d(TAG, "onConfirmResult: req=" + + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request + + " confirmed=" + msg.arg1 + " result=" + args.arg2); + if (request != null) { + ((ConfirmationRequest)request).onConfirmationResult(msg.arg1 != 0, + (Bundle) args.arg2); + request.clear(); + } + break; + case MSG_COMPLETE_VOICE_RESULT: + request = pullRequest((IVoiceInteractorRequest)args.arg1, true); + if (DEBUG) Log.d(TAG, "onCompleteVoice: req=" + + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request + + " result=" + args.arg1); + if (request != null) { + ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg2); + request.clear(); + } + break; + case MSG_ABORT_VOICE_RESULT: + request = pullRequest((IVoiceInteractorRequest)args.arg1, true); + if (DEBUG) Log.d(TAG, "onAbortVoice: req=" + + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request + + " result=" + args.arg1); + if (request != null) { + ((AbortVoiceRequest)request).onAbortResult((Bundle) args.arg2); + request.clear(); + } + break; + case MSG_COMMAND_RESULT: + request = pullRequest((IVoiceInteractorRequest)args.arg1, msg.arg1 != 0); + if (DEBUG) Log.d(TAG, "onCommandResult: req=" + + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request + + " result=" + args.arg2); + if (request != null) { + ((CommandRequest)request).onCommandResult((Bundle) args.arg2); + if (msg.arg1 != 0) { + request.clear(); + } + } + break; + case MSG_CANCEL_RESULT: + request = pullRequest((IVoiceInteractorRequest)args.arg1, true); + if (DEBUG) Log.d(TAG, "onCancelResult: req=" + + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request); + if (request != null) { + request.onCancel(); + request.clear(); + } + break; + } + } + }; + + final IVoiceInteractorCallback.Stub mCallback = new IVoiceInteractorCallback.Stub() { + @Override + public void deliverConfirmationResult(IVoiceInteractorRequest request, boolean confirmed, + Bundle result) { + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO( + MSG_CONFIRMATION_RESULT, confirmed ? 1 : 0, request, result)); + } + + @Override + public void deliverCompleteVoiceResult(IVoiceInteractorRequest request, Bundle result) { + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO( + MSG_COMPLETE_VOICE_RESULT, request, result)); + } + + @Override + public void deliverAbortVoiceResult(IVoiceInteractorRequest request, Bundle result) { + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO( + MSG_ABORT_VOICE_RESULT, request, result)); + } + + @Override + public void deliverCommandResult(IVoiceInteractorRequest request, boolean complete, + Bundle result) { + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO( + MSG_COMMAND_RESULT, complete ? 1 : 0, request, result)); + } + + @Override + public void deliverCancel(IVoiceInteractorRequest request) throws RemoteException { + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO( + MSG_CANCEL_RESULT, request)); + } + }; + + final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>(); + + static final int MSG_CONFIRMATION_RESULT = 1; + static final int MSG_COMPLETE_VOICE_RESULT = 2; + static final int MSG_ABORT_VOICE_RESULT = 3; + static final int MSG_COMMAND_RESULT = 4; + static final int MSG_CANCEL_RESULT = 5; + + public static abstract class Request { + IVoiceInteractorRequest mRequestInterface; + Context mContext; + Activity mActivity; + + public Request() { + } + + public void cancel() { + try { + mRequestInterface.cancel(); + } catch (RemoteException e) { + Log.w(TAG, "Voice interactor has died", e); + } + } + + public Context getContext() { + return mContext; + } + + public Activity getActivity() { + return mActivity; + } + + public void onCancel() { + } + + public void onAttached(Activity activity) { + } + + public void onDetached() { + } + + void clear() { + mRequestInterface = null; + mContext = null; + mActivity = null; + } + + abstract IVoiceInteractorRequest submit(IVoiceInteractor interactor, + String packageName, IVoiceInteractorCallback callback) throws RemoteException; + } + + public static class ConfirmationRequest extends Request { + final CharSequence mPrompt; + final Bundle mExtras; + + /** + * Confirms an operation with the user via the trusted system + * VoiceInteractionService. This allows an Activity to complete an unsafe operation that + * would require the user to touch the screen when voice interaction mode is not enabled. + * The result of the confirmation will be returned through an asynchronous call to + * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or + * {@link #onCancel()}. + * + * <p>In some cases this may be a simple yes / no confirmation or the confirmation could + * include context information about how the action will be completed + * (e.g. booking a cab might include details about how long until the cab arrives) + * so the user can give a confirmation. + * @param prompt Optional confirmation text to read to the user as the action being + * confirmed. + * @param extras Additional optional information. + */ + public ConfirmationRequest(CharSequence prompt, Bundle extras) { + mPrompt = prompt; + mExtras = extras; + } + + public void onConfirmationResult(boolean confirmed, Bundle result) { + } + + IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName, + IVoiceInteractorCallback callback) throws RemoteException { + return interactor.startConfirmation(packageName, callback, mPrompt, mExtras); + } + } + + public static class CompleteVoiceRequest extends Request { + final CharSequence mMessage; + final Bundle mExtras; + + /** + * Reports that the current interaction was successfully completed with voice, so the + * application can report the final status to the user. When the response comes back, the + * voice system has handled the request and is ready to switch; at that point the + * application can start a new non-voice activity or finish. Be sure when starting the new + * activity to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK + * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice + * interaction task. + * + * @param message Optional message to tell user about the completion status of the task. + * @param extras Additional optional information. + */ + public CompleteVoiceRequest(CharSequence message, Bundle extras) { + mMessage = message; + mExtras = extras; + } + + public void onCompleteResult(Bundle result) { + } + + IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName, + IVoiceInteractorCallback callback) throws RemoteException { + return interactor.startCompleteVoice(packageName, callback, mMessage, mExtras); + } + } + + public static class AbortVoiceRequest extends Request { + final CharSequence mMessage; + final Bundle mExtras; + + /** + * Reports that the current interaction can not be complete with voice, so the + * application will need to switch to a traditional input UI. Applications should + * only use this when they need to completely bail out of the voice interaction + * and switch to a traditional UI. When the response comes back, the voice + * system has handled the request and is ready to switch; at that point the application + * can start a new non-voice activity. Be sure when starting the new activity + * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK + * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice + * interaction task. + * + * @param message Optional message to tell user about not being able to complete + * the interaction with voice. + * @param extras Additional optional information. + */ + public AbortVoiceRequest(CharSequence message, Bundle extras) { + mMessage = message; + mExtras = extras; + } + + public void onAbortResult(Bundle result) { + } + + IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName, + IVoiceInteractorCallback callback) throws RemoteException { + return interactor.startAbortVoice(packageName, callback, mMessage, mExtras); + } + } + + public static class CommandRequest extends Request { + final String mCommand; + final Bundle mArgs; + + /** + * Execute a command using the trusted system VoiceInteractionService. + * This allows an Activity to request additional information from the user needed to + * complete an action (e.g. booking a table might have several possible times that the + * user could select from or an app might need the user to agree to a terms of service). + * The result of the confirmation will be returned through an asynchronous call to + * either {@link #onCommandResult(android.os.Bundle)} or + * {@link #onCancel()}. + * + * <p>The command is a string that describes the generic operation to be performed. + * The command will determine how the properties in extras are interpreted and the set of + * available commands is expected to grow over time. An example might be + * "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number of bags as part of + * airline check-in. (This is not an actual working example.) + * + * @param command The desired command to perform. + * @param args Additional arguments to control execution of the command. + */ + public CommandRequest(String command, Bundle args) { + mCommand = command; + mArgs = args; + } + + public void onCommandResult(Bundle result) { + } + + IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName, + IVoiceInteractorCallback callback) throws RemoteException { + return interactor.startCommand(packageName, callback, mCommand, mArgs); + } + } + + VoiceInteractor(IVoiceInteractor interactor, Context context, Activity activity, + Looper looper) { + mInteractor = interactor; + mContext = context; + mActivity = activity; + mHandlerCaller = new HandlerCaller(context, looper, mHandlerCallerCallback, true); + } + + Request pullRequest(IVoiceInteractorRequest request, boolean complete) { + synchronized (mActiveRequests) { + Request req = mActiveRequests.get(request.asBinder()); + if (req != null && complete) { + mActiveRequests.remove(request.asBinder()); + } + return req; + } + } + + private ArrayList<Request> makeRequestList() { + final int N = mActiveRequests.size(); + if (N < 1) { + return null; + } + ArrayList<Request> list = new ArrayList<Request>(N); + for (int i=0; i<N; i++) { + list.add(mActiveRequests.valueAt(i)); + } + return list; + } + + void attachActivity(Activity activity) { + if (mActivity == activity) { + return; + } + mContext = activity; + mActivity = activity; + ArrayList<Request> reqs = makeRequestList(); + if (reqs != null) { + for (int i=0; i<reqs.size(); i++) { + Request req = reqs.get(i); + req.mContext = activity; + req.mActivity = activity; + req.onAttached(activity); + } + } + } + + void detachActivity() { + ArrayList<Request> reqs = makeRequestList(); + if (reqs != null) { + for (int i=0; i<reqs.size(); i++) { + Request req = reqs.get(i); + req.onDetached(); + req.mActivity = null; + req.mContext = null; + } + } + mContext = null; + mActivity = null; + } + + public boolean submitRequest(Request request) { + try { + IVoiceInteractorRequest ireq = request.submit(mInteractor, + mContext.getOpPackageName(), mCallback); + request.mRequestInterface = ireq; + request.mContext = mContext; + request.mActivity = mActivity; + synchronized (mActiveRequests) { + mActiveRequests.put(ireq.asBinder(), request); + } + return true; + } catch (RemoteException e) { + Log.w(TAG, "Remove voice interactor service died", e); + return false; + } + } + + /** + * Queries the supported commands available from the VoiceinteractionService. + * The command is a string that describes the generic operation to be performed. + * An example might be "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number + * of bags as part of airline check-in. (This is not an actual working example.) + * + * @param commands + */ + public boolean[] supportsCommands(String[] commands) { + try { + boolean[] res = mInteractor.supportsCommands(mContext.getOpPackageName(), commands); + if (DEBUG) Log.d(TAG, "supportsCommands: cmds=" + commands + " res=" + res); + return res; + } catch (RemoteException e) { + throw new RuntimeException("Voice interactor has died", e); + } + } +}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index f87001a..8bfe6d3 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java
@@ -16,6 +16,8 @@ package android.app; +import android.annotation.SystemApi; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -41,15 +43,17 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; import android.view.WindowManagerGlobal; import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -67,6 +71,11 @@ private float mWallpaperXStep = -1; private float mWallpaperYStep = -1; + /** {@hide} */ + private static final String PROP_WALLPAPER = "ro.config.wallpaper"; + /** {@hide} */ + private static final String PROP_WALLPAPER_COMPONENT = "ro.config.wallpaper_component"; + /** * Activity Action: Show settings for choosing wallpaper. Do not use directly to construct * an intent; instead, use {@link #getCropAndSetWallpaperIntent}. @@ -220,24 +229,9 @@ private static final int MSG_CLEAR_WALLPAPER = 1; - private final Handler mHandler; - Globals(Looper looper) { IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE); mService = IWallpaperManager.Stub.asInterface(b); - mHandler = new Handler(looper) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_CLEAR_WALLPAPER: - synchronized (this) { - mWallpaper = null; - mDefaultWallpaper = null; - } - break; - } - } - }; } public void onWallpaperChanged() { @@ -246,7 +240,10 @@ * to null so if the user requests the wallpaper again then we'll * fetch it. */ - mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER); + synchronized (this) { + mWallpaper = null; + mDefaultWallpaper = null; + } } public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) { @@ -279,7 +276,6 @@ synchronized (this) { mWallpaper = null; mDefaultWallpaper = null; - mHandler.removeMessages(MSG_CLEAR_WALLPAPER); } } @@ -314,8 +310,7 @@ } private Bitmap getDefaultWallpaperLocked(Context context) { - InputStream is = context.getResources().openRawResource( - com.android.internal.R.drawable.default_wallpaper); + InputStream is = openDefaultWallpaper(context); if (is != null) { try { BitmapFactory.Options options = new BitmapFactory.Options(); @@ -413,8 +408,7 @@ horizontalAlignment = Math.max(0, Math.min(1, horizontalAlignment)); verticalAlignment = Math.max(0, Math.min(1, verticalAlignment)); - InputStream is = new BufferedInputStream( - resources.openRawResource(com.android.internal.R.drawable.default_wallpaper)); + InputStream is = new BufferedInputStream(openDefaultWallpaper(mContext)); if (is == null) { Log.e(TAG, "default wallpaper input stream is null"); @@ -439,8 +433,7 @@ } } - is = new BufferedInputStream(resources.openRawResource( - com.android.internal.R.drawable.default_wallpaper)); + is = new BufferedInputStream(openDefaultWallpaper(mContext)); RectF cropRectF; @@ -489,8 +482,7 @@ if (crop == null) { // BitmapRegionDecoder has failed, try to crop in-memory - is = new BufferedInputStream(resources.openRawResource( - com.android.internal.R.drawable.default_wallpaper)); + is = new BufferedInputStream(openDefaultWallpaper(mContext)); Bitmap fullSize = null; if (is != null) { BitmapFactory.Options options = new BitmapFactory.Options(); @@ -960,6 +952,48 @@ } /** + * Specify extra padding that the wallpaper should have outside of the display. + * That is, the given padding supplies additional pixels the wallpaper should extend + * outside of the display itself. + * @param padding The number of pixels the wallpaper should extend beyond the display, + * on its left, top, right, and bottom sides. + * @hide + */ + @SystemApi + public void setDisplayPadding(Rect padding) { + try { + if (sGlobals.mService == null) { + Log.w(TAG, "WallpaperService not running"); + } else { + sGlobals.mService.setDisplayPadding(padding); + } + } catch (RemoteException e) { + // Ignore + } + } + + /** + * Apply a raw offset to the wallpaper window. Should only be used in + * combination with {@link #setDisplayPadding(android.graphics.Rect)} when you + * have ensured that the wallpaper will extend outside of the display area so that + * it can be moved without leaving part of the display uncovered. + * @param x The offset, in pixels, to apply to the left edge. + * @param y The offset, in pixels, to apply to the top edge. + * @hide + */ + @SystemApi + public void setDisplayOffset(IBinder windowToken, int x, int y) { + try { + //Log.v(TAG, "Sending new wallpaper display offsets from app..."); + WindowManagerGlobal.getWindowSession().setWallpaperDisplayOffset( + windowToken, x, y); + //Log.v(TAG, "...app returning after sending display offset!"); + } catch (RemoteException e) { + // Ignore. + } + } + + /** * Set the position of the current wallpaper within any larger space, when * that wallpaper is visible behind the given window. The X and Y offsets * are floating point numbers ranging from 0 to 1, representing where the @@ -1052,6 +1086,53 @@ * wallpaper. */ public void clear() throws IOException { - setResource(com.android.internal.R.drawable.default_wallpaper); + setStream(openDefaultWallpaper(mContext)); + } + + /** + * Open stream representing the default static image wallpaper. + * + * @hide + */ + public static InputStream openDefaultWallpaper(Context context) { + final String path = SystemProperties.get(PROP_WALLPAPER); + if (!TextUtils.isEmpty(path)) { + final File file = new File(path); + if (file.exists()) { + try { + return new FileInputStream(file); + } catch (IOException e) { + // Ignored, fall back to platform default below + } + } + } + return context.getResources().openRawResource( + com.android.internal.R.drawable.default_wallpaper); + } + + /** + * Return {@link ComponentName} of the default live wallpaper, or + * {@code null} if none is defined. + * + * @hide + */ + public static ComponentName getDefaultWallpaperComponent(Context context) { + String flat = SystemProperties.get(PROP_WALLPAPER_COMPONENT); + if (!TextUtils.isEmpty(flat)) { + final ComponentName cn = ComponentName.unflattenFromString(flat); + if (cn != null) { + return cn; + } + } + + flat = context.getString(com.android.internal.R.string.default_wallpaper_component); + if (!TextUtils.isEmpty(flat)) { + final ComponentName cn = ComponentName.unflattenFromString(flat); + if (cn != null) { + return cn; + } + } + + return null; } }
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java index 66fc816..3074b49 100644 --- a/core/java/android/app/admin/DeviceAdminInfo.java +++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -52,6 +52,22 @@ static final String TAG = "DeviceAdminInfo"; /** + * A type of policy that this device admin can use: device owner meta-policy + * for an admin that is designated as owner of the device. + * + * @hide + */ + public static final int USES_POLICY_DEVICE_OWNER = -2; + + /** + * A type of policy that this device admin can use: profile owner meta-policy + * for admins that have been installed as owner of some user profile. + * + * @hide + */ + public static final int USES_POLICY_PROFILE_OWNER = -1; + + /** * A type of policy that this device admin can use: limit the passwords * that the user can select, via {@link DevicePolicyManager#setPasswordQuality} * and {@link DevicePolicyManager#setPasswordMinimumLength}.
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 30b65de..e9cce51 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -16,6 +16,7 @@ package android.app.admin; +import android.accounts.AccountManager; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; @@ -29,25 +30,25 @@ * Base class for implementing a device administration component. This * class provides a convenience for interpreting the raw intent actions * that are sent by the system. - * + * * <p>The callback methods, like the base * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()} * method, happen on the main thread of the process. Thus long running * operations must be done on another thread. Note that because a receiver * is done once returning from its receive function, such long-running operations * should probably be done in a {@link Service}. - * + * * <p>When publishing your DeviceAdmin subclass as a receiver, it must * handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission. A typical * manifest entry would look like:</p> - * + * * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration} - * + * * <p>The meta-data referenced here provides addition information specific * to the device administrator, as parsed by the {@link DeviceAdminInfo} class. * A typical file would be:</p> - * + * * {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data} * * <div class="special reference"> @@ -86,7 +87,7 @@ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; - + /** * A CharSequence that can be shown to the user informing them of the * impact of disabling your admin. @@ -94,7 +95,7 @@ * @see #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED */ public static final String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING"; - + /** * Action sent to a device administrator when the user has disabled * it. Upon return, the application no longer has access to the @@ -107,7 +108,7 @@ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; - + /** * Action sent to a device administrator when the user has changed the * password of their device. You can at this point check the characteristics @@ -115,7 +116,7 @@ * DevicePolicyManager.isActivePasswordSufficient()}. * You will generally * handle this in {@link DeviceAdminReceiver#onPasswordChanged}. - * + * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive * this broadcast. @@ -123,7 +124,7 @@ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED"; - + /** * Action sent to a device administrator when the user has failed at * attempted to enter the password. You can at this point check the @@ -131,7 +132,7 @@ * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts * DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally * handle this in {@link DeviceAdminReceiver#onPasswordFailed}. - * + * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive * this broadcast. @@ -139,11 +140,11 @@ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED"; - + /** * Action sent to a device administrator when the user has successfully * entered their password, after failing one or more times. - * + * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive * this broadcast. @@ -165,15 +166,73 @@ = "android.app.action.ACTION_PASSWORD_EXPIRING"; /** + * Action sent to a device administrator to notify that the device is entering + * lock task mode from an authorized package. The extra {@link #EXTRA_LOCK_TASK_PACKAGE} + * will describe the authorized package using lock task mode. + * + * @see DevicePolicyManager#isLockTaskPermitted(String) + * + * <p>The calling device admin must be the device owner or profile + * owner to receive this broadcast. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_LOCK_TASK_ENTERING + = "android.app.action.LOCK_TASK_ENTERING"; + + /** + * Action sent to a device administrator to notify that the device is exiting + * lock task mode from an authorized package. + * + * @see DevicePolicyManager#isLockTaskPermitted(String) + * + * <p>The calling device admin must be the device owner or profile + * owner to receive this broadcast. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_LOCK_TASK_EXITING + = "android.app.action.LOCK_TASK_EXITING"; + + /** + * A boolean describing whether the device is currently entering or exiting + * lock task mode. + * + * @see #ACTION_LOCK_TASK_CHANGED + */ + public static final String EXTRA_LOCK_TASK_PACKAGE = + "android.app.extra.LOCK_TASK_PACKAGE"; + + /** + * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile + * or managed device has completed successfully. + * + * <p>The broadcast is limited to the profile that will be managed by the application that + * requested provisioning. In the device owner case the profile is the primary user. + * The broadcast will also be limited to the {@link DeviceAdminReceiver} component + * specified in the original intent or NFC bump that started the provisioning process + * (@see DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE). + * + * <p>A device admin application which listens to this intent can find out if the device was + * provisioned for the device owner or profile owner case by calling respectively + * {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and + * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. + * + * <p>Input: Nothing.</p> + * <p>Output: Nothing</p> + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = + "android.app.action.PROFILE_PROVISIONING_COMPLETE"; + + /** * Name under which a DevicePolicy component publishes information * about itself. This meta-data must reference an XML resource containing * a device-admin tag. XXX TO DO: describe syntax. */ public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin"; - + private DevicePolicyManager mManager; private ComponentName mWho; - + /** * Retrieve the DevicePolicyManager interface for this administrator to work * with the system. @@ -186,7 +245,7 @@ Context.DEVICE_POLICY_SERVICE); return mManager; } - + /** * Retrieve the ComponentName describing who this device administrator is, for * use in {@link DevicePolicyManager} APIs that require the administrator to @@ -199,17 +258,23 @@ mWho = new ComponentName(context, getClass()); return mWho; } - + /** * Called after the administrator is first enabled, as a result of * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}. At this point you * can use {@link DevicePolicyManager} to set your desired policies. + * + * <p> If the admin is activated by a device owner, then the intent + * may contain private extras that are relevant to user setup. + * {@see DevicePolicyManager#createAndInitializeUser(ComponentName, String, String, + * ComponentName, Intent)} + * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. */ public void onEnabled(Context context, Intent intent) { } - + /** * Called when the user has asked to disable the administrator, as a result of * receiving {@link #ACTION_DEVICE_ADMIN_DISABLE_REQUESTED}, giving you @@ -224,7 +289,7 @@ public CharSequence onDisableRequested(Context context, Intent intent) { return null; } - + /** * Called prior to the administrator being disabled, as a result of * receiving {@link #ACTION_DEVICE_ADMIN_DISABLED}. Upon return, you @@ -235,7 +300,7 @@ */ public void onDisabled(Context context, Intent intent) { } - + /** * Called after the user has changed their password, as a result of * receiving {@link #ACTION_PASSWORD_CHANGED}. At this point you @@ -247,7 +312,7 @@ */ public void onPasswordChanged(Context context, Intent intent) { } - + /** * Called after the user has failed at entering their current password, as a result of * receiving {@link #ACTION_PASSWORD_FAILED}. At this point you @@ -258,7 +323,7 @@ */ public void onPasswordFailed(Context context, Intent intent) { } - + /** * Called after the user has succeeded at entering their current password, * as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}. This will @@ -292,6 +357,52 @@ } /** + * Called when provisioning of a managed profile or managed device has completed successfully. + * + * <p> As a prerequisit for the execution of this callback the (@link DeviceAdminReceiver} has + * to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}. + * Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN} + * of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the + * managed provisioning. + * + * <p>When provisioning is complete, the managed profile is hidden until the profile owner + * calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}. Typically a profile + * owner will enable the profile when it has finished any additional setup such as adding an + * account by using the {@link AccountManager} and calling apis to bring the profile into the + * desired state. + * + * <p> Note that provisioning completes without waiting for any server interactions, so the + * profile owner needs to wait for data to be available if required (e.g android device ids or + * other data that is set as a result of server interactions). + * + * @param context The running context as per {@link #onReceive}. + * @param intent The received intent as per {@link #onReceive}. + */ + public void onProfileProvisioningComplete(Context context, Intent intent) { + } + + /** + * Called when a device is entering lock task mode by a package authorized + * by {@link DevicePolicyManager#isLockTaskPermitted(String)} + * + * @param context The running context as per {@link #onReceive}. + * @param intent The received intent as per {@link #onReceive}. + * @param pkg If entering, the authorized package using lock task mode, otherwise null. + */ + public void onLockTaskModeEntering(Context context, Intent intent, String pkg) { + } + + /** + * Called when a device is exiting lock task mode by a package authorized + * by {@link DevicePolicyManager#isLockTaskPermitted(String)} + * + * @param context The running context as per {@link #onReceive}. + * @param intent The received intent as per {@link #onReceive}. + */ + public void onLockTaskModeExiting(Context context, Intent intent) { + } + + /** * Intercept standard device administrator broadcasts. Implementations * should not override this method; it is better to implement the * convenience callbacks for each action. @@ -299,6 +410,7 @@ @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + if (ACTION_PASSWORD_CHANGED.equals(action)) { onPasswordChanged(context, intent); } else if (ACTION_PASSWORD_FAILED.equals(action)) { @@ -317,6 +429,13 @@ onDisabled(context, intent); } else if (ACTION_PASSWORD_EXPIRING.equals(action)) { onPasswordExpiring(context, intent); + } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) { + onProfileProvisioningComplete(context, intent); + } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) { + String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE); + onLockTaskModeEntering(context, intent, pkg); + } else if (ACTION_LOCK_TASK_EXITING.equals(action)) { + onLockTaskModeExiting(context, intent); } } }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 49ed27b..2eba29a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16,33 +16,48 @@ package android.app.admin; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; +import android.app.Activity; +import android.app.admin.IDevicePolicyManager; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.net.ProxyInfo; +import android.os.Bundle; import android.os.Handler; +import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.os.UserManager; +import android.provider.Settings; +import android.security.Credentials; +import android.service.restrictions.RestrictionsReceiver; import android.util.Log; import com.android.org.conscrypt.TrustedCertificateStore; +import org.xmlpull.v1.XmlPullParserException; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Proxy; +import java.security.PrivateKey; +import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Set; /** * Public interface for managing policies enforced on a device. Most clients @@ -75,6 +90,263 @@ } /** + * Activity action: Starts the provisioning flow which sets up a managed profile. + * + * <p>A managed profile allows data separation for example for the usage of a + * device as a personal and corporate device. The user which provisioning is started from and + * the managed profile share a launcher. + * + * <p>This intent will typically be sent by a mobile device management application (mdm). + * Provisioning adds a managed profile and sets the mdm as the profile owner who has full + * control over the profile + * + * <p>This intent must contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. + * + * <p> When managed provisioning has completed, an intent of the type + * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the + * managed profile. + * + * <p> If provisioning fails, the managedProfile is removed so the device returns to its + * previous state. + * + * <p>Input: Nothing.</p> + * <p>Output: Nothing</p> + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_PROVISION_MANAGED_PROFILE + = "android.app.action.PROVISION_MANAGED_PROFILE"; + + /** + * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows + * a mobile device management application that starts managed profile provisioning to pass data + * to itself on the managed profile when provisioning completes. The mobile device management + * application sends this extra in an intent with the action + * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in + * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action + * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed + * during the managed profile provisioning. + */ + public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = + "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE"; + + /** + * A String extra holding the package name of the mobile device management application that + * will be set as the profile owner or device owner. + * + * <p>If an application starts provisioning directly via an intent with action + * {@link #ACTION_PROVISION_MANAGED_PROFILE} this package has to match the package name of the + * application that started provisioning. The package will be set as profile owner in that case. + * + * <p>This package is set as device owner when device owner provisioning is started by an Nfc + * message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}. + */ + public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME + = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME"; + + /** + * A String extra that, holds the email address of the account which a managed profile is + * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and + * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. + * + * <p> This extra is part of the {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. + * + * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning + * contains this extra, it is forwarded in the + * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile + * device management application that was set as the profile owner during provisioning. + * It is usually used to avoid that the user has to enter their email address twice. + */ + public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS + = "android.app.extra.PROVISIONING_EMAIL_ADDRESS"; + + /** + * A String extra holding the time zone {@link android.app.AlarmManager} that the device + * will be set to. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_TIME_ZONE + = "android.app.extra.PROVISIONING_TIME_ZONE"; + + /** + * A Long extra holding the wall clock time (in milliseconds) to be set on the device's + * {@link android.app.AlarmManager}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_LOCAL_TIME + = "android.app.extra.PROVISIONING_LOCAL_TIME"; + + /** + * A String extra holding the {@link java.util.Locale} that the device will be set to. + * Format: xx_yy, where xx is the language code, and yy the country code. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_LOCALE + = "android.app.extra.PROVISIONING_LOCALE"; + + /** + * A String extra holding the ssid of the wifi network that should be used during nfc device + * owner provisioning for downloading the mobile device management application. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_SSID + = "android.app.extra.PROVISIONING_WIFI_SSID"; + + /** + * A boolean extra indicating whether the wifi network in {@link #EXTRA_PROVISIONING_WIFI_SSID} + * is hidden or not. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_HIDDEN + = "android.app.extra.PROVISIONING_WIFI_HIDDEN"; + + /** + * A String extra indicating the security type of the wifi network in + * {@link #EXTRA_PROVISIONING_WIFI_SSID}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE + = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE"; + + /** + * A String extra holding the password of the wifi network in + * {@link #EXTRA_PROVISIONING_WIFI_SSID}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_PASSWORD + = "android.app.extra.PROVISIONING_WIFI_PASSWORD"; + + /** + * A String extra holding the proxy host for the wifi network in + * {@link #EXTRA_PROVISIONING_WIFI_SSID}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_PROXY_HOST + = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST"; + + /** + * An int extra holding the proxy port for the wifi network in + * {@link #EXTRA_PROVISIONING_WIFI_SSID}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_PROXY_PORT + = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT"; + + /** + * A String extra holding the proxy bypass for the wifi network in + * {@link #EXTRA_PROVISIONING_WIFI_SSID}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS + = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS"; + + /** + * A String extra holding the proxy auto-config (PAC) URL for the wifi network in + * {@link #EXTRA_PROVISIONING_WIFI_SSID}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_WIFI_PAC_URL + = "android.app.extra.PROVISIONING_WIFI_PAC_URL"; + + /** + * A String extra holding a url that specifies the download location of the device admin + * package. When not provided it is assumed that the device admin package is already installed. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION + = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION"; + + /** + * A String extra holding a http cookie header which should be used in the http request to the + * url specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER + = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER"; + + /** + * A String extra holding the SHA-1 checksum of the file at download location specified in + * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't match + * the file at the download location an error will be shown to the user and the user will be + * asked to factory reset the device. + * + * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * provisioning via an Nfc bump. + */ + public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM + = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM"; + + /** + * This MIME type is used for starting the Device Owner provisioning. + * + * <p>During device owner provisioning a device admin app is set as the owner of the device. + * A device owner has full control over the device. The device owner can not be modified by the + * user and the only way of resetting the device is if the device owner app calls a factory + * reset. + * + * <p> A typical use case would be a device that is owned by a company, but used by either an + * employee or client. + * + * <p> The Nfc message should be send to an unprovisioned device. + * + * <p>The Nfc record must contain a serialized {@link java.util.Properties} object which + * contains the following properties: + * <ul> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}</li> + * <li>{@link #EXTRA_PROVISIONING_LOCAL_TIME} (convert to String), optional</li> + * <li>{@link #EXTRA_PROVISIONING_TIME_ZONE}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_LOCALE}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_SSID}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_HIDDEN} (convert to String), optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_SECURITY_TYPE}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_PASSWORD}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li></ul> + * + * <p> When device owner provisioning has completed, an intent of the type + * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the + * device owner. + * + * <p> + * If provisioning fails, the device is factory reset. + * + * <p>Input: Nothing.</p> + * <p>Output: Nothing</p> + */ + public static final String MIME_TYPE_PROVISIONING_NFC + = "application/com.android.managedprovisioning"; + + /** * Activity action: ask the user to add a new device administrator to the system. * The desired policy is the ComponentName of the policy in the * {@link #EXTRA_DEVICE_ADMIN} extra field. This will invoke a UI to @@ -95,6 +367,40 @@ = "android.app.action.ADD_DEVICE_ADMIN"; /** + * @hide + * Activity action: ask the user to add a new device administrator as the profile owner + * for this user. Only system privileged apps that have MANAGE_USERS and MANAGE_DEVICE_ADMINS + * permission can call this API. + * + * <p>The ComponentName of the profile owner admin is pass in {@link #EXTRA_DEVICE_ADMIN} extra + * field. This will invoke a UI to bring the user through adding the profile owner admin + * to remotely control restrictions on the user. + * + * <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the + * result of whether or not the user approved the action. If approved, the result will + * be {@link Activity#RESULT_OK} and the component will be set as an active admin as well + * as a profile owner. + * + * <p>You can optionally include the {@link #EXTRA_ADD_EXPLANATION} + * field to provide the user with additional explanation (in addition + * to your component's description) about what is being added. + * + * <p>If there is already a profile owner active or the caller doesn't have the required + * permissions, the operation will return a failure result. + */ + @SystemApi + public static final String ACTION_SET_PROFILE_OWNER + = "android.app.action.SET_PROFILE_OWNER"; + + /** + * @hide + * Name of the profile owner admin that controls the user. + */ + @SystemApi + public static final String EXTRA_PROFILE_OWNER_NAME + = "android.app.extra.PROFILE_OWNER_NAME"; + + /** * Activity action: send when any policy admin changes a policy. * This is generally used to find out when a new policy is in effect. * @@ -133,13 +439,33 @@ = "android.app.action.SET_NEW_PASSWORD"; /** + * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a + * managed profile to its parent. + */ + public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001; + + /** + * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the + * parent to its managed profile. + */ + public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002; + + /** * Return true if the given administrator component is currently * active (enabled) in the system. */ public boolean isAdminActive(ComponentName who) { + return isAdminActiveAsUser(who, UserHandle.myUserId()); + } + + /** + * @see #isAdminActive(ComponentName) + * @hide + */ + public boolean isAdminActiveAsUser(ComponentName who, int userId) { if (mService != null) { try { - return mService.isAdminActive(who, UserHandle.myUserId()); + return mService.isAdminActive(who, userId); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -153,9 +479,17 @@ * returned. */ public List<ComponentName> getActiveAdmins() { + return getActiveAdminsAsUser(UserHandle.myUserId()); + } + + /** + * @see #getActiveAdmins() + * @hide + */ + public List<ComponentName> getActiveAdminsAsUser(int userId) { if (mService != null) { try { - return mService.getActiveAdmins(UserHandle.myUserId()); + return mService.getActiveAdmins(userId); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -246,6 +580,14 @@ /** * Constant for {@link #setPasswordQuality}: the user must have entered a + * password containing at least numeric characters with no repeating (4444) + * or ordered (1234, 4321, 2468) sequences. Note that quality + * constants are ordered so that higher values are more restrictive. + */ + public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 0x30000; + + /** + * Constant for {@link #setPasswordQuality}: the user must have entered a * password containing at least alphabetic (or other symbol) characters. * Note that quality constants are ordered so that higher values are more * restrictive. @@ -293,8 +635,9 @@ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param quality The new desired quality. One of * {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING}, - * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC}, - * {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}. + * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, + * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC} + * or {@link #PASSWORD_QUALITY_COMPLEX}. */ public void setPasswordQuality(ComponentName admin, int quality) { if (mService != null) { @@ -307,8 +650,8 @@ } /** - * Retrieve the current minimum password quality for all admins - * or a particular one. + * Retrieve the current minimum password quality for all admins of this user + * and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. */ @@ -337,9 +680,9 @@ * take place immediately. To prompt the user for a new password, use * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This * constraint is only imposed if the administrator has also requested either - * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC} - * {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX} - * with {@link #setPasswordQuality}. + * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, + * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC}, + * or {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call @@ -360,8 +703,8 @@ } /** - * Retrieve the current minimum password length for all admins - * or a particular one. + * Retrieve the current minimum password length for all admins of this + * user and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. */ @@ -415,8 +758,9 @@ /** * Retrieve the current number of upper case letters required in the - * password for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)} + * password for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -475,8 +819,9 @@ /** * Retrieve the current number of lower case letters required in the - * password for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)} + * password for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -592,8 +937,9 @@ /** * Retrieve the current number of numerical digits required in the password - * for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumNumeric(ComponentName, int)} + * for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumNumeric(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -708,8 +1054,9 @@ /** * Retrieve the current number of non-letter characters required in the - * password for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)} + * password for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -741,9 +1088,9 @@ * the change does not take place immediately. To prompt the user for a new * password, use {@link #ACTION_SET_NEW_PASSWORD} after setting this value. * This constraint is only imposed if the administrator has also requested - * either {@link #PASSWORD_QUALITY_NUMERIC}, - * {@link #PASSWORD_QUALITY_ALPHABETIC}, or - * {@link #PASSWORD_QUALITY_ALPHANUMERIC} with {@link #setPasswordQuality}. + * either {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX} + * {@link #PASSWORD_QUALITY_ALPHABETIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC} + * with {@link #setPasswordQuality}. * * <p> * The calling device admin must have requested @@ -780,6 +1127,9 @@ * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this * method; if it has not, a security exception will be thrown. * + * <p> Note that setting the password will automatically reset the expiration time for all + * active admins. Active admins do not need to explicitly call this method in that case. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param timeout The limit (in ms) that a password can remain in effect. A value of 0 * means there is no restriction (unlimited). @@ -816,9 +1166,10 @@ /** * Get the current password expiration time for the given admin or an aggregate of - * all admins if admin is null. If the password is expired, this will return the time since - * the password expired as a negative number. If admin is null, then a composite of all - * expiration timeouts is returned - which will be the minimum of all timeouts. + * all admins of this user and its profiles if admin is null. If the password is + * expired, this will return the time since the password expired as a negative number. + * If admin is null, then a composite of all expiration timeouts is returned + * - which will be the minimum of all timeouts. * * @param admin The name of the admin component to check, or null to aggregate all admins. * @return The password expiration time, in ms. @@ -835,8 +1186,8 @@ } /** - * Retrieve the current password history length for all admins - * or a particular one. + * Retrieve the current password history length for all admins of this + * user and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. * @return The length of the password history @@ -871,14 +1222,13 @@ /** * Determine whether the current password the user has set is sufficient * to meet the policy requirements (quality, minimum length) that have been - * requested. + * requested by the admins of this user and its profiles. * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call * this method; if it has not, a security exception will be thrown. * - * @return Returns true if the password meets the current requirements, - * else false. + * @return Returns true if the password meets the current requirements, else false. */ public boolean isActivePasswordSufficient() { if (mService != null) { @@ -941,7 +1291,7 @@ /** * Retrieve the current maximum number of login attempts that are allowed - * before the device wipes itself, for all admins + * before the device wipes itself, for all admins of this user and its profiles * or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. @@ -985,6 +1335,8 @@ * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call * this method; if it has not, a security exception will be thrown. * + * Can not be called from a managed profile. + * * @param password The new password for the user. * @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}. * @return Returns true if the password was applied, or false if it is @@ -1025,10 +1377,12 @@ } /** - * Retrieve the current maximum time to unlock for all admins - * or a particular one. + * Retrieve the current maximum time to unlock for all admins of this user + * and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. + * @return time in milliseconds for the given admin or the minimum value (strictest) of + * all admins if admin is null. Returns 0 if there are no restrictions. */ public long getMaximumTimeToLock(ComponentName admin) { return getMaximumTimeToLock(admin, UserHandle.myUserId()); @@ -1153,7 +1507,9 @@ } exclSpec = listBuilder.toString(); } - android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec); + if (android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec) + != android.net.Proxy.PROXY_VALID) + throw new IllegalArgumentException(); } return mService.setGlobalProxy(admin, hostSpec, exclSpec, UserHandle.myUserId()); } catch (RemoteException e) { @@ -1164,6 +1520,32 @@ } /** + * Set a network-independent global HTTP proxy. This is not normally what you want + * for typical HTTP proxies - they are generally network dependent. However if you're + * doing something unusual like general internal filtering this may be useful. On + * a private network where the proxy is not accessible, you may break HTTP using this. + * + * <p>This method requires the caller to be the device owner. + * + * <p>This proxy is only a recommendation and it is possible that some apps will ignore it. + * @see ProxyInfo + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated + * with. + * @param proxyInfo The a {@link ProxyInfo} object defining the new global + * HTTP proxy. A {@code null} value will clear the global HTTP proxy. + */ + public void setRecommendedGlobalProxy(ComponentName admin, ProxyInfo proxyInfo) { + if (mService != null) { + try { + mService.setRecommendedGlobalProxy(admin, proxyInfo); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** * Returns the component name setting the global proxy. * @return ComponentName object of the device admin that set the global proxy, or * null if no admin has set the proxy. @@ -1225,7 +1607,7 @@ public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; /** - * Disable all keyguard widgets + * Disable all keyguard widgets. Has no effect. */ public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0; @@ -1235,6 +1617,27 @@ public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 1 << 1; /** + * Disable showing all notifications on secure keyguard screens (e.g. PIN/Pattern/Password) + */ + public static final int KEYGUARD_DISABLE_SECURE_NOTIFICATIONS = 1 << 2; + + /** + * Only allow redacted notifications on secure keyguard screens (e.g. PIN/Pattern/Password) + */ + public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 1 << 3; + + /** + * Ignore trust agent state on secure keyguard screens + * (e.g. PIN/Pattern/Password). + */ + public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 1 << 4; + + /** + * Disable fingerprint sensor on keyguard secure screens (e.g. PIN/Pattern/Password). + */ + public static final int KEYGUARD_DISABLE_FINGERPRINT = 1 << 5; + + /** * Disable all current and future keyguard customizations. */ public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff; @@ -1314,7 +1717,7 @@ * storage. If the result is {@link #ENCRYPTION_STATUS_ACTIVATING} or * {@link #ENCRYPTION_STATUS_ACTIVE}, no further action is required. * - * @return current status of encryption. The value will be one of + * @return current status of encryption. The value will be one of * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, * {@link #ENCRYPTION_STATUS_ACTIVATING}, or{@link #ENCRYPTION_STATUS_ACTIVE}. */ @@ -1335,16 +1738,18 @@ } /** - * Installs the given certificate as a User CA. + * Installs the given certificate as a user CA. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param certBuffer encoded form of the certificate to install. * * @return false if the certBuffer cannot be parsed or installation is - * interrupted, otherwise true - * @hide + * interrupted, true otherwise. */ - public boolean installCaCert(byte[] certBuffer) { + public boolean installCaCert(ComponentName admin, byte[] certBuffer) { if (mService != null) { try { - return mService.installCaCert(certBuffer); + return mService.installCaCert(admin, certBuffer); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1353,14 +1758,18 @@ } /** - * Uninstalls the given certificate from the list of User CAs, if present. + * Uninstalls the given certificate from trusted user CAs, if present. * - * @hide + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param certBuffer encoded form of the certificate to remove. */ - public void uninstallCaCert(byte[] certBuffer) { + public void uninstallCaCert(ComponentName admin, byte[] certBuffer) { if (mService != null) { try { - mService.uninstallCaCert(certBuffer); + final String alias = getCaCertAlias(certBuffer); + mService.uninstallCaCert(admin, alias); + } catch (CertificateException e) { + Log.w(TAG, "Unable to parse certificate", e); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1368,37 +1777,109 @@ } /** - * Returns whether there are any user-installed CA certificates. + * Returns all CA certificates that are currently trusted, excluding system CA certificates. + * If a user has installed any certificates by other means than device policy these will be + * included too. * - * @hide + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return a List of byte[] arrays, each encoding one user CA certificate. */ - public static boolean hasAnyCaCertsInstalled() { - TrustedCertificateStore certStore = new TrustedCertificateStore(); - Set<String> aliases = certStore.userAliases(); - return aliases != null && !aliases.isEmpty(); + public List<byte[]> getInstalledCaCerts(ComponentName admin) { + List<byte[]> certs = new ArrayList<byte[]>(); + if (mService != null) { + try { + mService.enforceCanManageCaCerts(admin); + final TrustedCertificateStore certStore = new TrustedCertificateStore(); + for (String alias : certStore.userAliases()) { + try { + certs.add(certStore.getCertificate(alias).getEncoded()); + } catch (CertificateException ce) { + Log.w(TAG, "Could not encode certificate: " + alias, ce); + } + } + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } + } + return certs; } /** - * Returns whether this certificate has been installed as a User CA. + * Uninstalls all custom trusted CA certificates from the profile. Certificates installed by + * means other than device policy will also be removed, except for system CA certificates. * - * @hide + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. */ - public boolean hasCaCertInstalled(byte[] certBuffer) { - TrustedCertificateStore certStore = new TrustedCertificateStore(); - String alias; - byte[] pemCert; + public void uninstallAllUserCaCerts(ComponentName admin) { + if (mService != null) { + for (String alias : new TrustedCertificateStore().userAliases()) { + try { + mService.uninstallCaCert(admin, alias); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } + } + } + } + + /** + * Returns whether this certificate is installed as a trusted CA. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param certBuffer encoded form of the certificate to look up. + */ + public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) { + if (mService != null) { + try { + mService.enforceCanManageCaCerts(admin); + return getCaCertAlias(certBuffer) != null; + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } catch (CertificateException ce) { + Log.w(TAG, "Could not parse certificate", ce); + } + } + return false; + } + + /** + * Called by a device or profile owner to install a certificate and private key pair. The + * keypair will be visible to all apps within the profile. + * + * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param privKey The private key to install. + * @param cert The certificate to install. + * @param alias The private key alias under which to install the certificate. If a certificate + * with that alias already exists, it will be overwritten. + * @return {@code true} if the keys were installed, {@code false} otherwise. + */ + public boolean installKeyPair(ComponentName who, PrivateKey privKey, Certificate cert, + String alias) { try { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) certFactory.generateCertificate( - new ByteArrayInputStream(certBuffer)); - return certStore.getCertificateAlias(cert) != null; - } catch (CertificateException ce) { - Log.w(TAG, "Could not parse certificate", ce); + final byte[] pemCert = Credentials.convertToPem(cert); + return mService.installKeyPair(who, privKey.getEncoded(), pemCert, alias); + } catch (CertificateException e) { + Log.w(TAG, "Error encoding certificate", e); + } catch (IOException e) { + Log.w(TAG, "Error writing certificate", e); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); } return false; } /** + * Returns the alias of a given CA certificate in the certificate store, or null if it + * doesn't exist. + */ + private static String getCaCertAlias(byte[] certBuffer) throws CertificateException { + final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + final X509Certificate cert = (X509Certificate) certFactory.generateCertificate( + new ByteArrayInputStream(certBuffer)); + return new TrustedCertificateStore().getCertificateAlias(cert); + } + + /** * Called by an application that is administering the device to disable all cameras * on the device. After setting this, no applications will be able to access any cameras * on the device. @@ -1443,6 +1924,86 @@ } /** + * Called by a device/profile owner to set whether the screen capture is disabled. Disabling + * screen capture also prevents the content from being shown on display devices that do not have + * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about + * secure surfaces and secure displays. + * + * <p>The calling device admin must be a device or profile owner. If it is not, a + * security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param disabled Whether screen capture is disabled or not. + */ + public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) { + if (mService != null) { + try { + mService.setScreenCaptureDisabled(admin, UserHandle.myUserId(), disabled); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Determine whether or not screen capture has been disabled by the current + * admin, if specified, or all admins. + * @param admin The name of the admin component to check, or null to check if any admins + * have disabled screen capture. + */ + public boolean getScreenCaptureDisabled(ComponentName admin) { + return getScreenCaptureDisabled(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean getScreenCaptureDisabled(ComponentName admin, int userHandle) { + if (mService != null) { + try { + return mService.getScreenCaptureDisabled(admin, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Called by a device owner to set whether auto time is required. If auto time is + * required the user cannot set the date and time, but has to use network date and time. + * + * <p>Note: if auto time is required the user can still manually set the time zone. + * + * <p>The calling device admin must be a device owner. If it is not, a security exception will + * be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param required Whether auto time is set required or not. + */ + public void setAutoTimeRequired(ComponentName admin, boolean required) { + if (mService != null) { + try { + mService.setAutoTimeRequired(admin, UserHandle.myUserId(), required); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * @return true if auto time is required. + */ + public boolean getAutoTimeRequired() { + if (mService != null) { + try { + return mService.getAutoTimeRequired(); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** * Called by an application that is administering the device to disable keyguard customizations, * such as widgets. After setting this, keyguard features will be disabled according to the * provided feature list. @@ -1454,7 +2015,8 @@ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param which {@link #KEYGUARD_DISABLE_FEATURES_NONE} (default), * {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA}, - * {@link #KEYGUARD_DISABLE_FEATURES_ALL} + * {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, + * {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FEATURES_ALL} */ public void setKeyguardDisabledFeatures(ComponentName admin, int which) { if (mService != null) { @@ -1493,10 +2055,10 @@ /** * @hide */ - public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { + public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) { if (mService != null) { try { - mService.setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId()); + mService.setActiveAdmin(policyReceiver, refreshing, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1504,6 +2066,13 @@ } /** + * @hide + */ + public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { + setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId()); + } + + /** * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data * @hide */ @@ -1625,7 +2194,6 @@ return false; } - /** * Used to determine if a particular package has been registered as a Device Owner app. * A device owner app is a special device admin that cannot be deactivated by the user, once @@ -1658,7 +2226,27 @@ return isDeviceOwnerApp(packageName); } + /** + * Clears the current device owner. The caller must be the device owner. + * + * This function should be used cautiously as once it is called it cannot + * be undone. The device owner can only be set as a part of device setup + * before setup completes. + * + * @param packageName The package name of the device owner. + */ + public void clearDeviceOwnerApp(String packageName) { + if (mService != null) { + try { + mService.clearDeviceOwner(packageName); + } catch (RemoteException re) { + Log.w(TAG, "Failed to clear device owner"); + } + } + } + /** @hide */ + @SystemApi public String getDeviceOwner() { if (mService != null) { try { @@ -1681,4 +2269,1202 @@ } return null; } + + /** + * @hide + * @deprecated Use #ACTION_SET_PROFILE_OWNER + * Sets the given component as an active admin and registers the package as the profile + * owner for this user. The package must already be installed and there shouldn't be + * an existing profile owner registered for this user. Also, this method must be called + * before the user setup has been completed. + * <p> + * This method can only be called by system apps that hold MANAGE_USERS permission and + * MANAGE_DEVICE_ADMINS permission. + * @param admin The component to register as an active admin and profile owner. + * @param ownerName The user-visible name of the entity that is managing this user. + * @return whether the admin was successfully registered as the profile owner. + * @throws IllegalArgumentException if packageName is null, the package isn't installed, or + * the user has already been set up. + */ + @SystemApi + public boolean setActiveProfileOwner(ComponentName admin, String ownerName) + throws IllegalArgumentException { + if (mService != null) { + try { + final int myUserId = UserHandle.myUserId(); + mService.setActiveAdmin(admin, false, myUserId); + return mService.setProfileOwner(admin, ownerName, myUserId); + } catch (RemoteException re) { + Log.w(TAG, "Failed to set profile owner " + re); + throw new IllegalArgumentException("Couldn't set profile owner.", re); + } + } + return false; + } + + /** + * @hide + * Clears the active profile owner and removes all user restrictions. The caller must + * be from the same package as the active profile owner for this user, otherwise a + * SecurityException will be thrown. + * + * @param admin The component to remove as the profile owner. + * @return + */ + @SystemApi + public void clearProfileOwner(ComponentName admin) { + if (mService != null) { + try { + mService.clearProfileOwner(admin); + } catch (RemoteException re) { + Log.w(TAG, "Failed to clear profile owner " + admin + re); + } + } + } + + /** + * @hide + * Checks if the user was already setup. + */ + public boolean hasUserSetupCompleted() { + if (mService != null) { + try { + return mService.hasUserSetupCompleted(); + } catch (RemoteException re) { + Log.w(TAG, "Failed to check if user setup has completed"); + } + } + return true; + } + + /** + * @deprecated Use setProfileOwner(ComponentName ...) + * @hide + * Sets the given package as the profile owner of the given user profile. The package must + * already be installed and there shouldn't be an existing profile owner registered for this + * user. Also, this method must be called before the user has been used for the first time. + * @param packageName the package name of the application to be registered as profile owner. + * @param ownerName the human readable name of the organisation associated with this DPM. + * @param userHandle the userId to set the profile owner for. + * @return whether the package was successfully registered as the profile owner. + * @throws IllegalArgumentException if packageName is null, the package isn't installed, or + * the user has already been set up. + */ + public boolean setProfileOwner(String packageName, String ownerName, int userHandle) + throws IllegalArgumentException { + if (packageName == null) { + throw new NullPointerException("packageName cannot be null"); + } + return setProfileOwner(new ComponentName(packageName, ""), ownerName, userHandle); + } + + /** + * @hide + * Sets the given component as the profile owner of the given user profile. The package must + * already be installed and there shouldn't be an existing profile owner registered for this + * user. Only the system can call this API if the user has already completed setup. + * @param admin the component name to be registered as profile owner. + * @param ownerName the human readable name of the organisation associated with this DPM. + * @param userHandle the userId to set the profile owner for. + * @return whether the component was successfully registered as the profile owner. + * @throws IllegalArgumentException if admin is null, the package isn't installed, or + * the user has already been set up. + */ + public boolean setProfileOwner(ComponentName admin, String ownerName, int userHandle) + throws IllegalArgumentException { + if (admin == null) { + throw new NullPointerException("admin cannot be null"); + } + if (mService != null) { + try { + if (ownerName == null) { + ownerName = ""; + } + return mService.setProfileOwner(admin, ownerName, userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Failed to set profile owner", re); + throw new IllegalArgumentException("Couldn't set profile owner.", re); + } + } + return false; + } + + /** + * Sets the enabled state of the profile. A profile should be enabled only once it is ready to + * be used. Only the profile owner can call this. + * + * @see #isProfileOwnerApp + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public void setProfileEnabled(ComponentName admin) { + if (mService != null) { + try { + mService.setProfileEnabled(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Sets the name of the profile. In the device owner case it sets the name of the user + * which it is called from. Only a profile owner or device owner can call this. If this is + * never called by the profile or device owner, the name will be set to default values. + * + * @see #isProfileOwnerApp + * @see #isDeviceOwnerApp + * + * @param profileName The name of the profile. + */ + public void setProfileName(ComponentName who, String profileName) { + if (mService != null) { + try { + mService.setProfileName(who, profileName); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } +} + + /** + * Used to determine if a particular package is registered as the profile owner for the + * current user. A profile owner is a special device admin that has additional privileges + * within the profile. + * + * @param packageName The package name of the app to compare with the registered profile owner. + * @return Whether or not the package is registered as the profile owner. + */ + public boolean isProfileOwnerApp(String packageName) { + if (mService != null) { + try { + ComponentName profileOwner = mService.getProfileOwner( + Process.myUserHandle().getIdentifier()); + return profileOwner != null + && profileOwner.getPackageName().equals(packageName); + } catch (RemoteException re) { + Log.w(TAG, "Failed to check profile owner"); + } + } + return false; + } + + /** + * @hide + * @return the packageName of the owner of the given user profile or null if no profile + * owner has been set for that user. + * @throws IllegalArgumentException if the userId is invalid. + */ + @SystemApi + public ComponentName getProfileOwner() throws IllegalArgumentException { + return getProfileOwnerAsUser(Process.myUserHandle().getIdentifier()); + } + + /** + * @see #getProfileOwner() + * @hide + */ + public ComponentName getProfileOwnerAsUser(final int userId) throws IllegalArgumentException { + if (mService != null) { + try { + return mService.getProfileOwner(userId); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get profile owner"); + throw new IllegalArgumentException( + "Requested profile owner for invalid userId", re); + } + } + return null; + } + + /** + * @hide + * @return the human readable name of the organisation associated with this DPM or null if + * one is not set. + * @throws IllegalArgumentException if the userId is invalid. + */ + public String getProfileOwnerName() throws IllegalArgumentException { + if (mService != null) { + try { + return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier()); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get profile owner"); + throw new IllegalArgumentException( + "Requested profile owner for invalid userId", re); + } + } + return null; + } + + /** + * @hide + * @param user The user for whom to fetch the profile owner name, if any. + * @return the human readable name of the organisation associated with this profile owner or + * null if one is not set. + * @throws IllegalArgumentException if the userId is invalid. + */ + @SystemApi + public String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException { + if (mService != null) { + try { + return mService.getProfileOwnerName(userId); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get profile owner"); + throw new IllegalArgumentException( + "Requested profile owner for invalid userId", re); + } + } + return null; + } + + /** + * Called by a profile owner or device owner to add a default intent handler activity for + * intents that match a certain intent filter. This activity will remain the default intent + * handler even if the set of potential event handlers for the intent filter changes and if + * the intent preferences are reset. + * + * <p>The default disambiguation mechanism takes over if the activity is not installed + * (anymore). When the activity is (re)installed, it is automatically reset as default + * intent handler for the filter. + * + * <p>The calling device admin must be a profile owner or device owner. If it is not, a + * security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param filter The IntentFilter for which a default handler is added. + * @param activity The Activity that is added as default intent handler. + */ + public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter, + ComponentName activity) { + if (mService != null) { + try { + mService.addPersistentPreferredActivity(admin, filter, activity); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile owner or device owner to remove all persistent intent handler preferences + * associated with the given package that were set by {@link #addPersistentPreferredActivity}. + * + * <p>The calling device admin must be a profile owner. If it is not, a security + * exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The name of the package for which preferences are removed. + */ + public void clearPackagePersistentPreferredActivities(ComponentName admin, + String packageName) { + if (mService != null) { + try { + mService.clearPackagePersistentPreferredActivities(admin, packageName); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile or device owner to set the application restrictions for a given target + * application running in the profile. + * + * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be + * boolean, int, String, or String[]. + * + * <p>The application restrictions are only made visible to the target application and the + * profile or device owner. + * + * <p>The calling device admin must be a profile or device owner; if it is not, a security + * exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The name of the package to update restricted settings for. + * @param settings A {@link Bundle} to be parsed by the receiving application, conveying a new + * set of active restrictions. + */ + public void setApplicationRestrictions(ComponentName admin, String packageName, + Bundle settings) { + if (mService != null) { + try { + mService.setApplicationRestrictions(admin, packageName, settings); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Sets a list of features to enable for a TrustAgent component. This is meant to be + * used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which will disable all + * trust agents but those with features enabled by this function call. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param agent Which component to enable features for. + * @param features List of features to enable. Consult specific TrustAgent documentation for + * the feature list. + * @hide + */ + public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent, + List<String> features) { + if (mService != null) { + try { + mService.setTrustAgentFeaturesEnabled(admin, agent, features, UserHandle.myUserId()); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Gets list of enabled features for the given TrustAgent component. If admin is + * null, this will return the intersection of all features enabled for the given agent by all + * admins. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param agent Which component to get enabled features for. + * @return List of enabled features. + * @hide + */ + public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent) { + if (mService != null) { + try { + return mService.getTrustAgentFeaturesEnabled(admin, agent, UserHandle.myUserId()); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return new ArrayList<String>(); // empty list + } + + /** + * Called by a profile owner of a managed profile to set whether caller-Id information from + * the managed profile will be shown in the parent profile, for incoming calls. + * + * <p>The calling device admin must be a profile owner. If it is not, a + * security exception will be thrown. + * + * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param disabled If true caller-Id information in the managed profile is not displayed. + */ + public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) { + if (mService != null) { + try { + mService.setCrossProfileCallerIdDisabled(who, disabled); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile owner of a managed profile to determine whether or not caller-Id + * information has been disabled. + * + * <p>The calling device admin must be a profile owner. If it is not, a + * security exception will be thrown. + * + * @param who Which {@link DeviceAdminReceiver} this request is associated with. + */ + public boolean getCrossProfileCallerIdDisabled(ComponentName who) { + if (mService != null) { + try { + return mService.getCrossProfileCallerIdDisabled(who); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Determine whether or not caller-Id information has been disabled. + * + * @param userHandle The user for whom to check the caller-id permission + * @hide + */ + public boolean getCrossProfileCallerIdDisabled(UserHandle userHandle) { + if (mService != null) { + try { + return mService.getCrossProfileCallerIdDisabledForUser(userHandle.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Called by the profile owner of a managed profile so that some intents sent in the managed + * profile can also be resolved in the parent, or vice versa. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param filter The {@link IntentFilter} the intent has to match to be also resolved in the + * other profile + * @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and + * {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported. + */ + public void addCrossProfileIntentFilter(ComponentName admin, IntentFilter filter, int flags) { + if (mService != null) { + try { + mService.addCrossProfileIntentFilter(admin, filter, flags); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile owner of a managed profile to remove the cross-profile intent filters + * that go from the managed profile to the parent, or from the parent to the managed profile. + * Only removes those that have been set by the profile owner. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public void clearCrossProfileIntentFilters(ComponentName admin) { + if (mService != null) { + try { + mService.clearCrossProfileIntentFilters(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile or device owner to set the permitted accessibility services. When + * set by a device owner or profile owner the restriction applies to all profiles of the + * user the device owner or profile owner is an admin for. + * + * By default the user can use any accessiblity service. When zero or more packages have + * been added, accessiblity services that are not in the list and not part of the system + * can not be enabled by the user. + * + * <p> Calling with a null value for the list disables the restriction so that all services + * can be used, calling with an empty list only allows the builtin system's services. + * + * <p> System accesibility services are always available to the user the list can't modify + * this. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageNames List of accessibility service package names. + * + * @return true if setting the restriction succeeded. It fail if there is + * one or more non-system accessibility services enabled, that are not in the list. + */ + public boolean setPermittedAccessibilityServices(ComponentName admin, + List<String> packageNames) { + if (mService != null) { + try { + return mService.setPermittedAccessibilityServices(admin, packageNames); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Returns the list of permitted accessibility services set by this device or profile owner. + * + * <p>An empty list means no accessibility services except system services are allowed. + * Null means all accessibility services are allowed. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return List of accessiblity service package names. + */ + public List<String> getPermittedAccessibilityServices(ComponentName admin) { + if (mService != null) { + try { + return mService.getPermittedAccessibilityServices(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** + * Returns the list of accessibility services permitted by the device or profiles + * owners of this user. + * + * <p>Null means all accessibility services are allowed, if a non-null list is returned + * it will contain the intersection of the permitted lists for any device or profile + * owners that apply to this user. It will also include any system accessibility services. + * + * @param userId which user to check for. + * @return List of accessiblity service package names. + * @hide + */ + @SystemApi + public List<String> getPermittedAccessibilityServices(int userId) { + if (mService != null) { + try { + return mService.getPermittedAccessibilityServicesForUser(userId); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** + * Called by a profile or device owner to set the permitted input methods services. When + * set by a device owner or profile owner the restriction applies to all profiles of the + * user the device owner or profile owner is an admin for. + * + * By default the user can use any input method. When zero or more packages have + * been added, input method that are not in the list and not part of the system + * can not be enabled by the user. + * + * This method will fail if it is called for a admin that is not for the foreground user + * or a profile of the foreground user. + * + * <p> Calling with a null value for the list disables the restriction so that all input methods + * can be used, calling with an empty list disables all but the system's own input methods. + * + * <p> System input methods are always available to the user this method can't modify this. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageNames List of input method package names. + * @return true if setting the restriction succeeded. It will fail if there is + * one or more input method enabled, that are not in the list or user if the foreground + * user. + */ + public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) { + if (mService != null) { + try { + return mService.setPermittedInputMethods(admin, packageNames); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + + /** + * Returns the list of permitted input methods set by this device or profile owner. + * + * <p>An empty list means no input methods except system input methods are allowed. + * Null means all input methods are allowed. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return List of input method package names. + */ + public List<String> getPermittedInputMethods(ComponentName admin) { + if (mService != null) { + try { + return mService.getPermittedInputMethods(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** + * Returns the list of input methods permitted by the device or profiles + * owners of the current user. + * + * <p>Null means all input methods are allowed, if a non-null list is returned + * it will contain the intersection of the permitted lists for any device or profile + * owners that apply to this user. It will also include any system input methods. + * + * @return List of input method package names. + * @hide + */ + @SystemApi + public List<String> getPermittedInputMethodsForCurrentUser() { + if (mService != null) { + try { + return mService.getPermittedInputMethodsForCurrentUser(); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** + * Called by a device owner to create a user with the specified name. The UserHandle returned + * by this method should not be persisted as user handles are recycled as users are removed and + * created. If you need to persist an identifier for this user, use + * {@link UserManager#getSerialNumberForUser}. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param name the user's name + * @see UserHandle + * @return the UserHandle object for the created user, or null if the user could not be created. + */ + public UserHandle createUser(ComponentName admin, String name) { + try { + return mService.createUser(admin, name); + } catch (RemoteException re) { + Log.w(TAG, "Could not create a user", re); + } + return null; + } + + /** + * Called by a device owner to create a user with the specified name. The UserHandle returned + * by this method should not be persisted as user handles are recycled as users are removed and + * created. If you need to persist an identifier for this user, use + * {@link UserManager#getSerialNumberForUser}. The new user will be started in the background + * immediately. + * + * <p> profileOwnerComponent is the {@link DeviceAdminReceiver} to be the profile owner as well + * as registered as an active admin on the new user. The profile owner package will be + * installed on the new user if it already is installed on the device. + * + * <p>If the optionalInitializeData is not null, then the extras will be passed to the + * profileOwnerComponent when onEnable is called. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param name the user's name + * @param ownerName the human readable name of the organisation associated with this DPM. + * @param profileOwnerComponent The {@link DeviceAdminReceiver} that will be an active admin on + * the user. + * @param adminExtras Extras that will be passed to onEnable of the admin receiver + * on the new user. + * @see UserHandle + * @return the UserHandle object for the created user, or null if the user could not be created. + */ + public UserHandle createAndInitializeUser(ComponentName admin, String name, String ownerName, + ComponentName profileOwnerComponent, Bundle adminExtras) { + try { + return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent, + adminExtras); + } catch (RemoteException re) { + Log.w(TAG, "Could not create a user", re); + } + return null; + } + + /** + * Called by a device owner to remove a user and all associated data. The primary user can + * not be removed. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param userHandle the user to remove. + * @return {@code true} if the user was removed, {@code false} otherwise. + */ + public boolean removeUser(ComponentName admin, UserHandle userHandle) { + try { + return mService.removeUser(admin, userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not remove user ", re); + return false; + } + } + + /** + * Called by a device owner to switch the specified user to the foreground. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param userHandle the user to switch to; null will switch to primary. + * @return {@code true} if the switch was successful, {@code false} otherwise. + * + * @see Intent#ACTION_USER_FOREGROUND + */ + public boolean switchUser(ComponentName admin, UserHandle userHandle) { + try { + return mService.switchUser(admin, userHandle); + } catch (RemoteException re) { + Log.w(TAG, "Could not switch user ", re); + return false; + } + } + + /** + * Called by a profile or device owner to get the application restrictions for a given target + * application running in the profile. + * + * <p>The calling device admin must be a profile or device owner; if it is not, a security + * exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The name of the package to fetch restricted settings of. + * @return {@link Bundle} of settings corresponding to what was set last time + * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle} + * if no restrictions have been set. + */ + public Bundle getApplicationRestrictions(ComponentName admin, String packageName) { + if (mService != null) { + try { + return mService.getApplicationRestrictions(admin, packageName); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** + * Called by a profile or device owner to set a user restriction specified + * by the key. + * <p> + * The calling device admin must be a profile or device owner; if it is not, + * a security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated + * with. + * @param key The key of the restriction. See the constants in + * {@link android.os.UserManager} for the list of keys. + */ + public void addUserRestriction(ComponentName admin, String key) { + if (mService != null) { + try { + mService.setUserRestriction(admin, key, true); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile or device owner to clear a user restriction specified + * by the key. + * <p> + * The calling device admin must be a profile or device owner; if it is not, + * a security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated + * with. + * @param key The key of the restriction. See the constants in + * {@link android.os.UserManager} for the list of keys. + */ + public void clearUserRestriction(ComponentName admin, String key) { + if (mService != null) { + try { + mService.setUserRestriction(admin, key, false); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by device or profile owner to hide or unhide packages. When a package is hidden it + * is unavailable for use, but the data and actual package file remain. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The name of the package to hide or unhide. + * @param hidden {@code true} if the package should be hidden, {@code false} if it should be + * unhidden. + * @return boolean Whether the hidden setting of the package was successfully updated. + */ + public boolean setApplicationHidden(ComponentName admin, String packageName, + boolean hidden) { + if (mService != null) { + try { + return mService.setApplicationHidden(admin, packageName, hidden); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Called by device or profile owner to determine if a package is hidden. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The name of the package to retrieve the hidden status of. + * @return boolean {@code true} if the package is hidden, {@code false} otherwise. + */ + public boolean isApplicationHidden(ComponentName admin, String packageName) { + if (mService != null) { + try { + return mService.isApplicationHidden(admin, packageName); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Called by profile or device owner to re-enable a system app that was disabled by default + * when the user was initialized. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package to be re-enabled in the current profile. + */ + public void enableSystemApp(ComponentName admin, String packageName) { + if (mService != null) { + try { + mService.enableSystemApp(admin, packageName); + } catch (RemoteException e) { + Log.w(TAG, "Failed to install package: " + packageName); + } + } + } + + /** + * Called by profile or device owner to re-enable system apps by intent that were disabled + * by default when the user was initialized. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param intent An intent matching the app(s) to be installed. All apps that resolve for this + * intent will be re-enabled in the current profile. + * @return int The number of activities that matched the intent and were installed. + */ + public int enableSystemApp(ComponentName admin, Intent intent) { + if (mService != null) { + try { + return mService.enableSystemAppWithIntent(admin, intent); + } catch (RemoteException e) { + Log.w(TAG, "Failed to install packages matching filter: " + intent); + } + } + return 0; + } + + /** + * Called by a profile owner to disable account management for a specific type of account. + * + * <p>The calling device admin must be a profile owner. If it is not, a + * security exception will be thrown. + * + * <p>When account management is disabled for an account type, adding or removing an account + * of that type will not be possible. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param accountType For which account management is disabled or enabled. + * @param disabled The boolean indicating that account management will be disabled (true) or + * enabled (false). + */ + public void setAccountManagementDisabled(ComponentName admin, String accountType, + boolean disabled) { + if (mService != null) { + try { + mService.setAccountManagementDisabled(admin, accountType, disabled); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Gets the array of accounts for which account management is disabled by the profile owner. + * + * <p> Account management can be disabled/enabled by calling + * {@link #setAccountManagementDisabled}. + * + * @return a list of account types for which account management has been disabled. + * + * @see #setAccountManagementDisabled + */ + public String[] getAccountTypesWithManagementDisabled() { + return getAccountTypesWithManagementDisabledAsUser(UserHandle.myUserId()); + } + + /** + * @see #getAccountTypesWithManagementDisabled() + * @hide + */ + public String[] getAccountTypesWithManagementDisabledAsUser(int userId) { + if (mService != null) { + try { + return mService.getAccountTypesWithManagementDisabledAsUser(userId); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + + return null; + } + + /** + * Sets which packages may enter lock task mode. + * + * <p>Any packages that shares uid with an allowed package will also be allowed + * to activate lock task. + * + * This function can only be called by the device owner. + * @param packages The list of packages allowed to enter lock task mode + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * + * @see Activity#startLockTask() + * @see DeviceAdminReceiver#onLockTaskModeChanged(Context, Intent, boolean, String) + * @see UserManager#DISALLOW_CREATE_WINDOWS + */ + public void setLockTaskPackages(ComponentName admin, String[] packages) + throws SecurityException { + if (mService != null) { + try { + mService.setLockTaskPackages(admin, packages); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * This function returns the list of packages allowed to start the lock task mode. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @hide + */ + public String[] getLockTaskPackages(ComponentName admin) { + if (mService != null) { + try { + return mService.getLockTaskPackages(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** + * This function lets the caller know whether the given component is allowed to start the + * lock task mode. + * @param pkg The package to check + */ + public boolean isLockTaskPermitted(String pkg) { + if (mService != null) { + try { + return mService.isLockTaskPermitted(pkg); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** + * Called by device owners to update {@link Settings.Global} settings. Validation that the value + * of the setting is in the correct form for the setting type should be performed by the caller. + * <p>The settings that can be updated with this method are: + * <ul> + * <li>{@link Settings.Global#ADB_ENABLED}</li> + * <li>{@link Settings.Global#AUTO_TIME}</li> + * <li>{@link Settings.Global#AUTO_TIME_ZONE}</li> + * <li>{@link Settings.Global#BLUETOOTH_ON}</li> + * <li>{@link Settings.Global#DATA_ROAMING}</li> + * <li>{@link Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}</li> + * <li>{@link Settings.Global#MODE_RINGER}</li> + * <li>{@link Settings.Global#NETWORK_PREFERENCE}</li> + * <li>{@link Settings.Global#USB_MASS_STORAGE_ENABLED}</li> + * <li>{@link Settings.Global#WIFI_ON}</li> + * <li>{@link Settings.Global#WIFI_SLEEP_POLICY}</li> + * </ul> + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param setting The name of the setting to update. + * @param value The value to update the setting to. + */ + public void setGlobalSetting(ComponentName admin, String setting, String value) { + if (mService != null) { + try { + mService.setGlobalSetting(admin, setting, value); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by profile or device owners to update {@link Settings.Secure} settings. Validation + * that the value of the setting is in the correct form for the setting type should be performed + * by the caller. + * <p>The settings that can be updated by a profile or device owner with this method are: + * <ul> + * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li> + * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li> + * </ul> + * <p>A device owner can additionally update the following settings: + * <ul> + * <li>{@link Settings.Secure#LOCATION_MODE}</li> + * </ul> + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param setting The name of the setting to update. + * @param value The value to update the setting to. + */ + public void setSecureSetting(ComponentName admin, String setting, String value) { + if (mService != null) { + try { + mService.setSecureSetting(admin, setting, value); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Designates a specific service component as the provider for + * making permission requests of a local or remote administrator of the user. + * <p/> + * Only a profile owner can designate the restrictions provider. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param provider The component name of the service that implements + * {@link RestrictionsReceiver}. If this param is null, + * it removes the restrictions provider previously assigned. + */ + public void setRestrictionsProvider(ComponentName admin, ComponentName provider) { + if (mService != null) { + try { + mService.setRestrictionsProvider(admin, provider); + } catch (RemoteException re) { + Log.w(TAG, "Failed to set permission provider on device policy service"); + } + } + } + + /** + * Called by profile or device owners to set the master volume mute on or off. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param on {@code true} to mute master volume, {@code false} to turn mute off. + */ + public void setMasterVolumeMuted(ComponentName admin, boolean on) { + if (mService != null) { + try { + mService.setMasterVolumeMuted(admin, on); + } catch (RemoteException re) { + Log.w(TAG, "Failed to setMasterMute on device policy service"); + } + } + } + + /** + * Called by profile or device owners to check whether the master volume mute is on or off. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return {@code true} if master volume is muted, {@code false} if it's not. + */ + public boolean isMasterVolumeMuted(ComponentName admin) { + if (mService != null) { + try { + return mService.isMasterVolumeMuted(admin); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get isMasterMute on device policy service"); + } + } + return false; + } + + /** + * Called by profile or device owners to change whether a user can uninstall + * a package. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName package to change. + * @param uninstallBlocked true if the user shouldn't be able to uninstall the package. + */ + public void setUninstallBlocked(ComponentName admin, String packageName, + boolean uninstallBlocked) { + if (mService != null) { + try { + mService.setUninstallBlocked(admin, packageName, uninstallBlocked); + } catch (RemoteException re) { + Log.w(TAG, "Failed to call block uninstall on device policy service"); + } + } + } + + /** + * Called by profile or device owners to check whether a user has been blocked from + * uninstalling a package. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName package to check. + * @return true if the user shouldn't be able to uninstall the package. + */ + public boolean isUninstallBlocked(ComponentName admin, String packageName) { + if (mService != null) { + try { + return mService.isUninstallBlocked(admin, packageName); + } catch (RemoteException re) { + Log.w(TAG, "Failed to call block uninstall on device policy service"); + } + } + return false; + } + + /** + * Called by the profile owner of a managed profile to enable widget providers from a + * given package to be available in the parent profile. As a result the user will be able to + * add widgets from the white-listed package running under the profile to a widget + * host which runs under the parent profile, for example the home screen. Note that + * a package may have zero or more provider components, where each component + * provides a different widget type. + * <p> + * <strong>Note:</strong> By default no widget provider package is white-listed. + * </p> + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package from which widget providers are white-listed. + * @return Whether the package was added. + * + * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String) + * @see #getCrossProfileWidgetProviders(android.content.ComponentName) + */ + public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) { + if (mService != null) { + try { + return mService.addCrossProfileWidgetProvider(admin, packageName); + } catch (RemoteException re) { + Log.w(TAG, "Error calling addCrossProfileWidgetProvider", re); + } + } + return false; + } + + /** + * Called by the profile owner of a managed profile to disable widget providers from a given + * package to be available in the parent profile. For this method to take effect the + * package should have been added via {@link #addCrossProfileWidgetProvider( + * android.content.ComponentName, String)}. + * <p> + * <strong>Note:</strong> By default no widget provider package is white-listed. + * </p> + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package from which widget providers are no longer + * white-listed. + * @return Whether the package was removed. + * + * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String) + * @see #getCrossProfileWidgetProviders(android.content.ComponentName) + */ + public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) { + if (mService != null) { + try { + return mService.removeCrossProfileWidgetProvider(admin, packageName); + } catch (RemoteException re) { + Log.w(TAG, "Error calling removeCrossProfileWidgetProvider", re); + } + } + return false; + } + + /** + * Called by the profile owner of a managed profile to query providers from which packages are + * available in the parent profile. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return The white-listed package list. + * + * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String) + * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String) + */ + public List<String> getCrossProfileWidgetProviders(ComponentName admin) { + if (mService != null) { + try { + List<String> providers = mService.getCrossProfileWidgetProviders(admin); + if (providers != null) { + return providers; + } + } catch (RemoteException re) { + Log.w(TAG, "Error calling getCrossProfileWidgetProviders", re); + } + } + return Collections.emptyList(); + } }
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java new file mode 100644 index 0000000..a1f1d92 --- /dev/null +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -0,0 +1,63 @@ +/* + * Copyright (C) 2014 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.admin; + +import java.util.List; + +/** + * Device policy manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class DevicePolicyManagerInternal { + + /** + * Listener for changes in the white-listed packages to show cross-profile + * widgets. + */ + public interface OnCrossProfileWidgetProvidersChangeListener { + + /** + * Called when the white-listed packages to show cross-profile widgets + * have changed for a given user. + * + * @param profileId The profile for which the white-listed packages changed. + * @param packages The white-listed packages. + */ + public void onCrossProfileWidgetProvidersChanged(int profileId, List<String> packages); + } + + /** + * Gets the packages whose widget providers are white-listed to be + * available in the parent user. + * + * @param profileId The profile id. + * @return The list of packages if such or empty list if there are + * no white-listed packages or the profile id is not a managed + * profile. + */ + public abstract List<String> getCrossProfileWidgetProviders(int profileId); + + /** + * Adds a listener for changes in the white-listed packages to show + * cross-profile app widgets. + * + * @param listener The listener to add. + */ + public abstract void addOnCrossProfileWidgetProvidersChangeListener( + OnCrossProfileWidgetProvidersChangeListener listener); +}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 172c47c2..c8e1780 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -18,7 +18,13 @@ package android.app.admin; import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ProxyInfo; +import android.os.Bundle; import android.os.RemoteCallback; +import android.os.UserHandle; +import java.util.List; /** * Internal IPC interface to the device policy service. @@ -74,6 +80,7 @@ ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList, int userHandle); ComponentName getGlobalProxyAdmin(int userHandle); + void setRecommendedGlobalProxy(in ComponentName admin, in ProxyInfo proxyInfo); int setStorageEncryption(in ComponentName who, boolean encrypt, int userHandle); boolean getStorageEncryption(in ComponentName who, int userHandle); @@ -82,6 +89,9 @@ void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle); boolean getCameraDisabled(in ComponentName who, int userHandle); + void setScreenCaptureDisabled(in ComponentName who, int userHandle, boolean disabled); + boolean getScreenCaptureDisabled(in ComponentName who, int userHandle); + void setKeyguardDisabledFeatures(in ComponentName who, int which, int userHandle); int getKeyguardDisabledFeatures(in ComponentName who, int userHandle); @@ -102,7 +112,84 @@ boolean isDeviceOwner(String packageName); String getDeviceOwner(); String getDeviceOwnerName(); + void clearDeviceOwner(String packageName); - boolean installCaCert(in byte[] certBuffer); - void uninstallCaCert(in byte[] certBuffer); + boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle); + ComponentName getProfileOwner(int userHandle); + String getProfileOwnerName(int userHandle); + void setProfileEnabled(in ComponentName who); + void setProfileName(in ComponentName who, String profileName); + void clearProfileOwner(in ComponentName who); + boolean hasUserSetupCompleted(); + + boolean installCaCert(in ComponentName admin, in byte[] certBuffer); + void uninstallCaCert(in ComponentName admin, in String alias); + void enforceCanManageCaCerts(in ComponentName admin); + + boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias); + + void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); + void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); + + void setApplicationRestrictions(in ComponentName who, in String packageName, in Bundle settings); + Bundle getApplicationRestrictions(in ComponentName who, in String packageName); + + void setRestrictionsProvider(in ComponentName who, in ComponentName provider); + ComponentName getRestrictionsProvider(int userHandle); + + void setUserRestriction(in ComponentName who, in String key, boolean enable); + void addCrossProfileIntentFilter(in ComponentName admin, in IntentFilter filter, int flags); + void clearCrossProfileIntentFilters(in ComponentName admin); + + boolean setPermittedAccessibilityServices(in ComponentName admin,in List packageList); + List getPermittedAccessibilityServices(in ComponentName admin); + List getPermittedAccessibilityServicesForUser(int userId); + + boolean setPermittedInputMethods(in ComponentName admin,in List packageList); + List getPermittedInputMethods(in ComponentName admin); + List getPermittedInputMethodsForCurrentUser(); + + boolean setApplicationHidden(in ComponentName admin, in String packageName, boolean hidden); + boolean isApplicationHidden(in ComponentName admin, in String packageName); + + UserHandle createUser(in ComponentName who, in String name); + UserHandle createAndInitializeUser(in ComponentName who, in String name, in String profileOwnerName, in ComponentName profileOwnerComponent, in Bundle adminExtras); + boolean removeUser(in ComponentName who, in UserHandle userHandle); + boolean switchUser(in ComponentName who, in UserHandle userHandle); + + void enableSystemApp(in ComponentName admin, in String packageName); + int enableSystemAppWithIntent(in ComponentName admin, in Intent intent); + + void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); + String[] getAccountTypesWithManagementDisabled(); + String[] getAccountTypesWithManagementDisabledAsUser(int userId); + + void setLockTaskPackages(in ComponentName who, in String[] packages); + String[] getLockTaskPackages(in ComponentName who); + boolean isLockTaskPermitted(in String pkg); + + void setGlobalSetting(in ComponentName who, in String setting, in String value); + void setSecureSetting(in ComponentName who, in String setting, in String value); + + void setMasterVolumeMuted(in ComponentName admin, boolean on); + boolean isMasterVolumeMuted(in ComponentName admin); + + void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userId); + + void setUninstallBlocked(in ComponentName admin, in String packageName, boolean uninstallBlocked); + boolean isUninstallBlocked(in ComponentName admin, in String packageName); + + void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled); + boolean getCrossProfileCallerIdDisabled(in ComponentName who); + boolean getCrossProfileCallerIdDisabledForUser(int userId); + + void setTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, in List<String> features, int userId); + List<String> getTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, int userId); + + boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName); + boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName); + List<String> getCrossProfileWidgetProviders(in ComponentName admin); + + void setAutoTimeRequired(in ComponentName who, int userHandle, boolean required); + boolean getAutoTimeRequired(); }
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 70a3797..87d785a 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java
@@ -127,6 +127,13 @@ Handler mHandler = null; + Handler getHandler() { + if (mHandler == null) { + mHandler = new Handler(Looper.getMainLooper()); + } + return mHandler; + } + class SharedPrefsSynchronizer implements Runnable { public final CountDownLatch mLatch = new CountDownLatch(1); @@ -139,12 +146,9 @@ // Syncing shared preferences deferred writes needs to happen on the main looper thread private void waitForSharedPrefs() { - if (mHandler == null) { - mHandler = new Handler(Looper.getMainLooper()); - } - + Handler h = getHandler(); final SharedPrefsSynchronizer s = new SharedPrefsSynchronizer(); - mHandler.postAtFrontOfQueue(s); + h.postAtFrontOfQueue(s); try { s.mLatch.await(); } catch (InterruptedException e) { /* ignored */ } @@ -205,7 +209,7 @@ * output stream. */ public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException; + ParcelFileDescriptor newState) throws IOException; /** * The application is being restored from backup and should replace any @@ -239,16 +243,43 @@ * When a full-backup dataset is being restored, this will be <code>null</code>. */ public abstract void onRestore(BackupDataInput data, int appVersionCode, - ParcelFileDescriptor newState) - throws IOException; + ParcelFileDescriptor newState) throws IOException; /** - * The default implementation backs up the entirety of the application's "owned" - * file system trees to the output. + * The application is having its entire file system contents backed up. {@code data} + * points to the backup destination, and the app has the opportunity to choose which + * files are to be stored. To commit a file as part of the backup, call the + * {@link #fullBackupFile(File, FullBackupDataOutput)} helper method. After all file + * data is written to the output, the agent returns from this method and the backup + * operation concludes. + * + * <p>Certain parts of the app's data are never backed up even if the app explicitly + * sends them to the output: + * + * <ul> + * <li>The contents of the {@link #getCacheDir()} directory</li> + * <li>The contents of the {@link #getNoBackupFilesDir()} directory</li> + * <li>The contents of the app's shared library directory</li> + * </ul> + * + * <p>The default implementation of this method backs up the entirety of the + * application's "owned" file system trees to the output other than the few exceptions + * listed above. Apps only need to override this method if they need to impose special + * limitations on which files are being stored beyond the control that + * {@link #getNoBackupFilesDir()} offers. + * + * @param data A structured wrapper pointing to the backup destination. + * @throws IOException + * + * @see Context#getNoBackupFilesDir() + * @see #fullBackupFile(File, FullBackupDataOutput) + * @see #onRestoreFile(ParcelFileDescriptor, long, File, int, long, long) */ public void onFullBackup(FullBackupDataOutput data) throws IOException { ApplicationInfo appInfo = getApplicationInfo(); + // Note that we don't need to think about the no_backup dir because it's outside + // all of the ones we will be traversing String rootDir = new File(appInfo.dataDir).getCanonicalPath(); String filesDir = getFilesDir().getCanonicalPath(); String databaseDir = getDatabasePath("foo").getParentFile().getCanonicalPath(); @@ -307,6 +338,10 @@ * to place it with the proper location and permissions on the device where the * data is restored. * + * <p class="note">It is safe to explicitly back up files underneath your application's + * {@link #getNoBackupFilesDir()} directory, and they will be restored to that + * location correctly. + * * @param file The file to be backed up. The file must exist and be readable by * the caller. * @param output The destination to which the backed-up file data will be sent. @@ -315,6 +350,7 @@ // Look up where all of our various well-defined dir trees live on this device String mainDir; String filesDir; + String nbFilesDir; String dbDir; String spDir; String cacheDir; @@ -327,6 +363,7 @@ try { mainDir = new File(appInfo.dataDir).getCanonicalPath(); filesDir = getFilesDir().getCanonicalPath(); + nbFilesDir = getNoBackupFilesDir().getCanonicalPath(); dbDir = getDatabasePath("foo").getParentFile().getCanonicalPath(); spDir = getSharedPrefsFile("foo").getParentFile().getCanonicalPath(); cacheDir = getCacheDir().getCanonicalPath(); @@ -350,8 +387,10 @@ return; } - if (filePath.startsWith(cacheDir) || filePath.startsWith(libDir)) { - Log.w(TAG, "lib and cache files are not backed up"); + if (filePath.startsWith(cacheDir) + || filePath.startsWith(libDir) + || filePath.startsWith(nbFilesDir)) { + Log.w(TAG, "lib, cache, and no_backup files are not backed up"); return; } @@ -504,6 +543,8 @@ mode = -1; // < 0 is a token to skip attempting a chmod() } } + } else if (domain.equals(FullBackup.NO_BACKUP_TREE_TOKEN)) { + basePath = getNoBackupFilesDir().getCanonicalPath(); } else { // Not a supported location Log.i(TAG, "Unrecognized domain " + domain); @@ -533,6 +574,20 @@ FullBackup.restoreFile(data, size, type, mode, mtime, null); } + /** + * The application's restore operation has completed. This method is called after + * all available data has been delivered to the application for restore (via either + * the {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()} or + * {@link #onRestoreFile(ParcelFileDescriptor, long, File, int, long, long) onRestoreFile()} + * callbacks). This provides the app with a stable end-of-restore opportunity to + * perform any appropriate post-processing on the data that was just delivered. + * + * @see #onRestore(BackupDataInput, int, ParcelFileDescriptor) + * @see #onRestoreFile(ParcelFileDescriptor, long, File, int, long, long) + */ + public void onRestoreFinished() { + } + // ----- Core implementation ----- /** @hide */ @@ -679,5 +734,41 @@ } } } + + @Override + public void doRestoreFinished(int token, IBackupManager callbackBinder) { + long ident = Binder.clearCallingIdentity(); + try { + BackupAgent.this.onRestoreFinished(); + } finally { + // Ensure that any side-effect SharedPreferences writes have landed + waitForSharedPrefs(); + + Binder.restoreCallingIdentity(ident); + try { + callbackBinder.opComplete(token); + } catch (RemoteException e) { + // we'll time out anyway, so we're safe + } + } + } + + @Override + public void fail(String message) { + getHandler().post(new FailRunnable(message)); + } + } + + static class FailRunnable implements Runnable { + private String mMessage; + + FailRunnable(String message) { + mMessage = message; + } + + @Override + public void run() { + throw new IllegalStateException(mMessage); + } } }
diff --git a/core/java/android/app/backup/BackupDataInput.java b/core/java/android/app/backup/BackupDataInput.java index 03205fb..26f9e3e 100644 --- a/core/java/android/app/backup/BackupDataInput.java +++ b/core/java/android/app/backup/BackupDataInput.java
@@ -16,6 +16,8 @@ package android.app.backup; +import android.annotation.SystemApi; + import java.io.FileDescriptor; import java.io.IOException; @@ -70,6 +72,7 @@ } /** @hide */ + @SystemApi public BackupDataInput(FileDescriptor fd) { if (fd == null) throw new NullPointerException(); mBackupReader = ctor(fd); @@ -79,6 +82,7 @@ } /** @hide */ + @Override protected void finalize() throws Throwable { try { dtor(mBackupReader); @@ -174,7 +178,7 @@ * for further processing. This allows a {@link android.app.backup.BackupAgent} to * efficiently discard obsolete or otherwise uninteresting records during the * restore operation. - * + * * @throws IOException if an error occurred when trying to read the restore data stream */ public void skipEntityData() throws IOException {
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java index 3a070b6..048a4bb 100644 --- a/core/java/android/app/backup/BackupDataOutput.java +++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -16,7 +16,9 @@ package android.app.backup; +import android.annotation.SystemApi; import android.os.ParcelFileDescriptor; +import android.os.Process; import java.io.FileDescriptor; import java.io.IOException; @@ -65,6 +67,7 @@ long mBackupWriter; /** @hide */ + @SystemApi public BackupDataOutput(FileDescriptor fd) { if (fd == null) throw new NullPointerException(); mBackupWriter = ctor(fd); @@ -76,7 +79,8 @@ /** * Mark the beginning of one record in the backup data stream. This must be called before * {@link #writeEntityData}. - * @param key A string key that uniquely identifies the data record within the application + * @param key A string key that uniquely identifies the data record within the application. + * Keys whose first character is \uFF00 or higher are not valid. * @param dataSize The size in bytes of this record's data. Passing a dataSize * of -1 indicates that the record under this key should be deleted. * @return The number of bytes written to the backup stream @@ -113,6 +117,7 @@ } /** @hide */ + @Override protected void finalize() throws Throwable { try { dtor(mBackupWriter);
diff --git a/core/java/android/app/backup/BackupHelper.java b/core/java/android/app/backup/BackupHelper.java index e3f0d54..7cbbbc3 100644 --- a/core/java/android/app/backup/BackupHelper.java +++ b/core/java/android/app/backup/BackupHelper.java
@@ -37,10 +37,9 @@ */ public interface BackupHelper { /** - * Based on <code>oldState</code>, determine which of the files from the - * application's data directory need to be backed up, write them to - * <code>data</code>, and fill in <code>newState</code> with the state as it - * exists now. + * Based on <code>oldState</code>, determine what application content + * needs to be backed up, write it to <code>data</code>, and fill in + * <code>newState</code> with the complete state as it exists now. * <p> * Implementing this method is much like implementing * {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index be8108c..9151a16 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java
@@ -16,6 +16,7 @@ package android.app.backup; +import android.annotation.SystemApi; import android.app.backup.RestoreSession; import android.app.backup.IBackupManager; import android.app.backup.IRestoreSession; @@ -114,7 +115,7 @@ try { sService.dataChanged(packageName); } catch (RemoteException e) { - Log.d(TAG, "dataChanged(pkg) couldn't connect"); + Log.e(TAG, "dataChanged(pkg) couldn't connect"); } } } @@ -150,7 +151,7 @@ result = session.restorePackage(mContext.getPackageName(), observer); } } catch (RemoteException e) { - Log.w(TAG, "restoreSelf() unable to contact service"); + Log.e(TAG, "restoreSelf() unable to contact service"); } finally { if (session != null) { session.endRestoreSession(); @@ -160,11 +161,14 @@ return result; } + // system APIs start here + /** * Begin the process of restoring data from backup. See the * {@link android.app.backup.RestoreSession} class for documentation on that process. * @hide */ + @SystemApi public RestoreSession beginRestoreSession() { RestoreSession session = null; checkServiceBinder(); @@ -176,9 +180,163 @@ session = new RestoreSession(mContext, binder); } } catch (RemoteException e) { - Log.w(TAG, "beginRestoreSession() couldn't connect"); + Log.e(TAG, "beginRestoreSession() couldn't connect"); } } return session; } + + /** + * Enable/disable the backup service entirely. When disabled, no backup + * or restore operations will take place. Data-changed notifications will + * still be observed and collected, however, so that changes made while the + * mechanism was disabled will still be backed up properly if it is enabled + * at some point in the future. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + * + * @hide + */ + @SystemApi + public void setBackupEnabled(boolean isEnabled) { + checkServiceBinder(); + if (sService != null) { + try { + sService.setBackupEnabled(isEnabled); + } catch (RemoteException e) { + Log.e(TAG, "setBackupEnabled() couldn't connect"); + } + } + } + + /** + * Report whether the backup mechanism is currently enabled. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + * + * @hide + */ + @SystemApi + public boolean isBackupEnabled() { + checkServiceBinder(); + if (sService != null) { + try { + return sService.isBackupEnabled(); + } catch (RemoteException e) { + Log.e(TAG, "isBackupEnabled() couldn't connect"); + } + } + return false; + } + + /** + * Enable/disable data restore at application install time. When enabled, app + * installation will include an attempt to fetch the app's historical data from + * the archival restore dataset (if any). When disabled, no such attempt will + * be made. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + * + * @hide + */ + @SystemApi + public void setAutoRestore(boolean isEnabled) { + checkServiceBinder(); + if (sService != null) { + try { + sService.setAutoRestore(isEnabled); + } catch (RemoteException e) { + Log.e(TAG, "setAutoRestore() couldn't connect"); + } + } + } + + /** + * Identify the currently selected transport. Callers must hold the + * android.permission.BACKUP permission to use this method. + * @return The name of the currently active backup transport. In case of + * failure or if no transport is currently active, this method returns {@code null}. + * + * @hide + */ + @SystemApi + public String getCurrentTransport() { + checkServiceBinder(); + if (sService != null) { + try { + return sService.getCurrentTransport(); + } catch (RemoteException e) { + Log.e(TAG, "getCurrentTransport() couldn't connect"); + } + } + return null; + } + + /** + * Request a list of all available backup transports' names. Callers must + * hold the android.permission.BACKUP permission to use this method. + * + * @hide + */ + @SystemApi + public String[] listAllTransports() { + checkServiceBinder(); + if (sService != null) { + try { + return sService.listAllTransports(); + } catch (RemoteException e) { + Log.e(TAG, "listAllTransports() couldn't connect"); + } + } + return null; + } + + /** + * Specify the current backup transport. Callers must hold the + * android.permission.BACKUP permission to use this method. + * + * @param transport The name of the transport to select. This should be one + * of the names returned by {@link #listAllTransports()}. + * @return The name of the previously selected transport. If the given transport + * name is not one of the currently available transports, no change is made to + * the current transport setting and the method returns null. + * + * @hide + */ + @SystemApi + public String selectBackupTransport(String transport) { + checkServiceBinder(); + if (sService != null) { + try { + return sService.selectBackupTransport(transport); + } catch (RemoteException e) { + Log.e(TAG, "selectBackupTransport() couldn't connect"); + } + } + return null; + } + + /** + * Schedule an immediate backup attempt for all pending key/value updates. This + * is primarily intended for transports to use when they detect a suitable + * opportunity for doing a backup pass. If there are no pending updates to + * be sent, no action will be taken. Even if some updates are pending, the + * transport will still be asked to confirm via the usual requestBackupTime() + * method. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + * + * @hide + */ + @SystemApi + public void backupNow() { + checkServiceBinder(); + if (sService != null) { + try { + sService.backupNow(); + } catch (RemoteException e) { + Log.e(TAG, "backupNow() couldn't connect"); + } + } + } }
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java new file mode 100644 index 0000000..70bb5e4 --- /dev/null +++ b/core/java/android/app/backup/BackupTransport.java
@@ -0,0 +1,607 @@ +/* + * Copyright (C) 2014 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.backup; + +import android.annotation.SystemApi; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; + +import com.android.internal.backup.IBackupTransport; + +/** + * Concrete class that provides a stable-API bridge between IBackupTransport + * and its implementations. + * + * @hide + */ +@SystemApi +public class BackupTransport { + // Zero return always means things are okay. If returned from + // getNextFullRestoreDataChunk(), it means that no data could be delivered at + // this time, but the restore is still running and the caller should simply + // retry. + public static final int TRANSPORT_OK = 0; + + // -1 is special; it is used in getNextFullRestoreDataChunk() to indicate that + // we've delivered the entire data stream for the current restore target. + public static final int NO_MORE_DATA = -1; + + // Result codes that indicate real errors are negative and not -1 + public static final int TRANSPORT_ERROR = -1000; + public static final int TRANSPORT_NOT_INITIALIZED = -1001; + public static final int TRANSPORT_PACKAGE_REJECTED = -1002; + public static final int AGENT_ERROR = -1003; + public static final int AGENT_UNKNOWN = -1004; + + IBackupTransport mBinderImpl = new TransportImpl(); + + public IBinder getBinder() { + return mBinderImpl.asBinder(); + } + + // ------------------------------------------------------------------------------------ + // Transport self-description and general configuration interfaces + // + + /** + * Ask the transport for the name under which it should be registered. This will + * typically be its host service's component name, but need not be. + */ + public String name() { + throw new UnsupportedOperationException("Transport name() not implemented"); + } + + /** + * Ask the transport for an Intent that can be used to launch any internal + * configuration Activity that it wishes to present. For example, the transport + * may offer a UI for allowing the user to supply login credentials for the + * transport's off-device backend. + * + * <p>If the transport does not supply any user-facing configuration UI, it should + * return {@code null} from this method. + * + * @return An Intent that can be passed to Context.startActivity() in order to + * launch the transport's configuration UI. This method will return {@code null} + * if the transport does not offer any user-facing configuration UI. + */ + public Intent configurationIntent() { + return null; + } + + /** + * On demand, supply a one-line string that can be shown to the user that + * describes the current backend destination. For example, a transport that + * can potentially associate backup data with arbitrary user accounts should + * include the name of the currently-active account here. + * + * @return A string describing the destination to which the transport is currently + * sending data. This method should not return null. + */ + public String currentDestinationString() { + throw new UnsupportedOperationException( + "Transport currentDestinationString() not implemented"); + } + + /** + * Ask the transport for an Intent that can be used to launch a more detailed + * secondary data management activity. For example, the configuration intent might + * be one for allowing the user to select which account they wish to associate + * their backups with, and the management intent might be one which presents a + * UI for managing the data on the backend. + * + * <p>In the Settings UI, the configuration intent will typically be invoked + * when the user taps on the preferences item labeled with the current + * destination string, and the management intent will be placed in an overflow + * menu labelled with the management label string. + * + * <p>If the transport does not supply any user-facing data management + * UI, then it should return {@code null} from this method. + * + * @return An intent that can be passed to Context.startActivity() in order to + * launch the transport's data-management UI. This method will return + * {@code null} if the transport does not offer any user-facing data + * management UI. + */ + public Intent dataManagementIntent() { + return null; + } + + /** + * On demand, supply a short string that can be shown to the user as the label + * on an overflow menu item used to invoked the data management UI. + * + * @return A string to be used as the label for the transport's data management + * affordance. If the transport supplies a data management intent, this + * method must not return {@code null}. + */ + public String dataManagementLabel() { + throw new UnsupportedOperationException( + "Transport dataManagementLabel() not implemented"); + } + + /** + * Ask the transport where, on local device storage, to keep backup state blobs. + * This is per-transport so that mock transports used for testing can coexist with + * "live" backup services without interfering with the live bookkeeping. The + * returned string should be a name that is expected to be unambiguous among all + * available backup transports; the name of the class implementing the transport + * is a good choice. + * + * @return A unique name, suitable for use as a file or directory name, that the + * Backup Manager could use to disambiguate state files associated with + * different backup transports. + */ + public String transportDirName() { + throw new UnsupportedOperationException( + "Transport transportDirName() not implemented"); + } + + // ------------------------------------------------------------------------------------ + // Device-level operations common to both key/value and full-data storage + + /** + * Initialize the server side storage for this device, erasing all stored data. + * The transport may send the request immediately, or may buffer it. After + * this is called, {@link #finishBackup} will be called to ensure the request + * is sent and received successfully. + * + * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far) or + * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure). + */ + public int initializeDevice() { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * Erase the given application's data from the backup destination. This clears + * out the given package's data from the current backup set, making it as though + * the app had never yet been backed up. After this is called, {@link finishBackup} + * must be called to ensure that the operation is recorded successfully. + * + * @return the same error codes as {@link #performBackup}. + */ + public int clearBackupData(PackageInfo packageInfo) { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * Finish sending application data to the backup destination. This must be + * called after {@link #performBackup}, {@link #performFullBackup}, or {@link clearBackupData} + * to ensure that all data is sent and the operation properly finalized. Only when this + * method returns true can a backup be assumed to have succeeded. + * + * @return the same error codes as {@link #performBackup} or {@link #performFullBackup}. + */ + public int finishBackup() { + return BackupTransport.TRANSPORT_ERROR; + } + + // ------------------------------------------------------------------------------------ + // Key/value incremental backup support interfaces + + /** + * Verify that this is a suitable time for a key/value backup pass. This should return zero + * if a backup is reasonable right now, some positive value otherwise. This method + * will be called outside of the {@link #performBackup}/{@link #finishBackup} pair. + * + * <p>If this is not a suitable time for a backup, the transport should return a + * backoff delay, in milliseconds, after which the Backup Manager should try again. + * + * @return Zero if this is a suitable time for a backup pass, or a positive time delay + * in milliseconds to suggest deferring the backup pass for a while. + */ + public long requestBackupTime() { + return 0; + } + + /** + * Send one application's key/value data update to the backup destination. The + * transport may send the data immediately, or may buffer it. After this is called, + * {@link #finishBackup} will be called to ensure the data is sent and recorded successfully. + * + * @param packageInfo The identity of the application whose data is being backed up. + * This specifically includes the signature list for the package. + * @param data The data stream that resulted from invoking the application's + * BackupService.doBackup() method. This may be a pipe rather than a file on + * persistent media, so it may not be seekable. + * @param wipeAllFirst When true, <i>all</i> backed-up data for the current device/account + * must be erased prior to the storage of the data provided here. The purpose of this + * is to provide a guarantee that no stale data exists in the restore set when the + * device begins providing incremental backups. + * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far), + * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), or + * {@link BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has + * become lost due to inactivity purge or some other reason and needs re-initializing) + */ + public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) { + return BackupTransport.TRANSPORT_ERROR; + } + + // ------------------------------------------------------------------------------------ + // Key/value dataset restore interfaces + + /** + * Get the set of all backups currently available over this transport. + * + * @return Descriptions of the set of restore images available for this device, + * or null if an error occurred (the attempt should be rescheduled). + **/ + public RestoreSet[] getAvailableRestoreSets() { + return null; + } + + /** + * Get the identifying token of the backup set currently being stored from + * this device. This is used in the case of applications wishing to restore + * their last-known-good data. + * + * @return A token that can be passed to {@link #startRestore}, or 0 if there + * is no backup set available corresponding to the current device state. + */ + public long getCurrentRestoreSet() { + return 0; + } + + /** + * Start restoring application data from backup. After calling this function, + * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData} + * to walk through the actual application data. + * + * @param token A backup token as returned by {@link #getAvailableRestoreSets} + * or {@link #getCurrentRestoreSet}. + * @param packages List of applications to restore (if data is available). + * Application data will be restored in the order given. + * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far, call + * {@link #nextRestorePackage}) or {@link BackupTransport#TRANSPORT_ERROR} + * (an error occurred, the restore should be aborted and rescheduled). + */ + public int startRestore(long token, PackageInfo[] packages) { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * Get the package name of the next application with data in the backup store, plus + * a description of the structure of the restored archive: either TYPE_KEY_VALUE for + * an original-API key/value dataset, or TYPE_FULL_STREAM for a tarball-type archive stream. + * + * <p>If the package name in the returned RestoreDescription object is the singleton + * {@link RestoreDescription#NO_MORE_PACKAGES}, it indicates that no further data is available + * in the current restore session: all packages described in startRestore() have been + * processed. + * + * <p>If this method returns {@code null}, it means that a transport-level error has + * occurred and the entire restore operation should be abandoned. + * + * <p class="note">The OS may call {@link #nextRestorePackage()} multiple times + * before calling either {@link #getRestoreData(ParcelFileDescriptor) getRestoreData()} + * or {@link #getNextFullRestoreDataChunk(ParcelFileDescriptor) getNextFullRestoreDataChunk()}. + * It does this when it has determined that it needs to skip restore of one or more + * packages. The transport should not actually transfer any restore data for + * the given package in response to {@link #nextRestorePackage()}, but rather wait + * for an explicit request before doing so. + * + * @return A RestoreDescription object containing the name of one of the packages + * supplied to {@link #startRestore} plus an indicator of the data type of that + * restore data; or {@link RestoreDescription#NO_MORE_PACKAGES} to indicate that + * no more packages can be restored in this session; or {@code null} to indicate + * a transport-level error. + */ + public RestoreDescription nextRestorePackage() { + return null; + } + + /** + * Get the data for the application returned by {@link #nextRestorePackage}, if that + * method reported {@link RestoreDescription#TYPE_KEY_VALUE} as its delivery type. + * If the package has only TYPE_FULL_STREAM data, then this method will return an + * error. + * + * @param data An open, writable file into which the key/value backup data should be stored. + * @return the same error codes as {@link #startRestore}. + */ + public int getRestoreData(ParcelFileDescriptor outFd) { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * End a restore session (aborting any in-process data transfer as necessary), + * freeing any resources and connections used during the restore process. + */ + public void finishRestore() { + throw new UnsupportedOperationException( + "Transport finishRestore() not implemented"); + } + + // ------------------------------------------------------------------------------------ + // Full backup interfaces + + /** + * Verify that this is a suitable time for a full-data backup pass. This should return zero + * if a backup is reasonable right now, some positive value otherwise. This method + * will be called outside of the {@link #performFullBackup}/{@link #finishBackup} pair. + * + * <p>If this is not a suitable time for a backup, the transport should return a + * backoff delay, in milliseconds, after which the Backup Manager should try again. + * + * @return Zero if this is a suitable time for a backup pass, or a positive time delay + * in milliseconds to suggest deferring the backup pass for a while. + * + * @see #requestBackupTime() + */ + public long requestFullBackupTime() { + return 0; + } + + /** + * Begin the process of sending an application's full-data archive to the backend. + * The description of the package whose data will be delivered is provided, as well as + * the socket file descriptor on which the transport will receive the data itself. + * + * <p>If the package is not eligible for backup, the transport should return + * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED}. In this case the system will + * simply proceed with the next candidate if any, or finish the full backup operation + * if all apps have been processed. + * + * <p>After the transport returns {@link BackupTransport#TRANSPORT_OK} from this + * method, the OS will proceed to call {@link #sendBackupData()} one or more times + * to deliver the application's data as a streamed tarball. The transport should not + * read() from the socket except as instructed to via the {@link #sendBackupData(int)} + * method. + * + * <p>After all data has been delivered to the transport, the system will call + * {@link #finishBackup()}. At this point the transport should commit the data to + * its datastore, if appropriate, and close the socket that had been provided in + * {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}. + * + * <p class="note">If the transport returns TRANSPORT_OK from this method, then the + * OS will always provide a matching call to {@link #finishBackup()} even if sending + * data via {@link #sendBackupData(int)} failed at some point. + * + * @param targetPackage The package whose data is to follow. + * @param socket The socket file descriptor through which the data will be provided. + * If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still + * close this file descriptor now; otherwise it should be cached for use during + * succeeding calls to {@link #sendBackupData(int)}, and closed in response to + * {@link #finishBackup()}. + * @return TRANSPORT_PACKAGE_REJECTED to indicate that the stated application is not + * to be backed up; TRANSPORT_OK to indicate that the OS may proceed with delivering + * backup data; TRANSPORT_ERROR to indicate a fatal error condition that precludes + * performing a backup at this time. + */ + public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) { + return BackupTransport.TRANSPORT_PACKAGE_REJECTED; + } + + /** + * Tells the transport to read {@code numBytes} bytes of data from the socket file + * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)} + * call, and deliver those bytes to the datastore. + * + * @param numBytes The number of bytes of tarball data available to be read from the + * socket. + * @return TRANSPORT_OK on successful processing of the data; TRANSPORT_ERROR to + * indicate a fatal error situation. If an error is returned, the system will + * call finishBackup() and stop attempting backups until after a backoff and retry + * interval. + */ + public int sendBackupData(int numBytes) { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * Tells the transport to cancel the currently-ongoing full backup operation. This + * will happen between {@link #performFullBackup()} and {@link #finishBackup()} + * if the OS needs to abort the backup operation for any reason, such as a crash in + * the application undergoing backup. + * + * <p>When it receives this call, the transport should discard any partial archive + * that it has stored so far. If possible it should also roll back to the previous + * known-good archive in its datastore. + * + * <p>If the transport receives this callback, it will <em>not</em> receive a + * call to {@link #finishBackup()}. It needs to tear down any ongoing backup state + * here. + */ + public void cancelFullBackup() { + throw new UnsupportedOperationException( + "Transport cancelFullBackup() not implemented"); + } + + // ------------------------------------------------------------------------------------ + // Full restore interfaces + + /** + * Ask the transport to provide data for the "current" package being restored. This + * is the package that was just reported by {@link #nextRestorePackage()} as having + * {@link RestoreDescription#TYPE_FULL_STREAM} data. + * + * The transport writes some data to the socket supplied to this call, and returns + * the number of bytes written. The system will then read that many bytes and + * stream them to the application's agent for restore, then will call this method again + * to receive the next chunk of the archive. This sequence will be repeated until the + * transport returns zero indicating that all of the package's data has been delivered + * (or returns a negative value indicating some sort of hard error condition at the + * transport level). + * + * <p>After this method returns zero, the system will then call + * {@link #getNextFullRestorePackage()} to begin the restore process for the next + * application, and the sequence begins again. + * + * <p>The transport should always close this socket when returning from this method. + * Do not cache this socket across multiple calls or you may leak file descriptors. + * + * @param socket The file descriptor that the transport will use for delivering the + * streamed archive. The transport must close this socket in all cases when returning + * from this method. + * @return {@link #NO_MORE_DATA} when no more data for the current package is available. + * A positive value indicates the presence of that many bytes to be delivered to the app. + * A value of zero indicates that no data was deliverable at this time, but the restore + * is still running and the caller should retry. {@link #TRANSPORT_PACKAGE_REJECTED} + * means that the current package's restore operation should be aborted, but that + * the transport itself is still in a good state and so a multiple-package restore + * sequence can still be continued. Any other negative return value is treated as a + * fatal error condition that aborts all further restore operations on the current dataset. + */ + public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { + return 0; + } + + /** + * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM} + * data for restore, it will invoke this method to tell the transport that it should + * abandon the data download for the current package. The OS will then either call + * {@link #nextRestorePackage()} again to move on to restoring the next package in the + * set being iterated over, or will call {@link #finishRestore()} to shut down the restore + * operation. + * + * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the + * current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious + * transport-level failure. If the transport reports an error here, the entire restore + * operation will immediately be finished with no further attempts to restore app data. + */ + public int abortFullRestore() { + return BackupTransport.TRANSPORT_OK; + } + + /** + * Bridge between the actual IBackupTransport implementation and the stable API. If the + * binder interface needs to change, we use this layer to translate so that we can + * (if appropriate) decouple those framework-side changes from the BackupTransport + * implementations. + */ + class TransportImpl extends IBackupTransport.Stub { + + @Override + public String name() throws RemoteException { + return BackupTransport.this.name(); + } + + @Override + public Intent configurationIntent() throws RemoteException { + return BackupTransport.this.configurationIntent(); + } + + @Override + public String currentDestinationString() throws RemoteException { + return BackupTransport.this.currentDestinationString(); + } + + @Override + public Intent dataManagementIntent() { + return BackupTransport.this.dataManagementIntent(); + } + + @Override + public String dataManagementLabel() { + return BackupTransport.this.dataManagementLabel(); + } + + @Override + public String transportDirName() throws RemoteException { + return BackupTransport.this.transportDirName(); + } + + @Override + public long requestBackupTime() throws RemoteException { + return BackupTransport.this.requestBackupTime(); + } + + @Override + public int initializeDevice() throws RemoteException { + return BackupTransport.this.initializeDevice(); + } + + @Override + public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) + throws RemoteException { + return BackupTransport.this.performBackup(packageInfo, inFd); + } + + @Override + public int clearBackupData(PackageInfo packageInfo) throws RemoteException { + return BackupTransport.this.clearBackupData(packageInfo); + } + + @Override + public int finishBackup() throws RemoteException { + return BackupTransport.this.finishBackup(); + } + + @Override + public RestoreSet[] getAvailableRestoreSets() throws RemoteException { + return BackupTransport.this.getAvailableRestoreSets(); + } + + @Override + public long getCurrentRestoreSet() throws RemoteException { + return BackupTransport.this.getCurrentRestoreSet(); + } + + @Override + public int startRestore(long token, PackageInfo[] packages) throws RemoteException { + return BackupTransport.this.startRestore(token, packages); + } + + @Override + public RestoreDescription nextRestorePackage() throws RemoteException { + return BackupTransport.this.nextRestorePackage(); + } + + @Override + public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException { + return BackupTransport.this.getRestoreData(outFd); + } + + @Override + public void finishRestore() throws RemoteException { + BackupTransport.this.finishRestore(); + } + + @Override + public long requestFullBackupTime() throws RemoteException { + return BackupTransport.this.requestFullBackupTime(); + } + + @Override + public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) throws RemoteException { + return BackupTransport.this.performFullBackup(targetPackage, socket); + } + + @Override + public int sendBackupData(int numBytes) throws RemoteException { + return BackupTransport.this.sendBackupData(numBytes); + } + + @Override + public void cancelFullBackup() throws RemoteException { + BackupTransport.this.cancelFullBackup(); + } + + @Override + public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { + return BackupTransport.this.getNextFullRestoreDataChunk(socket); + } + + @Override + public int abortFullRestore() { + return BackupTransport.this.abortFullRestore(); + } + } +}
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index 477285d..e5b47c6 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java
@@ -16,9 +16,6 @@ package android.app.backup; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; @@ -43,6 +40,7 @@ public static final String OBB_TREE_TOKEN = "obb"; public static final String ROOT_TREE_TOKEN = "r"; public static final String DATA_TREE_TOKEN = "f"; + public static final String NO_BACKUP_TREE_TOKEN = "nb"; public static final String DATABASE_TREE_TOKEN = "db"; public static final String SHAREDPREFS_TREE_TOKEN = "sp"; public static final String MANAGED_EXTERNAL_TREE_TOKEN = "ef";
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index 12ee3b6..8a44c8e 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -167,8 +167,16 @@ * are to be backed up. The <code>allApps</code> parameter supersedes this. */ void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, - boolean includeShared, boolean allApps, boolean allIncludesSystem, - in String[] packageNames); + boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem, + boolean doCompress, in String[] packageNames); + + /** + * Perform a full-dataset backup of the given applications via the currently active + * transport. + * + * @param packageNames The package names of the apps whose data are to be backed up. + */ + void fullTransportBackup(in String[] packageNames); /** * Restore device content from the data stream passed through the given socket. The @@ -242,6 +250,18 @@ String getDestinationString(String transport); /** + * Get the manage-data UI intent, if any, from the given transport. Callers must + * hold the android.permission.BACKUP permission in order to use this method. + */ + Intent getDataManagementIntent(String transport); + + /** + * Get the manage-data menu label, if any, from the given transport. Callers must + * hold the android.permission.BACKUP permission in order to use this method. + */ + String getDataManagementLabel(String transport); + + /** * Begin a restore session. Either or both of packageName and transportID * may be null. If packageName is non-null, then only the given package will be * considered for restore. If transportID is null, then the restore will use
diff --git a/core/java/android/app/backup/RestoreDescription.aidl b/core/java/android/app/backup/RestoreDescription.aidl new file mode 100644 index 0000000..9cbea78 --- /dev/null +++ b/core/java/android/app/backup/RestoreDescription.aidl
@@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 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.backup; + +parcelable RestoreDescription;
diff --git a/core/java/android/app/backup/RestoreDescription.java b/core/java/android/app/backup/RestoreDescription.java new file mode 100644 index 0000000..611ff07 --- /dev/null +++ b/core/java/android/app/backup/RestoreDescription.java
@@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014 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.backup; + +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Description of the available restore data for a given package. Returned by a + * BackupTransport in response to a request about the next available restorable + * package. + * + * @see BackupTransport#nextRestorePackage() + * + * @hide + */ +@SystemApi +public class RestoreDescription implements Parcelable { + private final String mPackageName; + private final int mDataType; + + private static final String NO_MORE_PACKAGES_SENTINEL = ""; + + /** + * Return this constant RestoreDescription from BackupTransport.nextRestorePackage() + * to indicate that no more package data is available in the current restore operation. + */ + public static final RestoreDescription NO_MORE_PACKAGES = + new RestoreDescription(NO_MORE_PACKAGES_SENTINEL, 0); + + // --------------------------------------- + // Data type identifiers + + /** This package's restore data is an original-style key/value dataset */ + public static final int TYPE_KEY_VALUE = 1; + + /** This package's restore data is a tarball-type full data stream */ + public static final int TYPE_FULL_STREAM = 2; + + @Override + public String toString() { + return "RestoreDescription{" + mPackageName + " : " + + ((mDataType == TYPE_KEY_VALUE) ? "KEY_VALUE" : "STREAM") + + '}'; + } + + // --------------------------------------- + // API + + public RestoreDescription(String packageName, int dataType) { + mPackageName = packageName; + mDataType = dataType; + } + + public String getPackageName() { + return mPackageName; + } + + public int getDataType() { + return mDataType; + } + + // --------------------------------------- + // Parcelable implementation - not used by transport + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(mPackageName); + out.writeInt(mDataType); + } + + public static final Parcelable.Creator<RestoreDescription> CREATOR + = new Parcelable.Creator<RestoreDescription>() { + public RestoreDescription createFromParcel(Parcel in) { + final RestoreDescription unparceled = new RestoreDescription(in); + return (NO_MORE_PACKAGES_SENTINEL.equals(unparceled.mPackageName)) + ? NO_MORE_PACKAGES + : unparceled; + } + + public RestoreDescription[] newArray(int size) { + return new RestoreDescription[size]; + } + }; + + private RestoreDescription(Parcel in) { + mPackageName = in.readString(); + mDataType = in.readInt(); + } +}
diff --git a/core/java/android/app/backup/RestoreObserver.java b/core/java/android/app/backup/RestoreObserver.java index dbddb78..b4a23d0 100644 --- a/core/java/android/app/backup/RestoreObserver.java +++ b/core/java/android/app/backup/RestoreObserver.java
@@ -17,6 +17,8 @@ package android.app.backup; import java.lang.String; + +import android.annotation.SystemApi; import android.app.backup.RestoreSet; /** @@ -36,6 +38,7 @@ * * @hide */ + @SystemApi public void restoreSetsAvailable(RestoreSet[] result) { }
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java index 7181c61..0a885b6 100644 --- a/core/java/android/app/backup/RestoreSession.java +++ b/core/java/android/app/backup/RestoreSession.java
@@ -16,6 +16,7 @@ package android.app.backup; +import android.annotation.SystemApi; import android.app.backup.RestoreObserver; import android.app.backup.RestoreSet; import android.app.backup.IRestoreObserver; @@ -30,6 +31,7 @@ * Interface for managing a restore session. * @hide */ +@SystemApi public class RestoreSession { static final String TAG = "RestoreSession";
diff --git a/core/java/android/app/backup/RestoreSet.java b/core/java/android/app/backup/RestoreSet.java index 0431977..aacaf7c 100644 --- a/core/java/android/app/backup/RestoreSet.java +++ b/core/java/android/app/backup/RestoreSet.java
@@ -16,6 +16,7 @@ package android.app.backup; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -25,6 +26,7 @@ * * @hide */ +@SystemApi public class RestoreSet implements Parcelable { /** * Name of this restore set. May be user generated, may simply be the name
diff --git a/core/java/android/app/backup/SharedPreferencesBackupHelper.java b/core/java/android/app/backup/SharedPreferencesBackupHelper.java index 213bd31..939616b 100644 --- a/core/java/android/app/backup/SharedPreferencesBackupHelper.java +++ b/core/java/android/app/backup/SharedPreferencesBackupHelper.java
@@ -18,7 +18,6 @@ import android.app.QueuedWork; import android.content.Context; -import android.content.SharedPreferences; import android.os.ParcelFileDescriptor; import android.util.Log;
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java index 9e8ab2c..b8575d7 100644 --- a/core/java/android/app/backup/WallpaperBackupHelper.java +++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -80,17 +80,17 @@ mFiles = files; mKeys = keys; - WallpaperManager wpm; - wpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE); - mDesiredMinWidth = (double) wpm.getDesiredMinimumWidth(); + final WindowManager wm = + (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + final WallpaperManager wpm = + (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE); + final Display d = wm.getDefaultDisplay(); + final Point size = new Point(); + d.getSize(size); + mDesiredMinWidth = size.x; mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight(); - if (mDesiredMinWidth <= 0 || mDesiredMinHeight <= 0) { - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display d = wm.getDefaultDisplay(); - Point size = new Point(); - d.getSize(size); - mDesiredMinWidth = size.x; + if (mDesiredMinHeight <= 0) { mDesiredMinHeight = size.y; } @@ -130,25 +130,25 @@ if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth + " h=" + options.outHeight); - // How much does the image differ from our preference? The threshold - // here is set to accept any image larger than our target, because - // scaling down is acceptable; but to reject images that are deemed - // "too small" to scale up attractively. The value 1.33 is just barely - // too low to pass Nexus 1 or Droid wallpapers for use on a Xoom, but - // will pass anything relatively larger. - double widthRatio = mDesiredMinWidth / options.outWidth; - double heightRatio = mDesiredMinHeight / options.outHeight; - if (widthRatio > 0 && widthRatio < 1.33 + // We accept any wallpaper that is at least as wide as our preference + // (i.e. wide enough to fill the screen), and is within a comfortable + // factor of the target height, to avoid significant clipping/scaling/ + // letterboxing. + final double heightRatio = mDesiredMinHeight / options.outHeight; + if (options.outWidth >= mDesiredMinWidth && heightRatio > 0 && heightRatio < 1.33) { // sufficiently close to our resolution; go ahead and use it - if (DEBUG) Slog.d(TAG, "wallpaper dimension match; using"); + Slog.d(TAG, "Applying restored wallpaper image."); f.renameTo(new File(WALLPAPER_IMAGE)); // TODO: spin a service to copy the restored image to sd/usb storage, // since it does not exist anywhere other than the private wallpaper // file. } else { - if (DEBUG) Slog.d(TAG, "dimensions too far off: wr=" + widthRatio - + " hr=" + heightRatio); + Slog.i(TAG, "Restored image dimensions (w=" + + options.outWidth + ", h=" + options.outHeight + + ") too far off target (tw=" + + mDesiredMinWidth + ", th=" + mDesiredMinHeight + + "); falling back to default wallpaper."); f.delete(); } }
diff --git a/core/java/android/app/job/IJobCallback.aidl b/core/java/android/app/job/IJobCallback.aidl new file mode 100644 index 0000000..2d3948f --- /dev/null +++ b/core/java/android/app/job/IJobCallback.aidl
@@ -0,0 +1,53 @@ +/** + * Copyright 2014, 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.job; + +/** + * The server side of the JobScheduler IPC protocols. The app-side implementation + * invokes on this interface to indicate completion of the (asynchronous) instructions + * issued by the server. + * + * In all cases, the 'who' parameter is the caller's service binder, used to track + * which Job Service instance is reporting. + * + * {@hide} + */ +interface IJobCallback { + /** + * Immediate callback to the system after sending a start signal, used to quickly detect ANR. + * + * @param jobId Unique integer used to identify this job. + * @param ongoing True to indicate that the client is processing the job. False if the job is + * complete + */ + void acknowledgeStartMessage(int jobId, boolean ongoing); + /** + * Immediate callback to the system after sending a stop signal, used to quickly detect ANR. + * + * @param jobId Unique integer used to identify this job. + * @param reschedule Whether or not to reschedule this job. + */ + void acknowledgeStopMessage(int jobId, boolean reschedule); + /* + * Tell the job manager that the client is done with its execution, so that it can go on to + * the next one and stop attributing wakelock time to us etc. + * + * @param jobId Unique integer used to identify this job. + * @param reschedule Whether or not to reschedule this job. + */ + void jobFinished(int jobId, boolean reschedule); +}
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/core/java/android/app/job/IJobScheduler.aidl new file mode 100644 index 0000000..f1258ae --- /dev/null +++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -0,0 +1,30 @@ +/** + * Copyright (C) 2014 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.job; + +import android.app.job.JobInfo; + + /** + * IPC interface that supports the app-facing {@link #JobScheduler} api. + * {@hide} + */ +interface IJobScheduler { + int schedule(in JobInfo job); + void cancel(int jobId); + void cancelAll(); + List<JobInfo> getAllPendingJobs(); +}
diff --git a/core/java/android/app/job/IJobService.aidl b/core/java/android/app/job/IJobService.aidl new file mode 100644 index 0000000..7f55d29 --- /dev/null +++ b/core/java/android/app/job/IJobService.aidl
@@ -0,0 +1,32 @@ +/** + * Copyright 2014, 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.job; + +import android.app.job.JobParameters; + +/** + * Interface that the framework uses to communicate with application code that implements a + * JobService. End user code does not implement this interface directly; instead, the app's + * service implementation will extend android.app.job.JobService. + * {@hide} + */ +oneway interface IJobService { + /** Begin execution of application's job. */ + void startJob(in JobParameters jobParams); + /** Stop execution of application's job. */ + void stopJob(in JobParameters jobParams); +}
diff --git a/core/java/android/app/job/JobInfo.aidl b/core/java/android/app/job/JobInfo.aidl new file mode 100644 index 0000000..7b198a8 --- /dev/null +++ b/core/java/android/app/job/JobInfo.aidl
@@ -0,0 +1,19 @@ +/** + * Copyright (C) 2014 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.job; + +parcelable JobInfo;
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java new file mode 100644 index 0000000..0d9e778 --- /dev/null +++ b/core/java/android/app/job/JobInfo.java
@@ -0,0 +1,473 @@ +/* + * Copyright (C) 2014 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.job; + +import android.content.ComponentName; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; + +/** + * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the + * parameters required to schedule work against the calling application. These are constructed + * using the {@link JobInfo.Builder}. + * You must specify at least one sort of constraint on the JobInfo object that you are creating. + * The goal here is to provide the scheduler with high-level semantics about the work you want to + * accomplish. Doing otherwise with throw an exception in your app. + */ +public class JobInfo implements Parcelable { + /** Default. */ + public static final int NETWORK_TYPE_NONE = 0; + /** This job requires network connectivity. */ + public static final int NETWORK_TYPE_ANY = 1; + /** This job requires network connectivity that is unmetered. */ + public static final int NETWORK_TYPE_UNMETERED = 2; + + /** + * Amount of backoff a job has initially by default, in milliseconds. + */ + public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 30 seconds. + + /** + * Maximum backoff we allow for a job, in milliseconds. + */ + public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000; // 5 hours. + + /** + * Linearly back-off a failed job. See + * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} + * retry_time(current_time, num_failures) = + * current_time + initial_backoff_millis * num_failures, num_failures >= 1 + */ + public static final int BACKOFF_POLICY_LINEAR = 0; + + /** + * Exponentially back-off a failed job. See + * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} + * + * retry_time(current_time, num_failures) = + * current_time + initial_backoff_millis * 2 ^ (num_failures - 1), num_failures >= 1 + */ + public static final int BACKOFF_POLICY_EXPONENTIAL = 1; + + /** + * Default type of backoff. + * @hide + */ + public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL; + + private final int jobId; + private final PersistableBundle extras; + private final ComponentName service; + private final boolean requireCharging; + private final boolean requireDeviceIdle; + private final boolean hasEarlyConstraint; + private final boolean hasLateConstraint; + private final int networkType; + private final long minLatencyMillis; + private final long maxExecutionDelayMillis; + private final boolean isPeriodic; + private final boolean isPersisted; + private final long intervalMillis; + private final long initialBackoffMillis; + private final int backoffPolicy; + + /** + * Unique job id associated with this class. This is assigned to your job by the scheduler. + */ + public int getId() { + return jobId; + } + + /** + * Bundle of extras which are returned to your application at execution time. + */ + public PersistableBundle getExtras() { + return extras; + } + + /** + * Name of the service endpoint that will be called back into by the JobScheduler. + */ + public ComponentName getService() { + return service; + } + + /** + * Whether this job needs the device to be plugged in. + */ + public boolean isRequireCharging() { + return requireCharging; + } + + /** + * Whether this job needs the device to be in an Idle maintenance window. + */ + public boolean isRequireDeviceIdle() { + return requireDeviceIdle; + } + + /** + * One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY}, + * {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, or + * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}. + */ + public int getNetworkType() { + return networkType; + } + + /** + * Set for a job that does not recur periodically, to specify a delay after which the job + * will be eligible for execution. This value is not set if the job recurs periodically. + */ + public long getMinLatencyMillis() { + return minLatencyMillis; + } + + /** + * See {@link Builder#setOverrideDeadline(long)}. This value is not set if the job recurs + * periodically. + */ + public long getMaxExecutionDelayMillis() { + return maxExecutionDelayMillis; + } + + /** + * Track whether this job will repeat with a given period. + */ + public boolean isPeriodic() { + return isPeriodic; + } + + /** + * @return Whether or not this job should be persisted across device reboots. + */ + public boolean isPersisted() { + return isPersisted; + } + + /** + * Set to the interval between occurrences of this job. This value is <b>not</b> set if the + * job does not recur periodically. + */ + public long getIntervalMillis() { + return intervalMillis; + } + + /** + * The amount of time the JobScheduler will wait before rescheduling a failed job. This value + * will be increased depending on the backoff policy specified at job creation time. Defaults + * to 5 seconds. + */ + public long getInitialBackoffMillis() { + return initialBackoffMillis; + } + + /** + * One of either {@link android.app.job.JobInfo#BACKOFF_POLICY_EXPONENTIAL}, or + * {@link android.app.job.JobInfo#BACKOFF_POLICY_LINEAR}, depending on which criteria you set + * when creating this job. + */ + public int getBackoffPolicy() { + return backoffPolicy; + } + + /** + * User can specify an early constraint of 0L, which is valid, so we keep track of whether the + * function was called at all. + * @hide + */ + public boolean hasEarlyConstraint() { + return hasEarlyConstraint; + } + + /** + * User can specify a late constraint of 0L, which is valid, so we keep track of whether the + * function was called at all. + * @hide + */ + public boolean hasLateConstraint() { + return hasLateConstraint; + } + + private JobInfo(Parcel in) { + jobId = in.readInt(); + extras = in.readPersistableBundle(); + service = in.readParcelable(null); + requireCharging = in.readInt() == 1; + requireDeviceIdle = in.readInt() == 1; + networkType = in.readInt(); + minLatencyMillis = in.readLong(); + maxExecutionDelayMillis = in.readLong(); + isPeriodic = in.readInt() == 1; + isPersisted = in.readInt() == 1; + intervalMillis = in.readLong(); + initialBackoffMillis = in.readLong(); + backoffPolicy = in.readInt(); + hasEarlyConstraint = in.readInt() == 1; + hasLateConstraint = in.readInt() == 1; + } + + private JobInfo(JobInfo.Builder b) { + jobId = b.mJobId; + extras = b.mExtras; + service = b.mJobService; + requireCharging = b.mRequiresCharging; + requireDeviceIdle = b.mRequiresDeviceIdle; + networkType = b.mNetworkType; + minLatencyMillis = b.mMinLatencyMillis; + maxExecutionDelayMillis = b.mMaxExecutionDelayMillis; + isPeriodic = b.mIsPeriodic; + isPersisted = b.mIsPersisted; + intervalMillis = b.mIntervalMillis; + initialBackoffMillis = b.mInitialBackoffMillis; + backoffPolicy = b.mBackoffPolicy; + hasEarlyConstraint = b.mHasEarlyConstraint; + hasLateConstraint = b.mHasLateConstraint; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(jobId); + out.writePersistableBundle(extras); + out.writeParcelable(service, flags); + out.writeInt(requireCharging ? 1 : 0); + out.writeInt(requireDeviceIdle ? 1 : 0); + out.writeInt(networkType); + out.writeLong(minLatencyMillis); + out.writeLong(maxExecutionDelayMillis); + out.writeInt(isPeriodic ? 1 : 0); + out.writeInt(isPersisted ? 1 : 0); + out.writeLong(intervalMillis); + out.writeLong(initialBackoffMillis); + out.writeInt(backoffPolicy); + out.writeInt(hasEarlyConstraint ? 1 : 0); + out.writeInt(hasLateConstraint ? 1 : 0); + } + + public static final Creator<JobInfo> CREATOR = new Creator<JobInfo>() { + @Override + public JobInfo createFromParcel(Parcel in) { + return new JobInfo(in); + } + + @Override + public JobInfo[] newArray(int size) { + return new JobInfo[size]; + } + }; + + @Override + public String toString() { + return "(job:" + jobId + "/" + service.flattenToShortString() + ")"; + } + + /** Builder class for constructing {@link JobInfo} objects. */ + public static final class Builder { + private int mJobId; + private PersistableBundle mExtras = PersistableBundle.EMPTY; + private ComponentName mJobService; + // Requirements. + private boolean mRequiresCharging; + private boolean mRequiresDeviceIdle; + private int mNetworkType; + private boolean mIsPersisted; + // One-off parameters. + private long mMinLatencyMillis; + private long mMaxExecutionDelayMillis; + // Periodic parameters. + private boolean mIsPeriodic; + private boolean mHasEarlyConstraint; + private boolean mHasLateConstraint; + private long mIntervalMillis; + // Back-off parameters. + private long mInitialBackoffMillis = DEFAULT_INITIAL_BACKOFF_MILLIS; + private int mBackoffPolicy = DEFAULT_BACKOFF_POLICY; + /** Easy way to track whether the client has tried to set a back-off policy. */ + private boolean mBackoffPolicySet = false; + + /** + * @param jobId Application-provided id for this job. Subsequent calls to cancel, or + * jobs created with the same jobId, will update the pre-existing job with + * the same id. + * @param jobService The endpoint that you implement that will receive the callback from the + * JobScheduler. + */ + public Builder(int jobId, ComponentName jobService) { + mJobService = jobService; + mJobId = jobId; + } + + /** + * Set optional extras. This is persisted, so we only allow primitive types. + * @param extras Bundle containing extras you want the scheduler to hold on to for you. + */ + public Builder setExtras(PersistableBundle extras) { + mExtras = extras; + return this; + } + + /** + * Set some description of the kind of network type your job needs to have. + * Not calling this function means the network is not necessary, as the default is + * {@link #NETWORK_TYPE_NONE}. + * Bear in mind that calling this function defines network as a strict requirement for your + * job. If the network requested is not available your job will never run. See + * {@link #setOverrideDeadline(long)} to change this behaviour. + */ + public Builder setRequiredNetworkType(int networkType) { + mNetworkType = networkType; + return this; + } + + /** + * Specify that to run this job, the device needs to be plugged in. This defaults to + * false. + * @param requiresCharging Whether or not the device is plugged in. + */ + public Builder setRequiresCharging(boolean requiresCharging) { + mRequiresCharging = requiresCharging; + return this; + } + + /** + * Specify that to run, the job needs the device to be in idle mode. This defaults to + * false. + * <p>Idle mode is a loose definition provided by the system, which means that the device + * is not in use, and has not been in use for some time. As such, it is a good time to + * perform resource heavy jobs. Bear in mind that battery usage will still be attributed + * to your application, and surfaced to the user in battery stats.</p> + * @param requiresDeviceIdle Whether or not the device need be within an idle maintenance + * window. + */ + public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) { + mRequiresDeviceIdle = requiresDeviceIdle; + return this; + } + + /** + * Specify that this job should recur with the provided interval, not more than once per + * period. You have no control over when within this interval this job will be executed, + * only the guarantee that it will be executed at most once within this interval. + * Setting this function on the builder with {@link #setMinimumLatency(long)} or + * {@link #setOverrideDeadline(long)} will result in an error. + * @param intervalMillis Millisecond interval for which this job will repeat. + */ + public Builder setPeriodic(long intervalMillis) { + mIsPeriodic = true; + mIntervalMillis = intervalMillis; + mHasEarlyConstraint = mHasLateConstraint = true; + return this; + } + + /** + * Specify that this job should be delayed by the provided amount of time. + * Because it doesn't make sense setting this property on a periodic job, doing so will + * throw an {@link java.lang.IllegalArgumentException} when + * {@link android.app.job.JobInfo.Builder#build()} is called. + * @param minLatencyMillis Milliseconds before which this job will not be considered for + * execution. + */ + public Builder setMinimumLatency(long minLatencyMillis) { + mMinLatencyMillis = minLatencyMillis; + mHasEarlyConstraint = true; + return this; + } + + /** + * Set deadline which is the maximum scheduling latency. The job will be run by this + * deadline even if other requirements are not met. Because it doesn't make sense setting + * this property on a periodic job, doing so will throw an + * {@link java.lang.IllegalArgumentException} when + * {@link android.app.job.JobInfo.Builder#build()} is called. + */ + public Builder setOverrideDeadline(long maxExecutionDelayMillis) { + mMaxExecutionDelayMillis = maxExecutionDelayMillis; + mHasLateConstraint = true; + return this; + } + + /** + * Set up the back-off/retry policy. + * This defaults to some respectable values: {30 seconds, Exponential}. We cap back-off at + * 5hrs. + * Note that trying to set a backoff criteria for a job with + * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build(). + * This is because back-off typically does not make sense for these types of jobs. See + * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} + * for more description of the return value for the case of a job executing while in idle + * mode. + * @param initialBackoffMillis Millisecond time interval to wait initially when job has + * failed. + * @param backoffPolicy is one of {@link #BACKOFF_POLICY_LINEAR} or + * {@link #BACKOFF_POLICY_EXPONENTIAL} + */ + public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) { + mBackoffPolicySet = true; + mInitialBackoffMillis = initialBackoffMillis; + mBackoffPolicy = backoffPolicy; + return this; + } + + /** + * Set whether or not to persist this job across device reboots. This will only have an + * effect if your application holds the permission + * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED}. Otherwise an exception will + * be thrown. + * @param isPersisted True to indicate that the job will be written to disk and loaded at + * boot. + */ + public Builder setPersisted(boolean isPersisted) { + mIsPersisted = isPersisted; + return this; + } + + /** + * @return The job object to hand to the JobScheduler. This object is immutable. + */ + public JobInfo build() { + // Allow jobs with no constraints - What am I, a database? + if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging && + !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_NONE) { + throw new IllegalArgumentException("You're trying to build a job with no " + + "constraints, this is not allowed."); + } + mExtras = new PersistableBundle(mExtras); // Make our own copy. + // Check that a deadline was not set on a periodic job. + if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) { + throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " + + "periodic job."); + } + if (mIsPeriodic && (mMinLatencyMillis != 0L)) { + throw new IllegalArgumentException("Can't call setMinimumLatency() on a " + + "periodic job"); + } + if (mBackoffPolicySet && mRequiresDeviceIdle) { + throw new IllegalArgumentException("An idle mode job will not respect any" + + " back-off policy, so calling setBackoffCriteria with" + + " setRequiresDeviceIdle is an error."); + } + return new JobInfo(this); + } + } + +}
diff --git a/core/java/android/app/job/JobParameters.aidl b/core/java/android/app/job/JobParameters.aidl new file mode 100644 index 0000000..e7551b9 --- /dev/null +++ b/core/java/android/app/job/JobParameters.aidl
@@ -0,0 +1,19 @@ +/** + * Copyright 2014, 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.job; + +parcelable JobParameters;
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java new file mode 100644 index 0000000..62734f2 --- /dev/null +++ b/core/java/android/app/job/JobParameters.java
@@ -0,0 +1,108 @@ +/* + * Copyright (C) 2014 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.job; + +import android.app.job.IJobCallback; +import android.app.job.IJobCallback.Stub; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; + +/** + * Contains the parameters used to configure/identify your job. You do not create this object + * yourself, instead it is handed in to your application by the System. + */ +public class JobParameters implements Parcelable { + + private final int jobId; + private final PersistableBundle extras; + private final IBinder callback; + private final boolean overrideDeadlineExpired; + + /** @hide */ + public JobParameters(IBinder callback, int jobId, PersistableBundle extras, + boolean overrideDeadlineExpired) { + this.jobId = jobId; + this.extras = extras; + this.callback = callback; + this.overrideDeadlineExpired = overrideDeadlineExpired; + } + + /** + * @return The unique id of this job, specified at creation time. + */ + public int getJobId() { + return jobId; + } + + /** + * @return The extras you passed in when constructing this job with + * {@link android.app.job.JobInfo.Builder#setExtras(android.os.PersistableBundle)}. This will + * never be null. If you did not set any extras this will be an empty bundle. + */ + public PersistableBundle getExtras() { + return extras; + } + + /** + * For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this + * provides an easy way to tell whether the job is being executed due to the deadline + * expiring. Note: If the job is running because its deadline expired, it implies that its + * constraints will not be met. + */ + public boolean isOverrideDeadlineExpired() { + return overrideDeadlineExpired; + } + + /** @hide */ + public IJobCallback getCallback() { + return IJobCallback.Stub.asInterface(callback); + } + + private JobParameters(Parcel in) { + jobId = in.readInt(); + extras = in.readPersistableBundle(); + callback = in.readStrongBinder(); + overrideDeadlineExpired = in.readInt() == 1; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(jobId); + dest.writePersistableBundle(extras); + dest.writeStrongBinder(callback); + dest.writeInt(overrideDeadlineExpired ? 1 : 0); + } + + public static final Creator<JobParameters> CREATOR = new Creator<JobParameters>() { + @Override + public JobParameters createFromParcel(Parcel in) { + return new JobParameters(in); + } + + @Override + public JobParameters[] newArray(int size) { + return new JobParameters[size]; + } + }; +}
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java new file mode 100644 index 0000000..89efeb2 --- /dev/null +++ b/core/java/android/app/job/JobScheduler.java
@@ -0,0 +1,88 @@ +/* + * Copyright (C) 2014 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.job; + +import java.util.List; + +import android.content.Context; + +/** + * This is an API for scheduling various types of jobs against the framework that will be executed + * in your application's own process. + * <p> + * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run + * and how to construct them. You will construct these JobInfo objects and pass them to the + * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the + * system will execute this job on your application's {@link android.app.job.JobService}. + * You identify which JobService is meant to execute the logic for your job when you create the + * JobInfo with + * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}. + * </p> + * <p> + * The framework will be intelligent about when you receive your callbacks, and attempt to batch + * and defer them as much as possible. Typically if you don't specify a deadline on your job, it + * can be run at any moment depending on the current state of the JobScheduler's internal queue, + * however it might be deferred as long as until the next time the device is connected to a power + * source. + * </p> + * <p>You do not + * instantiate this class directly; instead, retrieve it through + * {@link android.content.Context#getSystemService + * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}. + */ +public abstract class JobScheduler { + /** + * Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur + * if the run-time for your job is too short, or perhaps the system can't resolve the + * requisite {@link JobService} in your package. + */ + public static final int RESULT_FAILURE = 0; + /** + * Returned from {@link #schedule(JobInfo)} if this application has made too many requests for + * work over too short a time. + */ + // TODO: Determine if this is necessary. + public static final int RESULT_SUCCESS = 1; + + /** + * @param job The job you wish scheduled. See + * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs + * you can schedule. + * @return If >0, this int returns the jobId of the successfully scheduled job. + * Otherwise you have to compare the return value to the error codes defined in this class. + */ + public abstract int schedule(JobInfo job); + + /** + * Cancel a job that is pending in the JobScheduler. + * @param jobId unique identifier for this job. Obtain this value from the jobs returned by + * {@link #getAllPendingJobs()}. + * @return + */ + public abstract void cancel(int jobId); + + /** + * Cancel all jobs that have been registered with the JobScheduler by this package. + */ + public abstract void cancelAll(); + + /** + * @return a list of all the jobs registered by this package that have not yet been executed. + */ + public abstract List<JobInfo> getAllPendingJobs(); + +}
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java new file mode 100644 index 0000000..940a530 --- /dev/null +++ b/core/java/android/app/job/JobService.java
@@ -0,0 +1,257 @@ +/* + * Copyright (C) 2014 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.job; + +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; + +/** + * <p>Entry point for the callback from the {@link android.app.job.JobScheduler}.</p> + * <p>This is the base class that handles asynchronous requests that were previously scheduled. You + * are responsible for overriding {@link JobService#onStartJob(JobParameters)}, which is where + * you will implement your job logic.</p> + * <p>This service executes each incoming job on a {@link android.os.Handler} running on your + * application's main thread. This means that you <b>must</b> offload your execution logic to + * another thread/handler/{@link android.os.AsyncTask} of your choosing. Not doing so will result + * in blocking any future callbacks from the JobManager - specifically + * {@link #onStopJob(android.app.job.JobParameters)}, which is meant to inform you that the + * scheduling requirements are no longer being met.</p> + */ +public abstract class JobService extends Service { + private static final String TAG = "JobService"; + + /** + * Job services must be protected with this permission: + * + * <pre class="prettyprint"> + * <service android:name="MyJobService" + * android:permission="android.permission.BIND_JOB_SERVICE" > + * ... + * </service> + * </pre> + * + * <p>If a job service is declared in the manifest but not protected with this + * permission, that service will be ignored by the OS. + */ + public static final String PERMISSION_BIND = + "android.permission.BIND_JOB_SERVICE"; + + /** + * Identifier for a message that will result in a call to + * {@link #onStartJob(android.app.job.JobParameters)}. + */ + private final int MSG_EXECUTE_JOB = 0; + /** + * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}. + */ + private final int MSG_STOP_JOB = 1; + /** + * Message that the client has completed execution of this job. + */ + private final int MSG_JOB_FINISHED = 2; + + /** Lock object for {@link #mHandler}. */ + private final Object mHandlerLock = new Object(); + + /** + * Handler we post jobs to. Responsible for calling into the client logic, and handling the + * callback to the system. + */ + @GuardedBy("mHandlerLock") + JobHandler mHandler; + + /** Binder for this service. */ + IJobService mBinder = new IJobService.Stub() { + @Override + public void startJob(JobParameters jobParams) { + ensureHandler(); + Message m = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams); + m.sendToTarget(); + } + @Override + public void stopJob(JobParameters jobParams) { + ensureHandler(); + Message m = Message.obtain(mHandler, MSG_STOP_JOB, jobParams); + m.sendToTarget(); + } + }; + + /** @hide */ + void ensureHandler() { + synchronized (mHandlerLock) { + if (mHandler == null) { + mHandler = new JobHandler(getMainLooper()); + } + } + } + + /** + * Runs on application's main thread - callbacks are meant to offboard work to some other + * (app-specified) mechanism. + * @hide + */ + class JobHandler extends Handler { + JobHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + final JobParameters params = (JobParameters) msg.obj; + switch (msg.what) { + case MSG_EXECUTE_JOB: + try { + boolean workOngoing = JobService.this.onStartJob(params); + ackStartMessage(params, workOngoing); + } catch (Exception e) { + Log.e(TAG, "Error while executing job: " + params.getJobId()); + throw new RuntimeException(e); + } + break; + case MSG_STOP_JOB: + try { + boolean ret = JobService.this.onStopJob(params); + ackStopMessage(params, ret); + } catch (Exception e) { + Log.e(TAG, "Application unable to handle onStopJob.", e); + throw new RuntimeException(e); + } + break; + case MSG_JOB_FINISHED: + final boolean needsReschedule = (msg.arg2 == 1); + IJobCallback callback = params.getCallback(); + if (callback != null) { + try { + callback.jobFinished(params.getJobId(), needsReschedule); + } catch (RemoteException e) { + Log.e(TAG, "Error reporting job finish to system: binder has gone" + + "away."); + } + } else { + Log.e(TAG, "finishJob() called for a nonexistent job id."); + } + break; + default: + Log.e(TAG, "Unrecognised message received."); + break; + } + } + + private void ackStartMessage(JobParameters params, boolean workOngoing) { + final IJobCallback callback = params.getCallback(); + final int jobId = params.getJobId(); + if (callback != null) { + try { + callback.acknowledgeStartMessage(jobId, workOngoing); + } catch(RemoteException e) { + Log.e(TAG, "System unreachable for starting job."); + } + } else { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Attempting to ack a job that has already been processed."); + } + } + } + + private void ackStopMessage(JobParameters params, boolean reschedule) { + final IJobCallback callback = params.getCallback(); + final int jobId = params.getJobId(); + if (callback != null) { + try { + callback.acknowledgeStopMessage(jobId, reschedule); + } catch(RemoteException e) { + Log.e(TAG, "System unreachable for stopping job."); + } + } else { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Attempting to ack a job that has already been processed."); + } + } + } + } + + /** @hide */ + public final IBinder onBind(Intent intent) { + return mBinder.asBinder(); + } + + /** + * Override this method with the callback logic for your job. Any such logic needs to be + * performed on a separate thread, as this function is executed on your application's main + * thread. + * + * @param params Parameters specifying info about this job, including the extras bundle you + * optionally provided at job-creation time. + * @return True if your service needs to process the work (on a separate thread). False if + * there's no more work to be done for this job. + */ + public abstract boolean onStartJob(JobParameters params); + + /** + * This method is called if the system has determined that you must stop execution of your job + * even before you've had a chance to call {@link #jobFinished(JobParameters, boolean)}. + * + * <p>This will happen if the requirements specified at schedule time are no longer met. For + * example you may have requested WiFi with + * {@link android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}, yet while your + * job was executing the user toggled WiFi. Another example is if you had specified + * {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its + * idle maintenance window. You are solely responsible for the behaviour of your application + * upon receipt of this message; your app will likely start to misbehave if you ignore it. One + * immediate repercussion is that the system will cease holding a wakelock for you.</p> + * + * @param params Parameters specifying info about this job. + * @return True to indicate to the JobManager whether you'd like to reschedule this job based + * on the retry criteria provided at job creation-time. False to drop the job. Regardless of + * the value returned, your job must stop executing. + */ + public abstract boolean onStopJob(JobParameters params); + + /** + * Callback to inform the JobManager you've finished executing. This can be called from any + * thread, as it will ultimately be run on your application's main thread. When the system + * receives this message it will release the wakelock being held. + * <p> + * You can specify post-execution behaviour to the scheduler here with + * <code>needsReschedule </code>. This will apply a back-off timer to your job based on + * the default, or what was set with + * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}. The original + * requirements are always honoured even for a backed-off job. Note that a job running in + * idle mode will not be backed-off. Instead what will happen is the job will be re-added + * to the queue and re-executed within a future idle maintenance window. + * </p> + * + * @param params Parameters specifying system-provided info about this job, this was given to + * your application in {@link #onStartJob(JobParameters)}. + * @param needsReschedule True if this job should be rescheduled according to the back-off + * criteria specified at schedule-time. False otherwise. + */ + public final void jobFinished(JobParameters params, boolean needsReschedule) { + ensureHandler(); + Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params); + m.arg2 = needsReschedule ? 1 : 0; + m.sendToTarget(); + } +} \ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustListener.aidl b/core/java/android/app/trust/ITrustListener.aidl new file mode 100644 index 0000000..d80f58c --- /dev/null +++ b/core/java/android/app/trust/ITrustListener.aidl
@@ -0,0 +1,27 @@ +/* +** +** Copyright 2014, 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.trust; + +/** + * Private API to be notified about trust changes. + * + * {@hide} + */ +oneway interface ITrustListener { + void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser); + void onTrustManagedChanged(boolean managed, int userId); +} \ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl new file mode 100644 index 0000000..6fbf87d --- /dev/null +++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -0,0 +1,32 @@ +/* +** +** Copyright 2014, 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.trust; + +import android.app.trust.ITrustListener; + +/** + * System private API to comunicate with trust service. + * + * {@hide} + */ +interface ITrustManager { + void reportUnlockAttempt(boolean successful, int userId); + void reportEnabledTrustAgentsChanged(int userId); + void reportRequireCredentialEntry(int userId); + void registerTrustListener(in ITrustListener trustListener); + void unregisterTrustListener(in ITrustListener trustListener); +}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java new file mode 100644 index 0000000..3d262b1 --- /dev/null +++ b/core/java/android/app/trust/TrustManager.java
@@ -0,0 +1,176 @@ +/* + * Copyright (C) 2014 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.trust; + +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.Log; + +/** + * See {@link com.android.server.trust.TrustManagerService} + * @hide + */ +public class TrustManager { + + private static final int MSG_TRUST_CHANGED = 1; + private static final int MSG_TRUST_MANAGED_CHANGED = 2; + + private static final String TAG = "TrustManager"; + private static final String DATA_INITIATED_BY_USER = "initiatedByUser"; + + private final ITrustManager mService; + private final ArrayMap<TrustListener, ITrustListener> mTrustListeners; + + public TrustManager(IBinder b) { + mService = ITrustManager.Stub.asInterface(b); + mTrustListeners = new ArrayMap<TrustListener, ITrustListener>(); + } + + /** + * Reports that user {@param userId} has tried to unlock the device. + * + * @param successful if true, the unlock attempt was successful. + * + * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. + */ + public void reportUnlockAttempt(boolean successful, int userId) { + try { + mService.reportUnlockAttempt(successful, userId); + } catch (RemoteException e) { + onError(e); + } + } + + /** + * Reports that the list of enabled trust agents changed for user {@param userId}. + * + * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. + */ + public void reportEnabledTrustAgentsChanged(int userId) { + try { + mService.reportEnabledTrustAgentsChanged(userId); + } catch (RemoteException e) { + onError(e); + } + } + + /** + * Reports that trust is disabled until credentials have been entered for user {@param userId}. + * + * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. + * + * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL} + */ + public void reportRequireCredentialEntry(int userId) { + try { + mService.reportRequireCredentialEntry(userId); + } catch (RemoteException e) { + onError(e); + } + } + + /** + * Registers a listener for trust events. + * + * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission. + */ + public void registerTrustListener(final TrustListener trustListener) { + try { + ITrustListener.Stub iTrustListener = new ITrustListener.Stub() { + @Override + public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) { + Message m = mHandler.obtainMessage(MSG_TRUST_CHANGED, (enabled ? 1 : 0), userId, + trustListener); + if (initiatedByUser) { + m.getData().putBoolean(DATA_INITIATED_BY_USER, initiatedByUser); + } + m.sendToTarget(); + } + + @Override + public void onTrustManagedChanged(boolean managed, int userId) { + mHandler.obtainMessage(MSG_TRUST_MANAGED_CHANGED, (managed ? 1 : 0), userId, + trustListener).sendToTarget(); + } + }; + mService.registerTrustListener(iTrustListener); + mTrustListeners.put(trustListener, iTrustListener); + } catch (RemoteException e) { + onError(e); + } + } + + /** + * Unregisters a listener for trust events. + * + * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission. + */ + public void unregisterTrustListener(final TrustListener trustListener) { + ITrustListener iTrustListener = mTrustListeners.remove(trustListener); + if (iTrustListener != null) { + try { + mService.unregisterTrustListener(iTrustListener); + } catch (RemoteException e) { + onError(e); + } + } + } + + private void onError(Exception e) { + Log.e(TAG, "Error while calling TrustManagerService", e); + } + + private final Handler mHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch(msg.what) { + case MSG_TRUST_CHANGED: + boolean initiatedByUser = msg.peekData() != null && + msg.peekData().getBoolean(DATA_INITIATED_BY_USER); + ((TrustListener)msg.obj).onTrustChanged( + msg.arg1 != 0, msg.arg2, initiatedByUser); + + break; + case MSG_TRUST_MANAGED_CHANGED: + ((TrustListener)msg.obj).onTrustManagedChanged(msg.arg1 != 0, msg.arg2); + } + } + }; + + public interface TrustListener { + + /** + * Reports that the trust state has changed. + * @param enabled if true, the system believes the environment to be trusted. + * @param userId the user, for which the trust changed. + * @param initiatedByUser indicates that the user has explicitly initiated an action that + * proves the user is about to use the device. + */ + void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser); + + /** + * Reports that whether trust is managed has changed + * @param enabled if true, at least one trust agent is managing trust. + * @param userId the user, for which the state changed. + */ + void onTrustManagedChanged(boolean enabled, int userId); + } +}
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java new file mode 100644 index 0000000..080216c --- /dev/null +++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -0,0 +1,161 @@ +/** + * Copyright (C) 2014 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.content.res.Configuration; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Represents the usage statistics of a device {@link android.content.res.Configuration} for a + * specific time range. + */ +public final class ConfigurationStats implements Parcelable { + + /** + * {@hide} + */ + public Configuration mConfiguration; + + /** + * {@hide} + */ + public long mBeginTimeStamp; + + /** + * {@hide} + */ + public long mEndTimeStamp; + + /** + * {@hide} + */ + public long mLastTimeActive; + + /** + * {@hide} + */ + public long mTotalTimeActive; + + /** + * {@hide} + */ + public int mActivationCount; + + /** + * {@hide} + */ + public ConfigurationStats() { + } + + public ConfigurationStats(ConfigurationStats stats) { + mConfiguration = stats.mConfiguration; + mBeginTimeStamp = stats.mBeginTimeStamp; + mEndTimeStamp = stats.mEndTimeStamp; + mLastTimeActive = stats.mLastTimeActive; + mTotalTimeActive = stats.mTotalTimeActive; + mActivationCount = stats.mActivationCount; + } + + public Configuration getConfiguration() { + return mConfiguration; + } + + /** + * Get the beginning of the time range this {@link ConfigurationStats} represents, + * measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getFirstTimeStamp() { + return mBeginTimeStamp; + } + + /** + * Get the end of the time range this {@link ConfigurationStats} represents, + * measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getLastTimeStamp() { + return mEndTimeStamp; + } + + /** + * Get the last time this configuration was active, measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getLastTimeActive() { + return mLastTimeActive; + } + + /** + * Get the total time this configuration was active, measured in milliseconds. + */ + public long getTotalTimeActive() { + return mTotalTimeActive; + } + + /** + * Get the number of times this configuration was active. + */ + public int getActivationCount() { + return mActivationCount; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + if (mConfiguration != null) { + dest.writeInt(1); + mConfiguration.writeToParcel(dest, flags); + } else { + dest.writeInt(0); + } + + dest.writeLong(mBeginTimeStamp); + dest.writeLong(mEndTimeStamp); + dest.writeLong(mLastTimeActive); + dest.writeLong(mTotalTimeActive); + dest.writeInt(mActivationCount); + } + + public static final Creator<ConfigurationStats> CREATOR = new Creator<ConfigurationStats>() { + @Override + public ConfigurationStats createFromParcel(Parcel source) { + ConfigurationStats stats = new ConfigurationStats(); + if (source.readInt() != 0) { + stats.mConfiguration = Configuration.CREATOR.createFromParcel(source); + } + stats.mBeginTimeStamp = source.readLong(); + stats.mEndTimeStamp = source.readLong(); + stats.mLastTimeActive = source.readLong(); + stats.mTotalTimeActive = source.readLong(); + stats.mActivationCount = source.readInt(); + return stats; + } + + @Override + public ConfigurationStats[] newArray(int size) { + return new ConfigurationStats[size]; + } + }; +}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl new file mode 100644 index 0000000..4ed1489 --- /dev/null +++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014, 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.app.usage.UsageEvents; +import android.content.pm.ParceledListSlice; + +/** + * System private API for talking with the UsageStatsManagerService. + * + * {@hide} + */ +interface IUsageStatsManager { + ParceledListSlice queryUsageStats(int bucketType, long beginTime, long endTime, + String callingPackage); + ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime, + String callingPackage); + UsageEvents queryEvents(long beginTime, long endTime, String callingPackage); +}
diff --git a/core/java/android/app/usage/PackageUsageStats.aidl b/core/java/android/app/usage/PackageUsageStats.aidl new file mode 100644 index 0000000..5293098 --- /dev/null +++ b/core/java/android/app/usage/PackageUsageStats.aidl
@@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014, 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; + +parcelable PackageUsageStats;
diff --git a/core/java/android/app/usage/TimeSparseArray.java b/core/java/android/app/usage/TimeSparseArray.java new file mode 100644 index 0000000..7974fa7 --- /dev/null +++ b/core/java/android/app/usage/TimeSparseArray.java
@@ -0,0 +1,91 @@ +/** + * Copyright (C) 2014 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.util.LongSparseArray; + +/** + * An array that indexes by a long timestamp, representing milliseconds since the epoch. + * + * {@hide} + */ +public class TimeSparseArray<E> extends LongSparseArray<E> { + public TimeSparseArray() { + super(); + } + + public TimeSparseArray(int initialCapacity) { + super(initialCapacity); + } + + /** + * Finds the index of the first element whose timestamp is greater or equal to + * the given time. + * + * @param time The timestamp for which to search the array. + * @return The index of the matched element, or -1 if no such match exists. + */ + public int closestIndexOnOrAfter(long time) { + // This is essentially a binary search, except that if no match is found + // the closest index is returned. + final int size = size(); + int lo = 0; + int hi = size - 1; + int mid = -1; + long key = -1; + while (lo <= hi) { + mid = lo + ((hi - lo) / 2); + key = keyAt(mid); + + if (time > key) { + lo = mid + 1; + } else if (time < key) { + hi = mid - 1; + } else { + return mid; + } + } + + if (time < key) { + return mid; + } else if (time > key && lo < size) { + return lo; + } else { + return -1; + } + } + + /** + * Finds the index of the first element whose timestamp is less than or equal to + * the given time. + * + * @param time The timestamp for which to search the array. + * @return The index of the matched element, or -1 if no such match exists. + */ + public int closestIndexOnOrBefore(long time) { + final int index = closestIndexOnOrAfter(time); + if (index < 0) { + // Everything is larger, so we use the last element, or -1 if the list is empty. + return size() - 1; + } + + if (keyAt(index) == time) { + return index; + } + return index - 1; + } +}
diff --git a/core/java/android/app/usage/UsageEvents.aidl b/core/java/android/app/usage/UsageEvents.aidl new file mode 100644 index 0000000..f1bceba --- /dev/null +++ b/core/java/android/app/usage/UsageEvents.aidl
@@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014, 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; + +parcelable UsageEvents;
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java new file mode 100644 index 0000000..1a947ec --- /dev/null +++ b/core/java/android/app/usage/UsageEvents.java
@@ -0,0 +1,379 @@ +/** + * Copyright (C) 2014 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.content.ComponentName; +import android.content.res.Configuration; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Arrays; +import java.util.List; + +/** + * A result returned from {@link android.app.usage.UsageStatsManager#queryEvents(long, long)} + * from which to read {@link android.app.usage.UsageEvents.Event} objects. + */ +public final class UsageEvents implements Parcelable { + + /** + * An event representing a state change for a component. + */ + public static final class Event { + + /** + * No event type. + */ + public static final int NONE = 0; + + /** + * An event type denoting that a component moved to the foreground. + */ + public static final int MOVE_TO_FOREGROUND = 1; + + /** + * An event type denoting that a component moved to the background. + */ + public static final int MOVE_TO_BACKGROUND = 2; + + /** + * An event type denoting that a component was in the foreground when the stats + * rolled-over. This is effectively treated as a {@link #MOVE_TO_BACKGROUND}. + * {@hide} + */ + public static final int END_OF_DAY = 3; + + /** + * An event type denoting that a component was in the foreground the previous day. + * This is effectively treated as a {@link #MOVE_TO_FOREGROUND}. + * {@hide} + */ + public static final int CONTINUE_PREVIOUS_DAY = 4; + + /** + * An event type denoting that the device configuration has changed. + */ + public static final int CONFIGURATION_CHANGE = 5; + + /** + * {@hide} + */ + public String mPackage; + + /** + * {@hide} + */ + public String mClass; + + /** + * {@hide} + */ + public long mTimeStamp; + + /** + * {@hide} + */ + public int mEventType; + + /** + * Only present for {@link #CONFIGURATION_CHANGE} event types. + * {@hide} + */ + public Configuration mConfiguration; + + /** + * TODO(adamlesinski): Removed before release. + * {@hide} + */ + public ComponentName getComponent() { + return new ComponentName(mPackage, mClass); + } + + /** + * The package name of the source of this event. + */ + public String getPackageName() { + return mPackage; + } + + /** + * The class name of the source of this event. This may be null for + * certain events. + */ + public String getClassName() { + return mClass; + } + + /** + * The time at which this event occurred, measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getTimeStamp() { + return mTimeStamp; + } + + /** + * The event type. + * + * See {@link #MOVE_TO_BACKGROUND} + * See {@link #MOVE_TO_FOREGROUND} + */ + public int getEventType() { + return mEventType; + } + + /** + * Returns a {@link Configuration} for this event if the event is of type + * {@link #CONFIGURATION_CHANGE}, otherwise it returns null. + */ + public Configuration getConfiguration() { + return mConfiguration; + } + } + + // Only used when creating the resulting events. Not used for reading/unparceling. + private List<Event> mEventsToWrite = null; + + // Only used for reading/unparceling events. + private Parcel mParcel = null; + private final int mEventCount; + + private int mIndex = 0; + + /* + * In order to save space, since ComponentNames will be duplicated everywhere, + * we use a map and index into it. + */ + private String[] mStringPool; + + /** + * Construct the iterator from a parcel. + * {@hide} + */ + public UsageEvents(Parcel in) { + mEventCount = in.readInt(); + mIndex = in.readInt(); + if (mEventCount > 0) { + mStringPool = in.createStringArray(); + + final int listByteLength = in.readInt(); + final int positionInParcel = in.readInt(); + mParcel = Parcel.obtain(); + mParcel.setDataPosition(0); + mParcel.appendFrom(in, in.dataPosition(), listByteLength); + mParcel.setDataSize(mParcel.dataPosition()); + mParcel.setDataPosition(positionInParcel); + } + } + + /** + * Create an empty iterator. + * {@hide} + */ + UsageEvents() { + mEventCount = 0; + } + + /** + * Construct the iterator in preparation for writing it to a parcel. + * {@hide} + */ + public UsageEvents(List<Event> events, String[] stringPool) { + mStringPool = stringPool; + mEventCount = events.size(); + mEventsToWrite = events; + } + + /** + * Returns whether or not there are more events to read using + * {@link #getNextEvent(android.app.usage.UsageEvents.Event)}. + * + * @return true if there are more events, false otherwise. + */ + public boolean hasNextEvent() { + return mIndex < mEventCount; + } + + /** + * Retrieve the next {@link android.app.usage.UsageEvents.Event} from the collection and put the + * resulting data into {@code eventOut}. + * + * @param eventOut The {@link android.app.usage.UsageEvents.Event} object that will receive the + * next event data. + * @return true if an event was available, false if there are no more events. + */ + public boolean getNextEvent(Event eventOut) { + if (mIndex >= mEventCount) { + return false; + } + + readEventFromParcel(mParcel, eventOut); + + mIndex++; + if (mIndex >= mEventCount) { + mParcel.recycle(); + mParcel = null; + } + return true; + } + + /** + * Resets the collection so that it can be iterated over from the beginning. + */ + public void resetToStart() { + mIndex = 0; + if (mParcel != null) { + mParcel.setDataPosition(0); + } + } + + private int findStringIndex(String str) { + final int index = Arrays.binarySearch(mStringPool, str); + if (index < 0) { + throw new IllegalStateException("String '" + str + "' is not in the string pool"); + } + return index; + } + + /** + * Writes a single event to the parcel. Modify this when updating {@link Event}. + */ + private void writeEventToParcel(Event event, Parcel p, int flags) { + final int packageIndex; + if (event.mPackage != null) { + packageIndex = findStringIndex(event.mPackage); + } else { + packageIndex = -1; + } + + final int classIndex; + if (event.mClass != null) { + classIndex = findStringIndex(event.mClass); + } else { + classIndex = -1; + } + p.writeInt(packageIndex); + p.writeInt(classIndex); + p.writeInt(event.mEventType); + p.writeLong(event.mTimeStamp); + + if (event.mEventType == Event.CONFIGURATION_CHANGE) { + event.mConfiguration.writeToParcel(p, flags); + } + } + + /** + * Reads a single event from the parcel. Modify this when updating {@link Event}. + */ + private void readEventFromParcel(Parcel p, Event eventOut) { + final int packageIndex = p.readInt(); + if (packageIndex >= 0) { + eventOut.mPackage = mStringPool[packageIndex]; + } else { + eventOut.mPackage = null; + } + + final int classIndex = p.readInt(); + if (classIndex >= 0) { + eventOut.mClass = mStringPool[classIndex]; + } else { + eventOut.mClass = null; + } + eventOut.mEventType = p.readInt(); + eventOut.mTimeStamp = p.readLong(); + + // Extract the configuration for configuration change events. + if (eventOut.mEventType == Event.CONFIGURATION_CHANGE) { + eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p); + } else { + eventOut.mConfiguration = null; + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mEventCount); + dest.writeInt(mIndex); + if (mEventCount > 0) { + dest.writeStringArray(mStringPool); + + if (mEventsToWrite != null) { + // Write out the events + Parcel p = Parcel.obtain(); + try { + p.setDataPosition(0); + for (int i = 0; i < mEventCount; i++) { + final Event event = mEventsToWrite.get(i); + writeEventToParcel(event, p, flags); + } + + final int listByteLength = p.dataPosition(); + + // Write the total length of the data. + dest.writeInt(listByteLength); + + // Write our current position into the data. + dest.writeInt(0); + + // Write the data. + dest.appendFrom(p, 0, listByteLength); + } finally { + p.recycle(); + } + + } else if (mParcel != null) { + // Write the total length of the data. + dest.writeInt(mParcel.dataSize()); + + // Write out current position into the data. + dest.writeInt(mParcel.dataPosition()); + + // Write the data. + dest.appendFrom(mParcel, 0, mParcel.dataSize()); + } else { + throw new IllegalStateException( + "Either mParcel or mEventsToWrite must not be null"); + } + } + } + + public static final Creator<UsageEvents> CREATOR = new Creator<UsageEvents>() { + @Override + public UsageEvents createFromParcel(Parcel source) { + return new UsageEvents(source); + } + + @Override + public UsageEvents[] newArray(int size) { + return new UsageEvents[size]; + } + }; + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (mParcel != null) { + mParcel.recycle(); + mParcel = null; + } + } +}
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java new file mode 100644 index 0000000..abfc435 --- /dev/null +++ b/core/java/android/app/usage/UsageStats.java
@@ -0,0 +1,177 @@ +/** + * Copyright (C) 2014 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.os.Parcel; +import android.os.Parcelable; + +/** + * Contains usage statistics for an app package for a specific + * time range. + */ +public final class UsageStats implements Parcelable { + + /** + * {@hide} + */ + public String mPackageName; + + /** + * {@hide} + */ + public long mBeginTimeStamp; + + /** + * {@hide} + */ + public long mEndTimeStamp; + + /** + * {@hide} + */ + public long mLastTimeUsed; + + /** + * {@hide} + */ + public long mTotalTimeInForeground; + + /** + * {@hide} + */ + public int mLaunchCount; + + /** + * {@hide} + */ + public int mLastEvent; + + /** + * {@hide} + */ + public UsageStats() { + } + + public UsageStats(UsageStats stats) { + mPackageName = stats.mPackageName; + mBeginTimeStamp = stats.mBeginTimeStamp; + mEndTimeStamp = stats.mEndTimeStamp; + mLastTimeUsed = stats.mLastTimeUsed; + mTotalTimeInForeground = stats.mTotalTimeInForeground; + mLaunchCount = stats.mLaunchCount; + mLastEvent = stats.mLastEvent; + } + + public String getPackageName() { + return mPackageName; + } + + /** + * Get the beginning of the time range this {@link android.app.usage.UsageStats} represents, + * measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getFirstTimeStamp() { + return mBeginTimeStamp; + } + + /** + * Get the end of the time range this {@link android.app.usage.UsageStats} represents, + * measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getLastTimeStamp() { + return mEndTimeStamp; + } + + /** + * Get the last time this package was used, measured in milliseconds since the epoch. + * <p/> + * See {@link System#currentTimeMillis()}. + */ + public long getLastTimeUsed() { + return mLastTimeUsed; + } + + /** + * Get the total time this package spent in the foreground, measured in milliseconds. + */ + public long getTotalTimeInForeground() { + return mTotalTimeInForeground; + } + + /** + * Add the statistics from the right {@link UsageStats} to the left. The package name for + * both {@link UsageStats} objects must be the same. + * @param right The {@link UsageStats} object to merge into this one. + * @throws java.lang.IllegalArgumentException if the package names of the two + * {@link UsageStats} objects are different. + */ + public void add(UsageStats right) { + if (!mPackageName.equals(right.mPackageName)) { + throw new IllegalArgumentException("Can't merge UsageStats for package '" + + mPackageName + "' with UsageStats for package '" + right.mPackageName + "'."); + } + + if (right.mEndTimeStamp > mEndTimeStamp) { + mLastEvent = right.mLastEvent; + mEndTimeStamp = right.mEndTimeStamp; + mLastTimeUsed = right.mLastTimeUsed; + } + mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp); + mTotalTimeInForeground += right.mTotalTimeInForeground; + mLaunchCount += right.mLaunchCount; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mPackageName); + dest.writeLong(mBeginTimeStamp); + dest.writeLong(mEndTimeStamp); + dest.writeLong(mLastTimeUsed); + dest.writeLong(mTotalTimeInForeground); + dest.writeInt(mLaunchCount); + dest.writeInt(mLastEvent); + } + + public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() { + @Override + public UsageStats createFromParcel(Parcel in) { + UsageStats stats = new UsageStats(); + stats.mPackageName = in.readString(); + stats.mBeginTimeStamp = in.readLong(); + stats.mEndTimeStamp = in.readLong(); + stats.mLastTimeUsed = in.readLong(); + stats.mTotalTimeInForeground = in.readLong(); + stats.mLaunchCount = in.readInt(); + stats.mLastEvent = in.readInt(); + return stats; + } + + @Override + public UsageStats[] newArray(int size) { + return new UsageStats[size]; + } + }; +}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java new file mode 100644 index 0000000..bc6099a --- /dev/null +++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -0,0 +1,220 @@ +/** + * Copyright (C) 2014 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.content.Context; +import android.content.pm.ParceledListSlice; +import android.os.RemoteException; +import android.util.ArrayMap; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Provides access to device usage history and statistics. Usage data is aggregated into + * time intervals: days, weeks, months, and years. + * <p /> + * When requesting usage data since a particular time, the request might look something like this: + * <pre> + * PAST REQUEST_TIME TODAY FUTURE + * ————————————————————————————||———————————————————————————¦-----------------------| + * YEAR || ¦ | + * ————————————————————————————||———————————————————————————¦-----------------------| + * MONTH | || MONTH ¦ | + * ——————————————————|—————————||———————————————————————————¦-----------------------| + * | WEEK | WEEK|| | WEEK | WE¦EK | WEEK | + * ————————————————————————————||———————————————————|———————¦-----------------------| + * || |DAY|DAY|DAY|DAY¦DAY|DAY|DAY|DAY|DAY|DAY| + * ————————————————————————————||———————————————————————————¦-----------------------| + * </pre> + * A request for data in the middle of a time interval will include that interval. + * <p/> + * <b>NOTE:</b> This API requires the permission android.permission.PACKAGE_USAGE_STATS, which + * is a system-level permission and will not be granted to third-party apps. However, declaring + * the permission implies intention to use the API and the user of the device can grant permission + * through the Settings application. + */ +public final class UsageStatsManager { + + /** + * An interval type that spans a day. See {@link #queryUsageStats(int, long, long)}. + */ + public static final int INTERVAL_DAILY = 0; + + /** + * An interval type that spans a week. See {@link #queryUsageStats(int, long, long)}. + */ + public static final int INTERVAL_WEEKLY = 1; + + /** + * An interval type that spans a month. See {@link #queryUsageStats(int, long, long)}. + */ + public static final int INTERVAL_MONTHLY = 2; + + /** + * An interval type that spans a year. See {@link #queryUsageStats(int, long, long)}. + */ + public static final int INTERVAL_YEARLY = 3; + + /** + * An interval type that will use the best fit interval for the given time range. + * See {@link #queryUsageStats(int, long, long)}. + */ + public static final int INTERVAL_BEST = 4; + + /** + * The number of available intervals. Does not include {@link #INTERVAL_BEST}, since it + * is a pseudo interval (it actually selects a real interval). + * {@hide} + */ + public static final int INTERVAL_COUNT = 4; + + private static final UsageEvents sEmptyResults = new UsageEvents(); + + private final Context mContext; + private final IUsageStatsManager mService; + + /** + * {@hide} + */ + public UsageStatsManager(Context context, IUsageStatsManager service) { + mContext = context; + mService = service; + } + + /** + * Gets application usage stats for the given time range, aggregated by the specified interval. + * <p>The returned list will contain a {@link UsageStats} object for each package that + * has data for an interval that is a subset of the time range given. To illustrate:</p> + * <pre> + * intervalType = INTERVAL_YEARLY + * beginTime = 2013 + * endTime = 2015 (exclusive) + * + * Results: + * 2013 - com.example.alpha + * 2013 - com.example.beta + * 2014 - com.example.alpha + * 2014 - com.example.beta + * 2014 - com.example.charlie + * </pre> + * + * @param intervalType The time interval by which the stats are aggregated. + * @param beginTime The inclusive beginning of the range of stats to include in the results. + * @param endTime The exclusive end of the range of stats to include in the results. + * @return A list of {@link UsageStats} or null if none are available. + * + * @see #INTERVAL_DAILY + * @see #INTERVAL_WEEKLY + * @see #INTERVAL_MONTHLY + * @see #INTERVAL_YEARLY + * @see #INTERVAL_BEST + */ + public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) { + try { + @SuppressWarnings("unchecked") + ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime, + endTime, mContext.getOpPackageName()); + if (slice != null) { + return slice.getList(); + } + } catch (RemoteException e) { + // fallthrough and return null. + } + return Collections.emptyList(); + } + + /** + * Gets the hardware configurations the device was in for the given time range, aggregated by + * the specified interval. The results are ordered as in + * {@link #queryUsageStats(int, long, long)}. + * + * @param intervalType The time interval by which the stats are aggregated. + * @param beginTime The inclusive beginning of the range of stats to include in the results. + * @param endTime The exclusive end of the range of stats to include in the results. + * @return A list of {@link ConfigurationStats} or null if none are available. + */ + public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime, + long endTime) { + try { + @SuppressWarnings("unchecked") + ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats( + intervalType, beginTime, endTime, mContext.getOpPackageName()); + if (slice != null) { + return slice.getList(); + } + } catch (RemoteException e) { + // fallthrough and return the empty list. + } + return Collections.emptyList(); + } + + /** + * Query for events in the given time range. Events are only kept by the system for a few + * days. + * <p /> + * <b>NOTE:</b> The last few minutes of the event log will be truncated to prevent abuse + * by applications. + * + * @param beginTime The inclusive beginning of the range of events to include in the results. + * @param endTime The exclusive end of the range of events to include in the results. + * @return A {@link UsageEvents}. + */ + public UsageEvents queryEvents(long beginTime, long endTime) { + try { + UsageEvents iter = mService.queryEvents(beginTime, endTime, + mContext.getOpPackageName()); + if (iter != null) { + return iter; + } + } catch (RemoteException e) { + // fallthrough and return null + } + return sEmptyResults; + } + + /** + * A convenience method that queries for all stats in the given range (using the best interval + * for that range), merges the resulting data, and keys it by package name. + * See {@link #queryUsageStats(int, long, long)}. + * + * @param beginTime The inclusive beginning of the range of stats to include in the results. + * @param endTime The exclusive end of the range of stats to include in the results. + * @return A {@link java.util.Map} keyed by package name, or null if no stats are + * available. + */ + public Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime) { + List<UsageStats> stats = queryUsageStats(INTERVAL_BEST, beginTime, endTime); + if (stats.isEmpty()) { + return Collections.emptyMap(); + } + + ArrayMap<String, UsageStats> aggregatedStats = new ArrayMap<>(); + final int statCount = stats.size(); + for (int i = 0; i < statCount; i++) { + UsageStats newStat = stats.get(i); + UsageStats existingStat = aggregatedStats.get(newStat.getPackageName()); + if (existingStat == null) { + aggregatedStats.put(newStat.mPackageName, newStat); + } else { + existingStat.add(newStat); + } + } + return aggregatedStats; + } +}
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java new file mode 100644 index 0000000..083a48a --- /dev/null +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -0,0 +1,50 @@ +/** + * Copyright (C) 2014 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.content.ComponentName; +import android.content.res.Configuration; + +/** + * UsageStatsManager local system service interface. + * + * {@hide} Only for use within the system server. + */ +public abstract class UsageStatsManagerInternal { + + /** + * Reports an event to the UsageStatsManager. + * + * @param component The component for which this event occurred. + * @param userId The user id to which the component belongs to. + * @param eventType The event that occurred. Valid values can be found at + * {@link UsageEvents} + */ + public abstract void reportEvent(ComponentName component, int userId, int eventType); + + /** + * Reports a configuration change to the UsageStatsManager. + * + * @param config The new device configuration. + */ + public abstract void reportConfigurationChange(Configuration config, int userId); + + /** + * Prepares the UsageStatsService for shutdown. + */ + public abstract void prepareShutdown(); +}
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index f104d71..24c6793 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -19,9 +19,14 @@ import java.util.ArrayList; import java.util.HashMap; -import android.app.ActivityThread; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Context; +import android.content.IntentSender; import android.os.Binder; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -29,9 +34,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.util.DisplayMetrics; -import android.util.Log; import android.util.TypedValue; import android.widget.RemoteViews; import android.widget.RemoteViews.OnClickHandler; @@ -55,7 +58,6 @@ private DisplayMetrics mDisplayMetrics; Context mContext; - String mPackageName; Handler mHandler; int mHostId; Callbacks mCallbacks = new Callbacks(); @@ -63,32 +65,30 @@ private OnClickHandler mOnClickHandler; class Callbacks extends IAppWidgetHost.Stub { - public void updateAppWidget(int appWidgetId, RemoteViews views, int userId) { + public void updateAppWidget(int appWidgetId, RemoteViews views) { if (isLocalBinder() && views != null) { views = views.clone(); - views.setUser(new UserHandle(userId)); } - Message msg = mHandler.obtainMessage(HANDLE_UPDATE, appWidgetId, userId, views); + Message msg = mHandler.obtainMessage(HANDLE_UPDATE, appWidgetId, 0, views); msg.sendToTarget(); } - public void providerChanged(int appWidgetId, AppWidgetProviderInfo info, int userId) { + public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) { if (isLocalBinder() && info != null) { info = info.clone(); } Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED, - appWidgetId, userId, info); + appWidgetId, 0, info); msg.sendToTarget(); } - public void providersChanged(int userId) { - Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED, userId, 0); - msg.sendToTarget(); + public void providersChanged() { + mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED).sendToTarget(); } - public void viewDataChanged(int appWidgetId, int viewId, int userId) { + public void viewDataChanged(int appWidgetId, int viewId) { Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED, - appWidgetId, viewId, userId); + appWidgetId, viewId); msg.sendToTarget(); } } @@ -101,7 +101,7 @@ public void handleMessage(Message msg) { switch (msg.what) { case HANDLE_UPDATE: { - updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj, msg.arg2); + updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj); break; } case HANDLE_PROVIDER_CHANGED: { @@ -113,7 +113,7 @@ break; } case HANDLE_VIEW_DATA_CHANGED: { - viewDataChanged(msg.arg1, msg.arg2, (Integer) msg.obj); + viewDataChanged(msg.arg1, msg.arg2); break; } } @@ -153,25 +153,17 @@ public void startListening() { int[] updatedIds; ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>(); - - final int userId = mContext.getUserId(); try { - if (mPackageName == null) { - mPackageName = mContext.getPackageName(); - } - updatedIds = sService.startListening( - mCallbacks, mPackageName, mHostId, updatedViews, userId); + updatedIds = sService.startListening(mCallbacks, mContext.getOpPackageName(), mHostId, + updatedViews); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } final int N = updatedIds.length; - for (int i=0; i<N; i++) { - if (updatedViews.get(i) != null) { - updatedViews.get(i).setUser(new UserHandle(userId)); - } - updateAppWidgetView(updatedIds[i], updatedViews.get(i), userId); + for (int i = 0; i < N; i++) { + updateAppWidgetView(updatedIds[i], updatedViews.get(i)); } } @@ -181,7 +173,7 @@ */ public void stopListening() { try { - sService.stopListening(mHostId, mContext.getUserId()); + sService.stopListening(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -199,10 +191,7 @@ */ public int allocateAppWidgetId() { try { - if (mPackageName == null) { - mPackageName = mContext.getPackageName(); - } - return sService.allocateAppWidgetId(mPackageName, mHostId, mContext.getUserId()); + return sService.allocateAppWidgetId(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -210,18 +199,37 @@ } /** - * Get a appWidgetId for a host in the given package. + * Starts an app widget provider configure activity for result on behalf of the caller. + * Use this method if the provider is in another profile as you are not allowed to start + * an activity in another profile. You can optionally provide a request code that is + * returned in {@link Activity#onActivityResult(int, int, android.content.Intent)} and + * an options bundle to be passed to the started activity. + * <p> + * Note that the provided app widget has to be bound for this method to work. + * </p> * - * @return a appWidgetId - * @hide + * @param activity The activity from which to start the configure one. + * @param appWidgetId The bound app widget whose provider's config activity to start. + * @param requestCode Optional request code retuned with the result. + * @param intentFlags Optional intent flags. + * + * @throws android.content.ActivityNotFoundException If the activity is not found. + * + * @see AppWidgetProviderInfo#getProfile() */ - public static int allocateAppWidgetIdForPackage(int hostId, int userId, String packageName) { - checkCallerIsSystem(); + public final void startAppWidgetConfigureActivityForResult(@NonNull Activity activity, + int appWidgetId, int intentFlags, int requestCode, @Nullable Bundle options) { try { - if (sService == null) { - bindService(); + IntentSender intentSender = sService.createAppWidgetConfigIntentSender( + mContext.getOpPackageName(), appWidgetId, intentFlags); + if (intentSender != null) { + activity.startIntentSenderForResult(intentSender, requestCode, null, 0, 0, 0, + options); + } else { + throw new ActivityNotFoundException(); } - return sService.allocateAppWidgetId(packageName, hostId, userId); + } catch (IntentSender.SendIntentException e) { + throw new ActivityNotFoundException(); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } @@ -237,20 +245,12 @@ if (sService == null) { bindService(); } - return sService.getAppWidgetIdsForHost(mHostId, mContext.getUserId()); + return sService.getAppWidgetIdsForHost(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } } - private static void checkCallerIsSystem() { - int uid = Process.myUid(); - if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) { - return; - } - throw new SecurityException("Disallowed call for uid " + uid); - } - private boolean isLocalBinder() { return Process.myPid() == Binder.getCallingPid(); } @@ -262,7 +262,7 @@ synchronized (mViews) { mViews.remove(appWidgetId); try { - sService.deleteAppWidgetId(appWidgetId, mContext.getUserId()); + sService.deleteAppWidgetId(mContext.getOpPackageName(), appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -271,22 +271,6 @@ } /** - * Stop listening to changes for this AppWidget. - * @hide - */ - public static void deleteAppWidgetIdForSystem(int appWidgetId, int userId) { - checkCallerIsSystem(); - try { - if (sService == null) { - bindService(); - } - sService.deleteAppWidgetId(appWidgetId, userId); - } catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } - - /** * Remove all records about this host from the AppWidget manager. * <ul> * <li>Call this when initializing your database, as it might be because of a data wipe.</li> @@ -296,7 +280,7 @@ */ public void deleteHost() { try { - sService.deleteHost(mHostId, mContext.getUserId()); + sService.deleteHost(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -312,16 +296,8 @@ * </ul> */ public static void deleteAllHosts() { - deleteAllHosts(UserHandle.myUserId()); - } - - /** - * Private method containing a userId - * @hide - */ - public static void deleteAllHosts(int userId) { try { - sService.deleteAllHosts(userId); + sService.deleteAllHosts(); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -334,9 +310,7 @@ */ public final AppWidgetHostView createView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { - final int userId = mContext.getUserId(); AppWidgetHostView view = onCreateView(mContext, appWidgetId, appWidget); - view.setUserId(userId); view.setOnClickHandler(mOnClickHandler); view.setAppWidget(appWidgetId, appWidget); synchronized (mViews) { @@ -344,10 +318,7 @@ } RemoteViews views; try { - views = sService.getAppWidgetViews(appWidgetId, userId); - if (views != null) { - views.setUser(new UserHandle(mContext.getUserId())); - } + views = sService.getAppWidgetViews(mContext.getOpPackageName(), appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } @@ -399,7 +370,7 @@ // Does nothing } - void updateAppWidgetView(int appWidgetId, RemoteViews views, int userId) { + void updateAppWidgetView(int appWidgetId, RemoteViews views) { AppWidgetHostView v; synchronized (mViews) { v = mViews.get(appWidgetId); @@ -409,7 +380,7 @@ } } - void viewDataChanged(int appWidgetId, int viewId, int userId) { + void viewDataChanged(int appWidgetId, int viewId) { AppWidgetHostView v; synchronized (mViews) { v = mViews.get(appWidgetId);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 700bba8..1ff476e 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -87,7 +87,6 @@ Bitmap mOld; Paint mOldPaint = new Paint(); private OnClickHandler mOnClickHandler; - private UserHandle mUser; /** * Create a host view. Uses default fade animations. @@ -115,17 +114,11 @@ public AppWidgetHostView(Context context, int animationIn, int animationOut) { super(context); mContext = context; - mUser = Process.myUserHandle(); // We want to segregate the view ids within AppWidgets to prevent // problems when those ids collide with view ids in the AppWidgetHost. setIsRootNamespace(true); } - /** @hide */ - public void setUserId(int userId) { - mUser = new UserHandle(userId); - } - /** * Pass the given handler to RemoteViews when updating this widget. Unless this * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)} @@ -380,7 +373,7 @@ } else { // Prepare a local reference to the remote Context so we're ready to // inflate any requested LayoutParams. - mRemoteContext = getRemoteContext(remoteViews); + mRemoteContext = getRemoteContext(); int layoutId = remoteViews.getLayoutId(); // If our stale view has been prepared to match active, and the new @@ -466,17 +459,14 @@ * Build a {@link Context} cloned into another package name, usually for the * purposes of reading remote resources. */ - private Context getRemoteContext(RemoteViews views) { - // Bail if missing package name - final String packageName = views.getPackage(); - if (packageName == null) return mContext; - + private Context getRemoteContext() { try { // Return if cloned successfully, otherwise default - return mContext.createPackageContextAsUser(packageName, Context.CONTEXT_RESTRICTED, - mUser); + return mContext.createApplicationContext( + mInfo.providerInfo.applicationInfo, + Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { - Log.e(TAG, "Package name " + packageName + " not found"); + Log.e(TAG, "Package name " + mInfo.providerInfo.packageName + " not found"); return mContext; } } @@ -548,8 +538,7 @@ try { if (mInfo != null) { - Context theirContext = mContext.createPackageContextAsUser( - mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED, mUser); + Context theirContext = getRemoteContext(); mRemoteContext = theirContext; LayoutInflater inflater = (LayoutInflater) theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -572,8 +561,6 @@ } else { Log.w(TAG, "can't inflate defaultView because mInfo is missing"); } - } catch (PackageManager.NameNotFoundException e) { - exception = e; } catch (RuntimeException e) { exception = e; }
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index d1c7bec..00248cc 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -16,14 +16,14 @@ package android.appwidget; -import android.app.ActivityManagerNative; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -31,9 +31,8 @@ import com.android.internal.appwidget.IAppWidgetService; -import java.lang.ref.WeakReference; +import java.util.Collections; import java.util.List; -import java.util.WeakHashMap; /** * Updates AppWidget state; gets information about installed AppWidget providers and other @@ -46,7 +45,6 @@ * </div> */ public class AppWidgetManager { - static final String TAG = "AppWidgetManager"; /** * Activity action to launch from your {@link AppWidgetHost} activity when you want to @@ -73,9 +71,9 @@ * <p> * When you receive the result from the AppWidget pick activity, if the resultCode is * {@link android.app.Activity#RESULT_OK}, an AppWidget has been selected. You should then - * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its configuration - * activity. If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete - * the appWidgetId. + * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its + * configuration activity. If {@link android.app.Activity#RESULT_CANCELED} is returned, you + * should delete the appWidgetId. * * @see #ACTION_APPWIDGET_CONFIGURE */ @@ -104,6 +102,12 @@ * <td>The BroadcastReceiver that will be the AppWidget provider for this AppWidget. * </td> * </tr> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_PROVIDER_PROFILE}</td> + * <td>An optional handle to a user profile under which runs the provider + * for this AppWidget. + * </td> + * </tr> * </table> * * <p> @@ -120,8 +124,7 @@ * {@link android.app.Activity#RESULT_OK}, the AppWidget has been bound. You should then * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its * configuration activity. If {@link android.app.Activity#RESULT_CANCELED} is returned, you - * should delete - * the appWidgetId. + * should delete the appWidgetId. * * @see #ACTION_APPWIDGET_CONFIGURE * @@ -131,7 +134,8 @@ /** * Sent when it is time to configure your AppWidget while it is being added to a host. * This action is not sent as a broadcast to the AppWidget provider, but as a startActivity - * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo meta-data}. + * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo + * meta-data}. * * <p> * The intent will contain the following extras: @@ -146,7 +150,8 @@ * {@link android.app.Activity#setResult Activity.setResult()}, the AppWidget will be added, * and you will receive an {@link #ACTION_APPWIDGET_UPDATE} broadcast for this AppWidget. * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add - * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED} broadcast. + * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED} + * broadcast. */ public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE"; @@ -182,13 +187,16 @@ * A bundle extra that hints to the AppWidgetProvider the category of host that owns this * this widget. Can have the value {@link * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link - * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. + * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link + * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}. */ public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory"; /** * An intent extra which points to a bundle of extra information for a particular widget id. - * In particular this bundle can contain EXTRA_APPWIDGET_WIDTH and EXTRA_APPWIDGET_HEIGHT. + * In particular this bundle can contain {@link #OPTION_APPWIDGET_MIN_WIDTH}, + * {@link #OPTION_APPWIDGET_MIN_HEIGHT}, {@link #OPTION_APPWIDGET_MAX_WIDTH}, + * {@link #OPTION_APPWIDGET_MAX_HEIGHT}. */ public static final String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions"; @@ -203,11 +211,19 @@ /** * An intent extra that contains the component name of a AppWidget provider. * <p> - * The value will be an ComponentName. + * The value will be an {@link android.content.ComponentName}. */ public static final String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider"; /** + * An intent extra that contains the user handle of the profile under + * which an AppWidget provider is registered. + * <p> + * The value will be a {@link android.os.UserHandle}. + */ + public static final String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile"; + + /** * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are * installed. (This is how the launcher shows the search widget). @@ -215,6 +231,12 @@ public static final String EXTRA_CUSTOM_INFO = "customInfo"; /** + * An intent extra attached to the {@link #ACTION_APPWIDGET_HOST_RESTORED} broadcast, + * indicating the integer ID of the host whose widgets have just been restored. + */ + public static final String EXTRA_HOST_ID = "hostId"; + + /** * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are * installed. It will be added to the extras object on the {@link android.content.Intent} @@ -289,12 +311,12 @@ public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED"; /** - * Sent when an instance of an AppWidget is removed from the last host. + * Sent when the last AppWidget of this provider is removed from the last host. * * <p class="note">This is a protected intent that can only be sent * by the system. * - * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context) + * @see AppWidgetProvider#onEnabled AppWidgetProvider.onDisabled(Context context) */ public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED"; @@ -311,52 +333,122 @@ public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED"; /** + * Sent to an {@link AppWidgetProvider} after AppWidget state related to that provider has + * been restored from backup. The intent contains information about how to translate AppWidget + * ids from the restored data to their new equivalents. + * + * <p>The intent will contain the following extras: + * + * <table> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_OLD_IDS}</td> + * <td>The set of appWidgetIds represented in a restored backup that have been successfully + * incorporated into the current environment. This may be all of the AppWidgets known + * to this application, or just a subset. Each entry in this array of appWidgetIds has + * a corresponding entry in the {@link #EXTRA_APPWIDGET_IDS} extra.</td> + * </tr> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_IDS}</td> + * <td>The set of appWidgetIds now valid for this application. The app should look at + * its restored widget configuration and translate each appWidgetId in the + * {@link #EXTRA_APPWIDGET_OLD_IDS} array to its new value found at the corresponding + * index within this array.</td> + * </tr> + * </table> + * + * <p class="note">This is a protected intent that can only be sent + * by the system. + * + * @see #ACTION_APPWIDGET_HOST_RESTORED + */ + public static final String ACTION_APPWIDGET_RESTORED + = "android.appwidget.action.APPWIDGET_RESTORED"; + + /** + * Sent to widget hosts after AppWidget state related to the host has been restored from + * backup. The intent contains information about how to translate AppWidget ids from the + * restored data to their new equivalents. If an application maintains multiple separate + * widget host instances, it will receive this broadcast separately for each one. + * + * <p>The intent will contain the following extras: + * + * <table> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_OLD_IDS}</td> + * <td>The set of appWidgetIds represented in a restored backup that have been successfully + * incorporated into the current environment. This may be all of the AppWidgets known + * to this application, or just a subset. Each entry in this array of appWidgetIds has + * a corresponding entry in the {@link #EXTRA_APPWIDGET_IDS} extra.</td> + * </tr> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_IDS}</td> + * <td>The set of appWidgetIds now valid for this application. The app should look at + * its restored widget configuration and translate each appWidgetId in the + * {@link #EXTRA_APPWIDGET_OLD_IDS} array to its new value found at the corresponding + * index within this array.</td> + * </tr> + * <tr> + * <td>{@link #EXTRA_HOST_ID}</td> + * <td>The integer ID of the widget host instance whose state has just been restored.</td> + * </tr> + * </table> + * + * <p class="note">This is a protected intent that can only be sent + * by the system. + * + * @see #ACTION_APPWIDGET_RESTORED + */ + public static final String ACTION_APPWIDGET_HOST_RESTORED + = "android.appwidget.action.APPWIDGET_HOST_RESTORED"; + + /** + * An intent extra that contains multiple appWidgetIds. These are id values as + * they were provided to the application during a recent restore from backup. It is + * attached to the {@link #ACTION_APPWIDGET_RESTORED} broadcast intent. + * + * <p> + * The value will be an int array that can be retrieved like this: + * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS} + */ + public static final String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds"; + + /** * Field for the manifest meta-data tag. * * @see AppWidgetProviderInfo */ public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider"; - static WeakHashMap<Context, WeakReference<AppWidgetManager>> sManagerCache = - new WeakHashMap<Context, WeakReference<AppWidgetManager>>(); - static IAppWidgetService sService; + private final String mPackageName; - Context mContext; + private final IAppWidgetService mService; - private DisplayMetrics mDisplayMetrics; + private final DisplayMetrics mDisplayMetrics; /** * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context * Context} object. */ public static AppWidgetManager getInstance(Context context) { - synchronized (sManagerCache) { - if (sService == null) { - IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); - sService = IAppWidgetService.Stub.asInterface(b); - } - - WeakReference<AppWidgetManager> ref = sManagerCache.get(context); - AppWidgetManager result = null; - if (ref != null) { - result = ref.get(); - } - if (result == null) { - result = new AppWidgetManager(context); - sManagerCache.put(context, new WeakReference<AppWidgetManager>(result)); - } - return result; - } + return (AppWidgetManager) context.getSystemService(Context.APPWIDGET_SERVICE); } - private AppWidgetManager(Context context) { - mContext = context; + /** + * Creates a new instance. + * + * @param context The current context in which to operate. + * @param service The backing system service. + * @hide + */ + public AppWidgetManager(Context context, IAppWidgetService service) { + mPackageName = context.getOpPackageName(); + mService = service; mDisplayMetrics = context.getResources().getDisplayMetrics(); } /** * Set the RemoteViews to use for the specified appWidgetIds. - * + * <p> * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should * contain a complete representation of the widget. For performing partial widget updates, see * {@link #partiallyUpdateAppWidget(int[], RemoteViews)}. @@ -370,12 +462,15 @@ * The total Bitmap memory used by the RemoteViews object cannot exceed that required to * fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes. * - * @param appWidgetIds The AppWidget instances for which to set the RemoteViews. - * @param views The RemoteViews object to show. + * @param appWidgetIds The AppWidget instances for which to set the RemoteViews. + * @param views The RemoteViews object to show. */ public void updateAppWidget(int[] appWidgetIds, RemoteViews views) { + if (mService == null) { + return; + } try { - sService.updateAppWidgetIds(appWidgetIds, views, mContext.getUserId()); + mService.updateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -384,18 +479,21 @@ /** * Update the extras for a given widget instance. - * + * <p> * The extras can be used to embed additional information about this widget to be accessed * by the associated widget's AppWidgetProvider. * * @see #getAppWidgetOptions(int) * - * @param appWidgetId The AppWidget instances for which to set the RemoteViews. - * @param options The options to associate with this widget + * @param appWidgetId The AppWidget instances for which to set the RemoteViews. + * @param options The options to associate with this widget */ public void updateAppWidgetOptions(int appWidgetId, Bundle options) { + if (mService == null) { + return; + } try { - sService.updateAppWidgetOptions(appWidgetId, options, mContext.getUserId()); + mService.updateAppWidgetOptions(mPackageName, appWidgetId, options); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -404,18 +502,21 @@ /** * Get the extras associated with a given widget instance. - * + * <p> * The extras can be used to embed additional information about this widget to be accessed * by the associated widget's AppWidgetProvider. * * @see #updateAppWidgetOptions(int, Bundle) * - * @param appWidgetId The AppWidget instances for which to set the RemoteViews. - * @return The options associated with the given widget instance. + * @param appWidgetId The AppWidget instances for which to set the RemoteViews. + * @return The options associated with the given widget instance. */ public Bundle getAppWidgetOptions(int appWidgetId) { + if (mService == null) { + return Bundle.EMPTY; + } try { - return sService.getAppWidgetOptions(appWidgetId, mContext.getUserId()); + return mService.getAppWidgetOptions(mPackageName, appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -424,7 +525,7 @@ /** * Set the RemoteViews to use for the specified appWidgetId. - * + * <p> * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should * contain a complete representation of the widget. For performing partial widget updates, see * {@link #partiallyUpdateAppWidget(int, RemoteViews)}. @@ -442,12 +543,15 @@ * @param views The RemoteViews object to show. */ public void updateAppWidget(int appWidgetId, RemoteViews views) { + if (mService == null) { + return; + } updateAppWidget(new int[] { appWidgetId }, views); } /** * Perform an incremental update or command on the widget(s) specified by appWidgetIds. - * + * <p> * This update differs from {@link #updateAppWidget(int[], RemoteViews)} in that the * RemoteViews object which is passed is understood to be an incomplete representation of the * widget, and hence does not replace the cached representation of the widget. As of API @@ -470,8 +574,11 @@ * @param views The RemoteViews object containing the incremental update / command. */ public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) { + if (mService == null) { + return; + } try { - sService.partiallyUpdateAppWidgetIds(appWidgetIds, views, mContext.getUserId()); + mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } @@ -479,7 +586,7 @@ /** * Perform an incremental update or command on the widget specified by appWidgetId. - * + * <p> * This update differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews * object which is passed is understood to be an incomplete representation of the widget, and * hence is not cached by the AppWidgetService. Note that because these updates are not cached, @@ -502,6 +609,9 @@ * @param views The RemoteViews object containing the incremental update / command. */ public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) { + if (mService == null) { + return; + } partiallyUpdateAppWidget(new int[] { appWidgetId }, views); } @@ -519,8 +629,11 @@ * @param views The RemoteViews object to show. */ public void updateAppWidget(ComponentName provider, RemoteViews views) { + if (mService == null) { + return; + } try { - sService.updateAppWidgetProvider(provider, views, mContext.getUserId()); + mService.updateAppWidgetProvider(provider, views); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -535,8 +648,11 @@ * @param viewId The collection view id. */ public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) { + if (mService == null) { + return; + } try { - sService.notifyAppWidgetViewDataChanged(appWidgetIds, viewId, mContext.getUserId()); + mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -551,37 +667,100 @@ * @param viewId The collection view id. */ public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) { + if (mService == null) { + return; + } notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId); } /** + * Gets the AppWidget providers for the given user profile. User profile can only + * be the current user or a profile of the current user. For example, the current + * user may have a corporate profile. In this case the parent user profile has a + * child profile, the corporate one. + * + * @param profile The profile for which to get providers. Passing null is equivaled + * to passing only the current user handle. + * @return The intalled providers. + * + * @see android.os.Process#myUserHandle() + * @see android.os.UserManager#getUserProfiles() + */ + public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(@Nullable UserHandle profile) { + if (mService == null) { + return Collections.emptyList(); + } + return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN, + profile); + } + + /** * Return a list of the AppWidget providers that are currently installed. */ public List<AppWidgetProviderInfo> getInstalledProviders() { - return getInstalledProviders(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN); + if (mService == null) { + return Collections.emptyList(); + } + return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN, + null); } /** - * Return a list of the AppWidget providers that are currently installed. + * Gets the AppWidget providers for the current user. * * @param categoryFilter Will only return providers which register as any of the specified * specified categories. See {@link AppWidgetProviderInfo#widgetCategory}. + * @return The intalled providers. + * + * @see android.os.Process#myUserHandle() + * @see android.os.UserManager#getUserProfiles() + * * @hide */ public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) { + if (mService == null) { + return Collections.emptyList(); + } + return getInstalledProvidersForProfile(categoryFilter, null); + } + + /** + * Gets the AppWidget providers for the given user profile. User profile can only + * be the current user or a profile of the current user. For example, the current + * user may have a corporate profile. In this case the parent user profile has a + * child profile, the corporate one. + * + * @param categoryFilter Will only return providers which register as any of the specified + * specified categories. See {@link AppWidgetProviderInfo#widgetCategory}. + * @param profile A profile of the current user which to be queried. The user + * is itself also a profile. If null, the providers only for the current user + * are returned. + * @return The intalled providers. + * + * @see android.os.Process#myUserHandle() + * @see android.os.UserManager#getUserProfiles() + * + * @hide + */ + public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter, + UserHandle profile) { + if (mService == null) { + return Collections.emptyList(); + } + + if (profile == null) { + profile = Process.myUserHandle(); + } + try { - List<AppWidgetProviderInfo> providers = sService.getInstalledProviders(categoryFilter, - mContext.getUserId()); + List<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile( + categoryFilter, profile.getIdentifier()); + if (providers == null) { + return Collections.emptyList(); + } for (AppWidgetProviderInfo info : providers) { // Converting complex to dp. - info.minWidth = - TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics); - info.minHeight = - TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics); - info.minResizeWidth = - TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics); - info.minResizeHeight = - TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics); + convertSizesToPixels(info); } return providers; } @@ -597,19 +776,14 @@ * you don't have access to that appWidgetId, null is returned. */ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) { + if (mService == null) { + return null; + } try { - AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId, - mContext.getUserId()); + AppWidgetProviderInfo info = mService.getAppWidgetInfo(mPackageName, appWidgetId); if (info != null) { // Converting complex to dp. - info.minWidth = - TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics); - info.minHeight = - TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics); - info.minResizeWidth = - TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics); - info.minResizeHeight = - TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics); + convertSizesToPixels(info); } return info; } @@ -631,12 +805,10 @@ * @hide */ public void bindAppWidgetId(int appWidgetId, ComponentName provider) { - try { - sService.bindAppWidgetId(appWidgetId, provider, null, mContext.getUserId()); + if (mService == null) { + return; } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } + bindAppWidgetId(appWidgetId, provider, null); } /** @@ -655,12 +827,10 @@ * @hide */ public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) { - try { - sService.bindAppWidgetId(appWidgetId, provider, options, mContext.getUserId()); + if (mService == null) { + return; } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } + bindAppWidgetIdIfAllowed(appWidgetId, Process.myUserHandle(), provider, options); } /** @@ -671,22 +841,16 @@ * method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to * bind * - * @param appWidgetId The AppWidget instance for which to set the RemoteViews. + * @param appWidgetId The AppWidget id under which to bind the provider. * @param provider The {@link android.content.BroadcastReceiver} that will be the AppWidget * provider for this AppWidget. * @return true if this component has permission to bind the AppWidget */ public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider) { - if (mContext == null) { + if (mService == null) { return false; } - try { - return sService.bindAppWidgetIdIfAllowed( - mContext.getPackageName(), appWidgetId, provider, null, mContext.getUserId()); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } + return bindAppWidgetIdIfAllowed(appWidgetId, UserHandle.myUserId(), provider, null); } /** @@ -697,7 +861,7 @@ * method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to * bind * - * @param appWidgetId The AppWidget instance for which to set the RemoteViews. + * @param appWidgetId The AppWidget id under which to bind the provider. * @param provider The {@link android.content.BroadcastReceiver} that will be the AppWidget * provider for this AppWidget. * @param options Bundle containing options for the AppWidget. See also @@ -707,12 +871,52 @@ */ public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider, Bundle options) { - if (mContext == null) { + if (mService == null) { + return false; + } + return bindAppWidgetIdIfAllowed(appWidgetId, UserHandle.myUserId(), provider, options); + } + + /** + * Set the provider for a given appWidgetId if the caller has a permission. + * <p> + * <strong>Note:</strong> You need the {@link android.Manifest.permission#BIND_APPWIDGET} + * permission or the user must have enabled binding widgets always for your component. + * Should be used by apps that host widgets. If this method returns false, call {@link + * #ACTION_APPWIDGET_BIND} to request permission to bind. + * </p> + * + * @param appWidgetId The AppWidget id under which to bind the provider. + * @param user The user id in which the provider resides. + * @param provider The component name of the provider. + * @param options An optional Bundle containing options for the AppWidget. + * + * @return true if this component has permission to bind the AppWidget + */ + public boolean bindAppWidgetIdIfAllowed(int appWidgetId, UserHandle user, + ComponentName provider, Bundle options) { + if (mService == null) { + return false; + } + return bindAppWidgetIdIfAllowed(appWidgetId, user.getIdentifier(), provider, options); + } + + /** + * Query if a given package was granted permission by the user to bind app widgets + * + * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission + * + * @param packageName The package for which the permission is being queried + * @param userId The user id of the user under which the package runs. + * @return true if the package was granted permission by the user to bind app widgets + * @hide + */ + public boolean hasBindAppWidgetPermission(String packageName, int userId) { + if (mService == null) { return false; } try { - return sService.bindAppWidgetIdIfAllowed(mContext.getPackageName(), appWidgetId, - provider, options, mContext.getUserId()); + return mService.hasBindAppWidgetPermission(packageName, userId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -729,8 +933,11 @@ * @hide */ public boolean hasBindAppWidgetPermission(String packageName) { + if (mService == null) { + return false; + } try { - return sService.hasBindAppWidgetPermission(packageName, mContext.getUserId()); + return mService.hasBindAppWidgetPermission(packageName, UserHandle.myUserId()); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -742,13 +949,35 @@ * * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission * - * @param provider The package whose permission is being changed - * @param permission Whether to give the package permission to bind widgets + * @param packageName The package whose permission is being changed + * @param permission Whether to give the package permission to bind widgets + * * @hide */ public void setBindAppWidgetPermission(String packageName, boolean permission) { + if (mService == null) { + return; + } + setBindAppWidgetPermission(packageName, UserHandle.myUserId(), permission); + } + + /** + * Changes any user-granted permission for the given package to bind app widgets + * + * <p class="note">You need the MODIFY_APPWIDGET_BIND_PERMISSIONS permission + * + * @param packageName The package whose permission is being changed + * @param userId The user under which the package is running. + * @param permission Whether to give the package permission to bind widgets + * + * @hide + */ + public void setBindAppWidgetPermission(String packageName, int userId, boolean permission) { + if (mService == null) { + return; + } try { - sService.setBindAppWidgetPermission(packageName, permission, mContext.getUserId()); + mService.setBindAppWidgetPermission(packageName, userId, permission); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -761,18 +990,20 @@ * The appWidgetId specified must already be bound to the calling AppWidgetHost via * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}. * + * @param packageName The package from which the binding is requested. * @param appWidgetId The AppWidget instance for which to bind the RemoteViewsService. * @param intent The intent of the service which will be providing the data to the * RemoteViewsAdapter. * @param connection The callback interface to be notified when a connection is made or lost. - * @param userHandle The user to bind to. * @hide */ - public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, - UserHandle userHandle) { + public void bindRemoteViewsService(String packageName, int appWidgetId, Intent intent, + IBinder connection) { + if (mService == null) { + return; + } try { - sService.bindRemoteViewsService(appWidgetId, intent, connection, - userHandle.getIdentifier()); + mService.bindRemoteViewsService(packageName, appWidgetId, intent, connection); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -785,15 +1016,18 @@ * The appWidgetId specified muse already be bound to the calling AppWidgetHost via * {@link android.appwidget.AppWidgetManager#bindAppWidgetId AppWidgetManager.bindAppWidgetId()}. * + * @param packageName The package from which the binding is requested. * @param appWidgetId The AppWidget instance for which to bind the RemoteViewsService. * @param intent The intent of the service which will be providing the data to the * RemoteViewsAdapter. - * @param userHandle The user to unbind from. * @hide */ - public void unbindRemoteViewsService(int appWidgetId, Intent intent, UserHandle userHandle) { + public void unbindRemoteViewsService(String packageName, int appWidgetId, Intent intent) { + if (mService == null) { + return; + } try { - sService.unbindRemoteViewsService(appWidgetId, intent, userHandle.getIdentifier()); + mService.unbindRemoteViewsService(packageName, appWidgetId, intent); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -808,12 +1042,40 @@ * AppWidget provider to find appWidgetIds for. */ public int[] getAppWidgetIds(ComponentName provider) { + if (mService == null) { + return new int[0]; + } try { - return sService.getAppWidgetIds(provider, mContext.getUserId()); + return mService.getAppWidgetIds(provider); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } } -} + private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId, + ComponentName provider, Bundle options) { + if (mService == null) { + return false; + } + try { + return mService.bindAppWidgetId(mPackageName, appWidgetId, + profileId, provider, options); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + private void convertSizesToPixels(AppWidgetProviderInfo info) { + // Converting complex to dp. + info.minWidth = TypedValue.complexToDimensionPixelSize(info.minWidth, + mDisplayMetrics); + info.minHeight = TypedValue.complexToDimensionPixelSize(info.minHeight, + mDisplayMetrics); + info.minResizeWidth = TypedValue.complexToDimensionPixelSize(info.minResizeWidth, + mDisplayMetrics); + info.minResizeHeight = TypedValue.complexToDimensionPixelSize(info.minResizeHeight, + mDisplayMetrics); + } +}
diff --git a/core/java/android/appwidget/AppWidgetProvider.java b/core/java/android/appwidget/AppWidgetProvider.java index edf142b..ab91edf 100644 --- a/core/java/android/appwidget/AppWidgetProvider.java +++ b/core/java/android/appwidget/AppWidgetProvider.java
@@ -66,15 +66,13 @@ this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds); } } - } - else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { + } else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { Bundle extras = intent.getExtras(); if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) { final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID); this.onDeleted(context, new int[] { appWidgetId }); } - } - else if (AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) { + } else if (AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) { Bundle extras = intent.getExtras(); if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID) && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS)) { @@ -83,19 +81,28 @@ this.onAppWidgetOptionsChanged(context, AppWidgetManager.getInstance(context), appWidgetId, widgetExtras); } - } - else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { + } else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { this.onEnabled(context); - } - else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) { + } else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) { this.onDisabled(context); + } else if (AppWidgetManager.ACTION_APPWIDGET_RESTORED.equals(action)) { + Bundle extras = intent.getExtras(); + if (extras != null) { + int[] oldIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS); + int[] newIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); + if (oldIds != null && oldIds.length > 0) { + this.onRestored(context, oldIds, newIds); + this.onUpdate(context, AppWidgetManager.getInstance(context), newIds); + } + } } } // END_INCLUDE(onReceive) /** - * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_UPDATE} broadcast when - * this AppWidget provider is being asked to provide {@link android.widget.RemoteViews RemoteViews} + * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_UPDATE} and + * {@link AppWidgetManager#ACTION_APPWIDGET_RESTORED} broadcasts when this AppWidget + * provider is being asked to provide {@link android.widget.RemoteViews RemoteViews} * for a set of AppWidgets. Override this method to implement your own AppWidget functionality. * * {@more} @@ -123,8 +130,8 @@ * running. * @param appWidgetManager A {@link AppWidgetManager} object you can call {@link * AppWidgetManager#updateAppWidget} on. - * @param appWidgetId The appWidgetId of the widget who's size changed. - * @param newOptions The appWidgetId of the widget who's size changed. + * @param appWidgetId The appWidgetId of the widget whose size changed. + * @param newOptions The appWidgetId of the widget whose size changed. * * @see AppWidgetManager#ACTION_APPWIDGET_OPTIONS_CHANGED */ @@ -181,4 +188,24 @@ */ public void onDisabled(Context context) { } + + /** + * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_RESTORED} broadcast + * when instances of this AppWidget provider have been restored from backup. If your + * provider maintains any persistent data about its widget instances, override this method + * to remap the old AppWidgetIds to the new values and update any other app state that may + * be relevant. + * + * <p>This callback will be followed immediately by a call to {@link #onUpdate} so your + * provider can immediately generate new RemoteViews suitable for its newly-restored set + * of instances. + * + * {@more} + * + * @param context + * @param oldWidgetIds + * @param newWidgetIds + */ + public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) { + } }
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 7b8b286..b4d79b4 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -16,9 +16,16 @@ package android.appwidget; +import android.annotation.NonNull; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.content.ComponentName; +import android.os.UserHandle; /** * Describes the meta data for an installed AppWidget provider. The fields in this class @@ -54,6 +61,11 @@ public static final int WIDGET_CATEGORY_KEYGUARD = 2; /** + * Indicates that the widget can be displayed within a space reserved for the search box. + */ + public static final int WIDGET_CATEGORY_SEARCHBOX = 4; + + /** * Identity of this AppWidget component. This component should be a {@link * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents * {@link android.appwidget as described in the AppWidget package documentation}. @@ -140,16 +152,15 @@ public ComponentName configure; /** - * The label to display to the user in the AppWidget picker. If not supplied in the - * xml, the application label will be used. + * The label to display to the user in the AppWidget picker. * - * <p>This field corresponds to the <code>android:label</code> attribute in - * the <code><receiver></code> element in the AndroidManifest.xml file. + * @deprecated Use {@link #loadLabel(android.content.pm.PackageManager)}. */ + @Deprecated public String label; /** - * The icon to display for this AppWidget in the AppWidget picker. If not supplied in the + * The icon to display for this AppWidget in the AppWidget picker. If not supplied in the * xml, the application icon will be used. * * <p>This field corresponds to the <code>android:icon</code> attribute in @@ -172,7 +183,7 @@ * <p>This field corresponds to the <code>android:previewImage</code> attribute in * the <code><receiver></code> element in the AndroidManifest.xml file. */ - public int previewImage; + public int previewImage; /** * The rules by which a widget can be resized. See {@link #RESIZE_NONE}, @@ -195,12 +206,17 @@ */ public int widgetCategory; + /** @hide */ + public ActivityInfo providerInfo; + public AppWidgetProviderInfo() { + } /** * Unflatten the AppWidgetProviderInfo from a parcel. */ + @SuppressWarnings("deprecation") public AppWidgetProviderInfo(Parcel in) { if (0 != in.readInt()) { this.provider = new ComponentName(in); @@ -221,8 +237,74 @@ this.autoAdvanceViewId = in.readInt(); this.resizeMode = in.readInt(); this.widgetCategory = in.readInt(); + this.providerInfo = in.readParcelable(null); } + /** + * Loads the localized label to display to the user in the AppWidget picker. + * + * @param packageManager Package manager instance for loading resources. + * @return The label for the current locale. + */ + public final String loadLabel(PackageManager packageManager) { + CharSequence label = providerInfo.loadLabel(packageManager); + if (label != null) { + return label.toString().trim(); + } + return null; + } + + /** + * Loads the icon to display for this AppWidget in the AppWidget picker. If not + * supplied in the xml, the application icon will be used. A client can optionally + * provide a desired density such as {@link android.util.DisplayMetrics#DENSITY_LOW} + * {@link android.util.DisplayMetrics#DENSITY_MEDIUM}, etc. If no density is + * provided, the density of the current display will be used. + * <p> + * The loaded icon corresponds to the <code>android:icon</code> attribute in + * the <code><receiver></code> element in the AndroidManifest.xml file. + * </p> + * + * @param context Context for accessing resources. + * @param density The optional desired density as per + * {@link android.util.DisplayMetrics#densityDpi}. + * @return The provider icon. + */ + public final Drawable loadIcon(@NonNull Context context, int density) { + return loadDrawable(context, density, providerInfo.getIconResource(), true); + } + + /** + * Loads a preview of what the AppWidget will look like after it's configured. + * A client can optionally provide a desired density such as + * {@link android.util.DisplayMetrics#DENSITY_LOW} + * {@link android.util.DisplayMetrics#DENSITY_MEDIUM}, etc. If no density is + * provided, the density of the current display will be used. + * <p> + * The loaded image corresponds to the <code>android:previewImage</code> attribute + * in the <code><receiver></code> element in the AndroidManifest.xml file. + * </p> + * + * @param context Context for accessing resources. + * @param density The optional desired density as per + * {@link android.util.DisplayMetrics#densityDpi}. + * @return The widget preview image or null if preview image is not available. + */ + public final Drawable loadPreviewImage(@NonNull Context context, int density) { + return loadDrawable(context, density, previewImage, false); + } + + /** + * Gets the user profile in which the provider resides. + * + * @return The hosting user profile. + */ + public final UserHandle getProfile() { + return new UserHandle(UserHandle.getUserId(providerInfo.applicationInfo.uid)); + } + + @Override + @SuppressWarnings("deprecation") public void writeToParcel(android.os.Parcel out, int flags) { if (this.provider != null) { out.writeInt(1); @@ -249,9 +331,11 @@ out.writeInt(this.autoAdvanceViewId); out.writeInt(this.resizeMode); out.writeInt(this.widgetCategory); + out.writeParcelable(this.providerInfo, flags); } @Override + @SuppressWarnings("deprecation") public AppWidgetProviderInfo clone() { AppWidgetProviderInfo that = new AppWidgetProviderInfo(); that.provider = this.provider == null ? null : this.provider.clone(); @@ -268,7 +352,8 @@ that.previewImage = this.previewImage; that.autoAdvanceViewId = this.autoAdvanceViewId; that.resizeMode = this.resizeMode; - that.widgetCategory = this.widgetCategory; + that.widgetCategory = this.widgetCategory; + that.providerInfo = this.providerInfo; return that; } @@ -276,6 +361,23 @@ return 0; } + private Drawable loadDrawable(Context context, int density, int resourceId, + boolean loadDefaultIcon) { + try { + Resources resources = context.getPackageManager().getResourcesForApplication( + providerInfo.applicationInfo); + if (resourceId > 0) { + if (density <= 0) { + density = context.getResources().getDisplayMetrics().densityDpi; + } + return resources.getDrawableForDensity(resourceId, density); + } + } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { + /* ignore */ + } + return loadDefaultIcon ? providerInfo.loadIcon(context.getPackageManager()) : null; + } + /** * Parcelable.Creator that instantiates AppWidgetProviderInfo objects */ @@ -294,6 +396,6 @@ }; public String toString() { - return "AppWidgetProviderInfo(provider=" + this.provider + ")"; + return "AppWidgetProviderInfo(" + getProfile() + '/' + provider + ')'; } }
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 6f929f2..5175490 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -90,6 +90,11 @@ public static final String ACTION_PLAYING_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED"; + /** @hide */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED = + "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED"; + /** * A2DP sink device is streaming music. This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of @@ -162,7 +167,8 @@ Intent intent = new Intent(IBluetoothA2dp.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); return false; }
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java new file mode 100644 index 0000000..2e27345 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -0,0 +1,432 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides the public APIs to control the Bluetooth A2DP Sink + * profile. + * + *<p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothA2dpSink proxy object. + * + * @hide + */ +public final class BluetoothA2dpSink implements BluetoothProfile { + private static final String TAG = "BluetoothA2dpSink"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** + * Intent used to broadcast the change in connection state of the A2DP Sink + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED"; + + /** + * Intent used to broadcast the change in the Playing state of the A2DP Sink + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING}, + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + public static final String ACTION_PLAYING_STATE_CHANGED = + "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED"; + + /** + * A2DP sink device is streaming music. This state can be one of + * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of + * {@link #ACTION_PLAYING_STATE_CHANGED} intent. + */ + public static final int STATE_PLAYING = 10; + + /** + * A2DP sink device is NOT streaming music. This state can be one of + * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of + * {@link #ACTION_PLAYING_STATE_CHANGED} intent. + */ + public static final int STATE_NOT_PLAYING = 11; + + /** + * Intent used to broadcast the change in the Playing state of the A2DP Sink + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_AUDIO_CONFIG} - The audio configuration for the remote device. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + public static final String ACTION_AUDIO_CONFIG_CHANGED = + "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED"; + + /** + * Extra for the {@link #ACTION_AUDIO_CONFIG_CHANGED} intent. + * + * This extra represents the current audio configuration of the A2DP source device. + * {@see BluetoothAudioConfig} + */ + public static final String EXTRA_AUDIO_CONFIG + = "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG"; + + private Context mContext; + private ServiceListener mServiceListener; + private IBluetoothA2dpSink mService; + private BluetoothAdapter mAdapter; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + doBind(); + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + /** + * Create a BluetoothA2dp proxy object for interacting with the local + * Bluetooth A2DP service. + * + */ + /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothA2dpSink.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); + return false; + } + return true; + } + + /*package*/ void close() { + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + + public void finalize() { + close(); + } + /** + * Initiate connection to a profile of the remote bluetooth device. + * + * <p> Currently, the system supports only 1 connection to the + * A2DP profile. The API will automatically disconnect connected + * devices before connecting. + * + * <p> This API returns false in scenarios like the profile on the + * device is already connected or Bluetooth is not turned on. + * When this API returns true, it is guaranteed that + * connection state intent for the profile will be broadcasted with + * the state. Users can get the connection state of the profile + * from this intent. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean connect(BluetoothDevice device) { + if (DBG) log("connect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.connect(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Initiate disconnection from a profile + * + * <p> This API will return false in scenarios like the profile on the + * Bluetooth device is not in connected state etc. When this API returns, + * true, it is guaranteed that the connection state change + * intent will be broadcasted with the state. Users can get the + * disconnection state of the profile from this intent. + * + * <p> If the disconnection is initiated by a remote device, the state + * will transition from {@link #STATE_CONNECTED} to + * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the + * host (local) device the state will transition from + * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to + * state {@link #STATE_DISCONNECTED}. The transition to + * {@link #STATE_DISCONNECTING} can be used to distinguish between the + * two scenarios. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + if (mService != null && isEnabled() + && isValidDevice(device)) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + /** + * Get the current audio configuration for the A2DP source device, + * or null if the device has no audio configuration + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. + * + * @param device Remote bluetooth device. + * @return audio configuration for the device, or null + * + * {@see BluetoothAudioConfig} + */ + public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) { + if (VDBG) log("getAudioConfig(" + device + ")"); + if (mService != null && isEnabled() + && isValidDevice(device)) { + try { + return mService.getAudioConfig(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return null; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } + + /** + * Helper for converting a state to a string. + * + * For debug use only - strings are not internationalized. + * @hide + */ + public static String stateToString(int state) { + switch (state) { + case STATE_DISCONNECTED: + return "disconnected"; + case STATE_CONNECTING: + return "connecting"; + case STATE_CONNECTED: + return "connected"; + case STATE_DISCONNECTING: + return "disconnecting"; + case STATE_PLAYING: + return "playing"; + case STATE_NOT_PLAYING: + return "not playing"; + default: + return "<unknown state " + state + ">"; + } + } + + private final ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "Proxy object connected"); + mService = IBluetoothA2dpSink.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK, + BluetoothA2dpSink.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +}
diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.aidl b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.aidl new file mode 100644 index 0000000..60cbf9f --- /dev/null +++ b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.aidl
@@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +parcelable BluetoothActivityEnergyInfo;
diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java new file mode 100644 index 0000000..ce87329 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
@@ -0,0 +1,141 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Record of energy and activity information from controller and + * underlying bt stack state.Timestamp the record with system + * time + * @hide + */ +public final class BluetoothActivityEnergyInfo implements Parcelable { + private final int mBluetoothStackState; + private final int mControllerTxTimeMs; + private final int mControllerRxTimeMs; + private final int mControllerIdleTimeMs; + private final int mControllerEnergyUsed; + private final long timestamp; + + public static final int BT_STACK_STATE_INVALID = 0; + public static final int BT_STACK_STATE_STATE_ACTIVE = 1; + public static final int BT_STACK_STATE_STATE_SCANNING = 2; + public static final int BT_STACK_STATE_STATE_IDLE = 3; + + public BluetoothActivityEnergyInfo(int stackState, int txTime, int rxTime, + int idleTime, int energyUsed) { + mBluetoothStackState = stackState; + mControllerTxTimeMs = txTime; + mControllerRxTimeMs = rxTime; + mControllerIdleTimeMs = idleTime; + mControllerEnergyUsed = energyUsed; + timestamp = System.currentTimeMillis(); + } + + @Override + public String toString() { + return "BluetoothActivityEnergyInfo{" + + " timestamp=" + timestamp + + " mBluetoothStackState=" + mBluetoothStackState + + " mControllerTxTimeMs=" + mControllerTxTimeMs + + " mControllerRxTimeMs=" + mControllerRxTimeMs + + " mControllerIdleTimeMs=" + mControllerIdleTimeMs + + " mControllerEnergyUsed=" + mControllerEnergyUsed + + " }"; + } + + public static final Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR = + new Parcelable.Creator<BluetoothActivityEnergyInfo>() { + public BluetoothActivityEnergyInfo createFromParcel(Parcel in) { + int stackState = in.readInt(); + int txTime = in.readInt(); + int rxTime = in.readInt(); + int idleTime = in.readInt(); + int energyUsed = in.readInt(); + return new BluetoothActivityEnergyInfo(stackState, txTime, rxTime, + idleTime, energyUsed); + } + public BluetoothActivityEnergyInfo[] newArray(int size) { + return new BluetoothActivityEnergyInfo[size]; + } + }; + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mBluetoothStackState); + out.writeInt(mControllerTxTimeMs); + out.writeInt(mControllerRxTimeMs); + out.writeInt(mControllerIdleTimeMs); + out.writeInt(mControllerEnergyUsed); + } + + public int describeContents() { + return 0; + } + + /** + * @return bt stack reported state + */ + public int getBluetoothStackState() { + return mBluetoothStackState; + } + + /** + * @return tx time in ms + */ + public int getControllerTxTimeMillis() { + return mControllerTxTimeMs; + } + + /** + * @return rx time in ms + */ + public int getControllerRxTimeMillis() { + return mControllerRxTimeMs; + } + + /** + * @return idle time in ms + */ + public int getControllerIdleTimeMillis() { + return mControllerIdleTimeMs; + } + + /** + * product of current(mA), voltage(V) and time(ms) + * @return energy used + */ + public int getControllerEnergyUsed() { + return mControllerEnergyUsed; + } + /** + * @return timestamp(wall clock) of record creation + */ + public long getTimeStamp() { + return timestamp; + } + + /** + * @return if the record is valid + */ + public boolean isValid() { + return ((getControllerTxTimeMillis() !=0) || + (getControllerRxTimeMillis() !=0) || + (getControllerIdleTimeMillis() !=0)); + } +}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 646be06..f0b609a 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2009-2014 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. @@ -18,12 +18,17 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanRecord; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; import android.content.Context; -import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Message; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ServiceManager; @@ -37,9 +42,9 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.UUID; @@ -216,22 +221,6 @@ "android.bluetooth.adapter.action.SCAN_MODE_CHANGED"; /** - * Broadcast Action: Indicate BLE Advertising is started. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED = - "android.bluetooth.adapter.action.ADVERTISING_STARTED"; - - /** - * Broadcast Action: Indicated BLE Advertising is stopped. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED = - "android.bluetooth.adapter.action.ADVERTISING_STOPPED"; - - /** * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} * intents to request the current scan mode. Possible values are: * {@link #SCAN_MODE_NONE}, @@ -367,43 +356,31 @@ /** The profile is in disconnecting state */ public static final int STATE_DISCONNECTING = 3; - /** States for Bluetooth LE advertising */ - /** @hide */ - public static final int STATE_ADVERTISE_STARTING = 0; - /** @hide */ - public static final int STATE_ADVERTISE_STARTED = 1; - /** @hide */ - public static final int STATE_ADVERTISE_STOPPING = 2; - /** @hide */ - public static final int STATE_ADVERTISE_STOPPED = 3; - /** - * Force stopping advertising without callback in case the advertising app dies. - * @hide - */ - public static final int STATE_ADVERTISE_FORCE_STOPPING = 4; - /** @hide */ public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager"; - /** @hide */ - public static final int ADVERTISE_CALLBACK_SUCCESS = 0; - private static final int ADDRESS_LENGTH = 17; + private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; + /** @hide */ + public static final int ACTIVITY_ENERGY_INFO_CACHED = 0; + /** @hide */ + public static final int ACTIVITY_ENERGY_INFO_REFRESHED = 1; + /** * Lazily initialized singleton. Guaranteed final after first object * constructed. */ private static BluetoothAdapter sAdapter; + private static BluetoothLeScanner sBluetoothLeScanner; + private static BluetoothLeAdvertiser sBluetoothLeAdvertiser; + private final IBluetoothManager mManagerService; private IBluetooth mService; - private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients; - private BluetoothAdvScanData mBluetoothAdvScanData = null; - private GattCallbackWrapper mAdvertisingGattCallback; - private final Handler mHandler; // Handler to post the advertise callback to run on main thread. private final Object mLock = new Object(); + private final Map<LeScanCallback, ScanCallback> mLeScanClients; /** * Get a handle to the default local Bluetooth adapter. @@ -438,8 +415,7 @@ mService = managerService.registerAdapter(mManagerCallback); } catch (RemoteException e) {Log.e(TAG, "", e);} mManagerService = managerService; - mLeScanClients = new HashMap<LeScanCallback, GattCallbackWrapper>(); - mHandler = new Handler(Looper.getMainLooper()); + mLeScanClients = new HashMap<LeScanCallback, ScanCallback>(); } /** @@ -478,126 +454,40 @@ } /** - * Returns a {@link BluetoothAdvScanData} object representing advertising data. - * Data will be reset when bluetooth service is turned off. - * @hide + * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations, or + * null if Bluetooth LE Advertising is not support on this device. + * <p> + * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported + * on this device before calling this method. */ - public BluetoothAdvScanData getAdvScanData() { - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - if (iGatt == null) { - // BLE is not supported - Log.e(TAG, "failed to start, iGatt null"); - return null; - } - if (mBluetoothAdvScanData == null) { - mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD); - } - return mBluetoothAdvScanData; - } catch (RemoteException e) { - Log.e(TAG, "failed to get advScanData, error: " + e); - return null; - } - } - - /** - * Interface for BLE advertising callback. - * - * @hide - */ - public interface AdvertiseCallback { - /** - * Callback when advertise starts. - * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure. - */ - void onAdvertiseStart(int status); - /** - * Callback when advertise stops. - * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure. - */ - void onAdvertiseStop(int status); - } - - /** - * Start BLE advertising using current {@link BluetoothAdvScanData}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} - * - * @param callback - {@link AdvertiseCallback} - * @return true if BLE advertising succeeds, false otherwise. - * @hide - */ - public boolean startAdvertising(final AdvertiseCallback callback) { - if (getState() != STATE_ON) return false; - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - if (iGatt == null) { - // BLE is not supported. - return false; - } - // Restart/reset advertising packets if advertising is in progress. - if (isAdvertising()) { - // Invalid advertising callback. - if (mAdvertisingGattCallback == null || mAdvertisingGattCallback.mLeHandle == -1) { - Log.e(TAG, "failed to restart advertising, invalid callback"); - return false; - } - iGatt.startAdvertising(mAdvertisingGattCallback.mLeHandle); - // Run the callback from main thread. - mHandler.post(new Runnable() { - @Override - public void run() { - // callback with status success. - callback.onAdvertiseStart(ADVERTISE_CALLBACK_SUCCESS); - } - }); - return true; - } - UUID uuid = UUID.randomUUID(); - GattCallbackWrapper wrapper = - new GattCallbackWrapper(this, null, null, callback); - iGatt.registerClient(new ParcelUuid(uuid), wrapper); - if (!wrapper.advertiseStarted()) { - return false; - } - synchronized (mLock) { - mAdvertisingGattCallback = wrapper; - } - return true; - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; + public BluetoothLeAdvertiser getBluetoothLeAdvertiser() { + if (getState() != STATE_ON) { + return null; } + if (!isMultipleAdvertisementSupported()) { + return null; + } + synchronized(mLock) { + if (sBluetoothLeAdvertiser == null) { + sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService); + } + } + return sBluetoothLeAdvertiser; } /** - * Stop BLE advertising. The callback has to be the same one used for start advertising. - * - * @param callback - {@link AdvertiseCallback} - * @return true if BLE advertising stops, false otherwise. - * @hide + * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations. */ - public boolean stopAdvertising(AdvertiseCallback callback) { - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - if (iGatt == null) { - // BLE is not supported - return false; - } - if (mAdvertisingGattCallback == null) { - // no callback. - return false; - } - // Make sure same callback is used for start and stop advertising. - if (callback != mAdvertisingGattCallback.mAdvertiseCallback) { - Log.e(TAG, "must use the same callback for star/stop advertising"); - return false; - } - mAdvertisingGattCallback.stopAdvertising(); - return true; - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; + public BluetoothLeScanner getBluetoothLeScanner() { + if (getState() != STATE_ON) { + return null; } + synchronized(mLock) { + if (sBluetoothLeScanner == null) { + sBluetoothLeScanner = new BluetoothLeScanner(mManagerService); + } + } + return sBluetoothLeScanner; } /** @@ -1012,23 +902,88 @@ } /** - * Returns whether BLE is currently advertising. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * Return true if the multi advertisement is supported by the chipset * - * @hide + * @return true if Multiple Advertisement feature is supported */ - public boolean isAdvertising() { + public boolean isMultipleAdvertisementSupported() { if (getState() != STATE_ON) return false; try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - return iGatt.isAdvertising(); + return mService.isMultiAdvertisementSupported(); } catch (RemoteException e) { - Log.e(TAG, "", e); + Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e); } return false; } /** + * Return true if offloaded filters are supported + * + * @return true if chipset supports on-chip filtering + */ + public boolean isOffloadedFilteringSupported() { + if (getState() != STATE_ON) return false; + try { + return mService.isOffloadedFilteringSupported(); + } catch (RemoteException e) { + Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e); + } + return false; + } + + /** + * Return true if offloaded scan batching is supported + * + * @return true if chipset supports on-chip scan batching + */ + public boolean isOffloadedScanBatchingSupported() { + if (getState() != STATE_ON) return false; + try { + return mService.isOffloadedScanBatchingSupported(); + } catch (RemoteException e) { + Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e); + } + return false; + } + + /** + * Return the record of {@link BluetoothActivityEnergyInfo} object that + * has the activity and energy info. This can be used to ascertain what + * the controller has been up to, since the last sample. + * @param updateType Type of info, cached vs refreshed. + * + * @return a record with {@link BluetoothActivityEnergyInfo} or null if + * report is unavailable or unsupported + * @hide + */ + public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { + if (getState() != STATE_ON) return null; + try { + BluetoothActivityEnergyInfo record; + if (!mService.isActivityAndEnergyReportingSupported()) { + return null; + } + synchronized(this) { + if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) { + mService.getActivityEnergyInfoFromController(); + wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); + } + record = mService.reportActivityInfo(); + if (record.isValid()) { + return record; + } else { + return null; + } + } + } catch (InterruptedException e) { + Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e); + } catch (RemoteException e) { + Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); + } + return null; + } + + /** * Return the set of {@link BluetoothDevice} objects that are bonded * (paired) to the local adapter. * <p>If Bluetooth state is not {@link #STATE_ON}, this API @@ -1363,6 +1318,12 @@ } else if (profile == BluetoothProfile.A2DP) { BluetoothA2dp a2dp = new BluetoothA2dp(context, listener); return true; + } else if (profile == BluetoothProfile.A2DP_SINK) { + BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener); + return true; + } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) { + BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener); + return true; } else if (profile == BluetoothProfile.INPUT_DEVICE) { BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener); return true; @@ -1375,6 +1336,9 @@ } else if (profile == BluetoothProfile.MAP) { BluetoothMap map = new BluetoothMap(context, listener); return true; + } else if (profile == BluetoothProfile.HEADSET_CLIENT) { + BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener); + return true; } else { return false; } @@ -1403,6 +1367,14 @@ BluetoothA2dp a2dp = (BluetoothA2dp)proxy; a2dp.close(); break; + case BluetoothProfile.A2DP_SINK: + BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy; + a2dpSink.close(); + break; + case BluetoothProfile.AVRCP_CONTROLLER: + BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy; + avrcp.close(); + break; case BluetoothProfile.INPUT_DEVICE: BluetoothInputDevice iDev = (BluetoothInputDevice)proxy; iDev.close(); @@ -1427,6 +1399,10 @@ BluetoothMap map = (BluetoothMap)proxy; map.close(); break; + case BluetoothProfile.HEADSET_CLIENT: + BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy; + headsetClient.close(); + break; } } @@ -1452,8 +1428,9 @@ if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); synchronized (mManagerCallback) { mService = null; - // Reset bluetooth adv scan data when Gatt service is down. - mBluetoothAdvScanData = null; + mLeScanClients.clear(); + if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); + if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ try { if (cb != null) { @@ -1651,7 +1628,10 @@ * * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully + * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} + * instead. */ + @Deprecated public boolean startLeScan(LeScanCallback callback) { return startLeScan(null, callback); } @@ -1668,14 +1648,21 @@ * @param serviceUuids Array of services to look for * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully + * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} + * instead. */ - public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) { + @Deprecated + public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) { if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids); - if (callback == null) { if (DBG) Log.e(TAG, "startLeScan: null callback"); return false; } + BluetoothLeScanner scanner = getBluetoothLeScanner(); + if (scanner == null) { + if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner"); + return false; + } synchronized(mLeScanClients) { if (mLeScanClients.containsKey(callback)) { @@ -1690,13 +1677,50 @@ return false; } - UUID uuid = UUID.randomUUID(); - GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids); - iGatt.registerClient(new ParcelUuid(uuid), wrapper); - if (wrapper.scanStarted()) { - mLeScanClients.put(callback, wrapper); - return true; + ScanCallback scanCallback = new ScanCallback() { + @Override + public void onScanResult(int callbackType, ScanResult result) { + if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) { + // Should not happen. + Log.e(TAG, "LE Scan has already started"); + return; + } + ScanRecord scanRecord = result.getScanRecord(); + if (scanRecord == null) { + return; + } + if (serviceUuids != null) { + List<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); + for (UUID uuid : serviceUuids) { + uuids.add(new ParcelUuid(uuid)); + } + List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids(); + if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) { + if (DBG) Log.d(TAG, "uuids does not match"); + return; + } + } + callback.onLeScan(result.getDevice(), result.getRssi(), + scanRecord.getBytes()); + } + }; + ScanSettings settings = new ScanSettings.Builder() + .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); + + List<ScanFilter> filters = new ArrayList<ScanFilter>(); + if (serviceUuids != null && serviceUuids.length > 0) { + // Note scan filter does not support matching an UUID array so we put one + // UUID to hardware and match the whole array in callback. + ScanFilter filter = new ScanFilter.Builder().setServiceUuid( + new ParcelUuid(serviceUuids[0])).build(); + filters.add(filter); } + scanner.startScan(filters, settings, scanCallback); + + mLeScanClients.put(callback, scanCallback); + return true; + } catch (RemoteException e) { Log.e(TAG,"",e); } @@ -1711,328 +1735,22 @@ * * @param callback used to identify which scan to stop * must be the same handle used to start the scan + * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead. */ + @Deprecated public void stopLeScan(LeScanCallback callback) { if (DBG) Log.d(TAG, "stopLeScan()"); - GattCallbackWrapper wrapper; - synchronized(mLeScanClients) { - wrapper = mLeScanClients.remove(callback); - if (wrapper == null) return; + BluetoothLeScanner scanner = getBluetoothLeScanner(); + if (scanner == null) { + return; } - wrapper.stopLeScan(); - } - - /** - * Bluetooth GATT interface callbacks - */ - private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub { - private static final int LE_CALLBACK_REG_TIMEOUT = 2000; - private static final int LE_CALLBACK_REG_WAIT_COUNT = 5; - - private final AdvertiseCallback mAdvertiseCallback; - private final LeScanCallback mLeScanCb; - - // mLeHandle 0: not registered - // -1: scan stopped - // >0: registered and scan started - private int mLeHandle; - private final UUID[] mScanFilter; - private WeakReference<BluetoothAdapter> mBluetoothAdapter; - - public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, - LeScanCallback leScanCb, UUID[] uuid) { - mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter); - mLeScanCb = leScanCb; - mScanFilter = uuid; - mLeHandle = 0; - mAdvertiseCallback = null; - } - - public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb, - UUID[] uuid, AdvertiseCallback callback) { - mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter); - mLeScanCb = leScanCb; - mScanFilter = uuid; - mLeHandle = 0; - mAdvertiseCallback = callback; - } - - public boolean scanStarted() { - return waitForRegisteration(LE_CALLBACK_REG_WAIT_COUNT); - } - - public boolean advertiseStarted() { - // Wait for registeration callback. - return waitForRegisteration(1); - } - - private boolean waitForRegisteration(int maxWaitCount) { - boolean started = false; - synchronized(this) { - if (mLeHandle == -1) return false; - int count = 0; - // wait for callback registration and LE scan to start - while (mLeHandle == 0 && count < maxWaitCount) { - try { - wait(LE_CALLBACK_REG_TIMEOUT); - } catch (InterruptedException e) { - Log.e(TAG, "Callback reg wait interrupted: " + e); - } - count++; - } - started = (mLeHandle > 0); + synchronized (mLeScanClients) { + ScanCallback scanCallback = mLeScanClients.remove(callback); + if (scanCallback == null) { + if (DBG) Log.d(TAG, "scan not started yet"); + return; } - return started; - } - - public void stopAdvertising() { - synchronized (this) { - if (mLeHandle <= 0) { - Log.e(TAG, "Error state, mLeHandle: " + mLeHandle); - return; - } - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter != null) { - try { - IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - iGatt.stopAdvertising(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to stop advertising" + e); - } - } else { - Log.e(TAG, "stopAdvertising, BluetoothAdapter is null"); - } - notifyAll(); - } - } - - public void stopLeScan() { - synchronized(this) { - if (mLeHandle <= 0) { - Log.e(TAG, "Error state, mLeHandle: " + mLeHandle); - return; - } - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter != null) { - try { - IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - iGatt.stopScan(mLeHandle, false); - iGatt.unregisterClient(mLeHandle); - } catch (RemoteException e) { - Log.e(TAG, "Failed to stop scan and unregister" + e); - } - } else { - Log.e(TAG, "stopLeScan, BluetoothAdapter is null"); - } - mLeHandle = -1; - notifyAll(); - } - } - - /** - * Application interface registered - app is ready to go - */ - public void onClientRegistered(int status, int clientIf) { - if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status + - " clientIf=" + clientIf); - synchronized(this) { - if (mLeHandle == -1) { - if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled"); - } - - if (status == BluetoothGatt.GATT_SUCCESS) { - mLeHandle = clientIf; - IBluetoothGatt iGatt = null; - try { - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter != null) { - iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - if (mAdvertiseCallback != null) { - iGatt.startAdvertising(mLeHandle); - } else { - if (mScanFilter == null) { - iGatt.startScan(mLeHandle, false); - } else { - ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; - for(int i = 0; i != uuids.length; ++i) { - uuids[i] = new ParcelUuid(mScanFilter[i]); - } - iGatt.startScanWithUuids(mLeHandle, false, uuids); - } - } - } else { - Log.e(TAG, "onClientRegistered, BluetoothAdapter null"); - mLeHandle = -1; - } - } catch (RemoteException e) { - Log.e(TAG, "fail to start le scan: " + e); - mLeHandle = -1; - } - if (mLeHandle == -1) { - // registration succeeded but start scan or advertise failed - if (iGatt != null) { - try { - iGatt.unregisterClient(mLeHandle); - } catch (RemoteException e) { - Log.e(TAG, "fail to unregister callback: " + mLeHandle + - " error: " + e); - } - } - } - } else { - // registration failed - mLeHandle = -1; - } - notifyAll(); - } - } - - public void onClientConnectionState(int status, int clientIf, - boolean connected, String address) { - // no op - } - - /** - * Callback reporting an LE scan result. - * @hide - */ - public void onScanResult(String address, int rssi, byte[] advData) { - if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi); - - // Check null in case the scan has been stopped - synchronized(this) { - if (mLeHandle <= 0) return; - } - try { - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter == null) { - Log.d(TAG, "onScanResult, BluetoothAdapter null"); - return; - } - mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception: " + ex); - } - } - - public void onGetService(String address, int srvcType, - int srvcInstId, ParcelUuid srvcUuid) { - // no op - } - - public void onGetIncludedService(String address, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int inclSrvcType, int inclSrvcInstId, - ParcelUuid inclSrvcUuid) { - // no op - } - - public void onGetCharacteristic(String address, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid, - int charProps) { - // no op - } - - public void onGetDescriptor(String address, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid, - int descInstId, ParcelUuid descUuid) { - // no op - } - - public void onSearchComplete(String address, int status) { - // no op - } - - public void onCharacteristicRead(String address, int status, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid, byte[] value) { - // no op - } - - public void onCharacteristicWrite(String address, int status, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid) { - // no op - } - - public void onNotify(String address, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid, - byte[] value) { - // no op - } - - public void onDescriptorRead(String address, int status, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid, - int descInstId, ParcelUuid descrUuid, byte[] value) { - // no op - } - - public void onDescriptorWrite(String address, int status, int srvcType, - int srvcInstId, ParcelUuid srvcUuid, - int charInstId, ParcelUuid charUuid, - int descInstId, ParcelUuid descrUuid) { - // no op - } - - public void onExecuteWrite(String address, int status) { - // no op - } - - public void onReadRemoteRssi(String address, int rssi, int status) { - // no op - } - - public void onAdvertiseStateChange(int advertiseState, int status) { - Log.d(TAG, "on advertise call back, state: " + advertiseState + " status: " + status); - if (advertiseState == STATE_ADVERTISE_STARTED) { - if (status == ADVERTISE_CALLBACK_SUCCESS) { - mAdvertiseCallback.onAdvertiseStart(status); - } else { - // If status is unsuccessful and advertise state is started, it means stop - // advertising fails. - mAdvertiseCallback.onAdvertiseStop(status); - } - } else { - synchronized (this) { - if (status == ADVERTISE_CALLBACK_SUCCESS) { - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter != null) { - try { - IBluetoothGatt iGatt = - adapter.getBluetoothManager().getBluetoothGatt(); - Log.d(TAG, "unregistering client " + mLeHandle); - iGatt.unregisterClient(mLeHandle); - // Reset advertise app handle. - mLeHandle = -1; - adapter.mAdvertisingGattCallback = null; - } catch (RemoteException e) { - Log.e(TAG, "Failed to unregister client" + e); - } - } else { - Log.e(TAG, "cannot unregister client, BluetoothAdapter is null"); - } - } - } - if (status == ADVERTISE_CALLBACK_SUCCESS) { - mAdvertiseCallback.onAdvertiseStop(status); - } else{ - // If status is unsuccesful and advertise state is stopped, it means start - // advertising fails. - mAdvertiseCallback.onAdvertiseStart(status); - } - } - } - - /** - * Callback reporting LE ATT MTU. - * @hide - */ - public void onConfigureMTU(String address, int mtu, int status) { - // no op + scanner.stopScan(scanCallback); } } }
diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java deleted file mode 100644 index df2c256..0000000 --- a/core/java/android/bluetooth/BluetoothAdvScanData.java +++ /dev/null
@@ -1,152 +0,0 @@ -/* - * Copyright (C) 2013 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.bluetooth; -import android.os.ParcelUuid; -import android.os.RemoteException; -import android.util.Log; - -import java.util.Collections; -import java.util.List; - - -/** - * This class provides the public APIs to set advertising and scan response data when BLE device - * operates in peripheral mode. <br> - * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11 - * @hide - */ -public final class BluetoothAdvScanData { - - /** - * Available data types of {@link BluetoothAdvScanData}. - */ - public static final int AD = 0; // Advertising Data - public static final int SCAN_RESPONSE = 1; // Scan Response - public static final int EIR = 2; // Extended Inquiry Response - - private static final String TAG = "BluetoothAdvScanData"; - - /** - * Data type of BluetoothAdvScanData. - */ - private final int mDataType; - /** - * Bluetooth Gatt Service. - */ - private IBluetoothGatt mBluetoothGatt; - - /** - * @param mBluetoothGatt - * @param dataType - */ - public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) { - this.mBluetoothGatt = mBluetoothGatt; - this.mDataType = dataType; - } - - /** - * @return advertising data type. - */ - public int getDataType() { - return mDataType; - } - - /** - * Set manufactureCode and manufactureData. - * Returns true if manufacturer data is set, false if there is no enough room to set - * manufacturer data or the data is already set. - * @param manufacturerCode - unique identifier for the manufacturer - * @param manufacturerData - data associated with the specific manufacturer. - */ - public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) { - if (mDataType != AD) return false; - try { - return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData); - } catch (RemoteException e) { - Log.e(TAG, "Unable to set manufacturer id and data.", e); - return false; - } - } - - /** - * Set service data. Note the service data can only be set when the data type is {@code AD}; - * @param serviceData - */ - public boolean setServiceData(byte[] serviceData) { - - if (mDataType != AD) return false; - if (serviceData == null) return false; - try { - return mBluetoothGatt.setAdvServiceData(serviceData); - } catch (RemoteException e) { - Log.e(TAG, "Unable to set service data.", e); - return false; - } - } - - /** - * Returns an immutable list of service uuids that will be advertised. - */ - public List<ParcelUuid> getServiceUuids() { - try { - return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids()); - } catch (RemoteException e) { - Log.e(TAG, "Unable to get service uuids.", e); - return null; - } - } - - /** - * Returns manufacturer data. - */ - public byte[] getManufacturerData() { - if (mBluetoothGatt == null) return null; - try { - return mBluetoothGatt.getAdvManufacturerData(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to get manufacturer data.", e); - return null; - } - } - - /** - * Returns service data. - */ - public byte[] getServiceData() { - if (mBluetoothGatt == null) return null; - try { - return mBluetoothGatt.getAdvServiceData(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to get service data.", e); - return null; - } - } - - /** - * Remove manufacturer data based on given manufacturer code. - * @param manufacturerCode - */ - public void removeManufacturerCodeAndData(int manufacturerCode) { - if (mBluetoothGatt != null) { - try { - mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode); - } catch (RemoteException e) { - Log.e(TAG, "Unable to remove manufacturer : " + manufacturerCode, e); - } - } - } -}
diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.aidl b/core/java/android/bluetooth/BluetoothAudioConfig.aidl new file mode 100644 index 0000000..63be5cf --- /dev/null +++ b/core/java/android/bluetooth/BluetoothAudioConfig.aidl
@@ -0,0 +1,19 @@ +/* + * Copyright (C) 2009 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.bluetooth; + +parcelable BluetoothAudioConfig;
diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.java b/core/java/android/bluetooth/BluetoothAudioConfig.java new file mode 100644 index 0000000..03176b9 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothAudioConfig.java
@@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Represents the audio configuration for a Bluetooth A2DP source device. + * + * {@see BluetoothA2dpSink} + * + * {@hide} + */ +public final class BluetoothAudioConfig implements Parcelable { + + private final int mSampleRate; + private final int mChannelConfig; + private final int mAudioFormat; + + public BluetoothAudioConfig(int sampleRate, int channelConfig, int audioFormat) { + mSampleRate = sampleRate; + mChannelConfig = channelConfig; + mAudioFormat = audioFormat; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BluetoothAudioConfig) { + BluetoothAudioConfig bac = (BluetoothAudioConfig)o; + return (bac.mSampleRate == mSampleRate && + bac.mChannelConfig == mChannelConfig && + bac.mAudioFormat == mAudioFormat); + } + return false; + } + + @Override + public int hashCode() { + return mSampleRate | (mChannelConfig << 24) | (mAudioFormat << 28); + } + + @Override + public String toString() { + return "{mSampleRate:" + mSampleRate + ",mChannelConfig:" + mChannelConfig + + ",mAudioFormat:" + mAudioFormat + "}"; + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<BluetoothAudioConfig> CREATOR = + new Parcelable.Creator<BluetoothAudioConfig>() { + public BluetoothAudioConfig createFromParcel(Parcel in) { + int sampleRate = in.readInt(); + int channelConfig = in.readInt(); + int audioFormat = in.readInt(); + return new BluetoothAudioConfig(sampleRate, channelConfig, audioFormat); + } + public BluetoothAudioConfig[] newArray(int size) { + return new BluetoothAudioConfig[size]; + } + }; + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mSampleRate); + out.writeInt(mChannelConfig); + out.writeInt(mAudioFormat); + } + + /** + * Returns the sample rate in samples per second + * @return sample rate + */ + public int getSampleRate() { + return mSampleRate; + } + + /** + * Returns the channel configuration (either {@link android.media.AudioFormat#CHANNEL_IN_MONO} + * or {@link android.media.AudioFormat#CHANNEL_IN_STEREO}) + * @return channel configuration + */ + public int getChannelConfig() { + return mChannelConfig; + } + + /** + * Returns the channel audio format (either {@link android.media.AudioFormat#ENCODING_PCM_16BIT} + * or {@link android.media.AudioFormat#ENCODING_PCM_8BIT} + * @return audio format + */ + public int getAudioFormat() { + return mAudioFormat; + } +}
diff --git a/core/java/android/bluetooth/BluetoothAvrcp.java b/core/java/android/bluetooth/BluetoothAvrcp.java new file mode 100644 index 0000000..44fe1b7 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothAvrcp.java
@@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +/** + * This class contains constants for Bluetooth AVRCP profile. + * + * {@hide} + */ +public final class BluetoothAvrcp { + + /* + * State flags for Passthrough commands + */ + public static final int PASSTHROUGH_STATE_PRESS = 0; + public static final int PASSTHROUGH_STATE_RELEASE = 1; + + /* + * Operation IDs for Passthrough commands + */ + public static final int PASSTHROUGH_ID_SELECT = 0x00; /* select */ + public static final int PASSTHROUGH_ID_UP = 0x01; /* up */ + public static final int PASSTHROUGH_ID_DOWN = 0x02; /* down */ + public static final int PASSTHROUGH_ID_LEFT = 0x03; /* left */ + public static final int PASSTHROUGH_ID_RIGHT = 0x04; /* right */ + public static final int PASSTHROUGH_ID_RIGHT_UP = 0x05; /* right-up */ + public static final int PASSTHROUGH_ID_RIGHT_DOWN = 0x06; /* right-down */ + public static final int PASSTHROUGH_ID_LEFT_UP = 0x07; /* left-up */ + public static final int PASSTHROUGH_ID_LEFT_DOWN = 0x08; /* left-down */ + public static final int PASSTHROUGH_ID_ROOT_MENU = 0x09; /* root menu */ + public static final int PASSTHROUGH_ID_SETUP_MENU = 0x0A; /* setup menu */ + public static final int PASSTHROUGH_ID_CONT_MENU = 0x0B; /* contents menu */ + public static final int PASSTHROUGH_ID_FAV_MENU = 0x0C; /* favorite menu */ + public static final int PASSTHROUGH_ID_EXIT = 0x0D; /* exit */ + public static final int PASSTHROUGH_ID_0 = 0x20; /* 0 */ + public static final int PASSTHROUGH_ID_1 = 0x21; /* 1 */ + public static final int PASSTHROUGH_ID_2 = 0x22; /* 2 */ + public static final int PASSTHROUGH_ID_3 = 0x23; /* 3 */ + public static final int PASSTHROUGH_ID_4 = 0x24; /* 4 */ + public static final int PASSTHROUGH_ID_5 = 0x25; /* 5 */ + public static final int PASSTHROUGH_ID_6 = 0x26; /* 6 */ + public static final int PASSTHROUGH_ID_7 = 0x27; /* 7 */ + public static final int PASSTHROUGH_ID_8 = 0x28; /* 8 */ + public static final int PASSTHROUGH_ID_9 = 0x29; /* 9 */ + public static final int PASSTHROUGH_ID_DOT = 0x2A; /* dot */ + public static final int PASSTHROUGH_ID_ENTER = 0x2B; /* enter */ + public static final int PASSTHROUGH_ID_CLEAR = 0x2C; /* clear */ + public static final int PASSTHROUGH_ID_CHAN_UP = 0x30; /* channel up */ + public static final int PASSTHROUGH_ID_CHAN_DOWN = 0x31; /* channel down */ + public static final int PASSTHROUGH_ID_PREV_CHAN = 0x32; /* previous channel */ + public static final int PASSTHROUGH_ID_SOUND_SEL = 0x33; /* sound select */ + public static final int PASSTHROUGH_ID_INPUT_SEL = 0x34; /* input select */ + public static final int PASSTHROUGH_ID_DISP_INFO = 0x35; /* display information */ + public static final int PASSTHROUGH_ID_HELP = 0x36; /* help */ + public static final int PASSTHROUGH_ID_PAGE_UP = 0x37; /* page up */ + public static final int PASSTHROUGH_ID_PAGE_DOWN = 0x38; /* page down */ + public static final int PASSTHROUGH_ID_POWER = 0x40; /* power */ + public static final int PASSTHROUGH_ID_VOL_UP = 0x41; /* volume up */ + public static final int PASSTHROUGH_ID_VOL_DOWN = 0x42; /* volume down */ + public static final int PASSTHROUGH_ID_MUTE = 0x43; /* mute */ + public static final int PASSTHROUGH_ID_PLAY = 0x44; /* play */ + public static final int PASSTHROUGH_ID_STOP = 0x45; /* stop */ + public static final int PASSTHROUGH_ID_PAUSE = 0x46; /* pause */ + public static final int PASSTHROUGH_ID_RECORD = 0x47; /* record */ + public static final int PASSTHROUGH_ID_REWIND = 0x48; /* rewind */ + public static final int PASSTHROUGH_ID_FAST_FOR = 0x49; /* fast forward */ + public static final int PASSTHROUGH_ID_EJECT = 0x4A; /* eject */ + public static final int PASSTHROUGH_ID_FORWARD = 0x4B; /* forward */ + public static final int PASSTHROUGH_ID_BACKWARD = 0x4C; /* backward */ + public static final int PASSTHROUGH_ID_ANGLE = 0x50; /* angle */ + public static final int PASSTHROUGH_ID_SUBPICT = 0x51; /* subpicture */ + public static final int PASSTHROUGH_ID_F1 = 0x71; /* F1 */ + public static final int PASSTHROUGH_ID_F2 = 0x72; /* F2 */ + public static final int PASSTHROUGH_ID_F3 = 0x73; /* F3 */ + public static final int PASSTHROUGH_ID_F4 = 0x74; /* F4 */ + public static final int PASSTHROUGH_ID_F5 = 0x75; /* F5 */ + public static final int PASSTHROUGH_ID_VENDOR = 0x7E; /* vendor unique */ + public static final int PASSTHROUGH_KEYPRESSED_RELEASE = 0x80; +}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java new file mode 100644 index 0000000..b53a8fc --- /dev/null +++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -0,0 +1,260 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides the public APIs to control the Bluetooth AVRCP Controller + * profile. + * + *<p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothAvrcpController proxy object. + * + * {@hide} + */ +public final class BluetoothAvrcpController implements BluetoothProfile { + private static final String TAG = "BluetoothAvrcpController"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** + * Intent used to broadcast the change in connection state of the AVRCP Controller + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.acrcp-controller.profile.action.CONNECTION_STATE_CHANGED"; + + private Context mContext; + private ServiceListener mServiceListener; + private IBluetoothAvrcpController mService; + private BluetoothAdapter mAdapter; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + doBind(); + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + + /** + * Create a BluetoothAvrcpController proxy object for interacting with the local + * Bluetooth AVRCP service. + * + */ + /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothAvrcpController.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent); + return false; + } + return true; + } + + /*package*/ void close() { + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + + public void finalize() { + close(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + if (mService != null && isEnabled() + && isValidDevice(device)) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) { + if (DBG) Log.d(TAG, "sendPassThroughCmd"); + if (mService != null && isEnabled()) { + try { + mService.sendPassThroughCmd(device, keyCode, keyState); + return; + } catch (RemoteException e) { + Log.e(TAG, "Error talking to BT service in sendPassThroughCmd()", e); + return; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + } + + private final ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "Proxy object connected"); + mService = IBluetoothAvrcpController.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER, + BluetoothAvrcpController.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index d789a944..5e50b69 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -19,12 +19,10 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; -import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelUuid; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.io.IOException; @@ -308,6 +306,11 @@ public static final String ACTION_UUID = "android.bluetooth.device.action.UUID"; + /** @hide */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_MAS_INSTANCE = + "android.bluetooth.device.action.MAS_INSTANCE"; + /** * Broadcast Action: Indicates a failure to retrieve the name of a remote * device. @@ -515,6 +518,49 @@ public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; /** + * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, + * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. + * @hide + */ + public static final int ACCESS_UNKNOWN = 0; + + /** + * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, + * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. + * @hide + */ + public static final int ACCESS_ALLOWED = 1; + + /** + * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, + * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. + * @hide + */ + public static final int ACCESS_REJECTED = 2; + + /** + * No preferrence of physical transport for GATT connections to remote dual-mode devices + * @hide + */ + public static final int TRANSPORT_AUTO = 0; + + /** + * Prefer BR/EDR transport for GATT connections to remote dual-mode devices + * @hide + */ + public static final int TRANSPORT_BREDR = 1; + + /** + * Prefer LE transport for GATT connections to remote dual-mode devices + * @hide + */ + public static final int TRANSPORT_LE = 2; + + /** @hide */ + public static final String EXTRA_MAS_INSTANCE = + "android.bluetooth.device.extra.MAS_INSTANCE"; + + /** * Lazy initialization. Guaranteed final after first object constructed, or * getService() called. * TODO: Unify implementation of sService amongst BluetoothFoo API's @@ -735,7 +781,38 @@ return false; } try { - return sService.createBond(this); + return sService.createBond(this, TRANSPORT_AUTO); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return false; + } + + /** + * Start the bonding (pairing) process with the remote device using the + * specified transport. + * + * <p>This is an asynchronous call, it will return immediately. Register + * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when + * the bonding process completes, and its result. + * <p>Android system services will handle the necessary user interactions + * to confirm and complete the bonding process. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. + * + * @param transport The transport to use for the pairing procedure. + * @return false on immediate error, true if bonding will begin + * @throws IllegalArgumentException if an invalid transport was specified + * @hide + */ + public boolean createBond(int transport) { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); + return false; + } + if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) + { + throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport"); + } + try { + return sService.createBond(this, transport); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -857,6 +934,26 @@ } /** + * Returns whether there is an open connection to this device. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. + * + * @return True if there is at least one open connection to this device. + * @hide + */ + public boolean isConnected() { + if (sService == null) { + // BT is not enabled, we cannot be connected. + return false; + } + try { + return sService.isConnected(this); + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** * Get the Bluetooth class of the remote device. * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * @@ -876,39 +973,6 @@ } /** - * Get trust state of a remote device. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. - * @hide - */ - public boolean getTrustState() { - //TODO(BT) - /* - try { - return sService.getTrustState(this); - } catch (RemoteException e) { - Log.e(TAG, "", e); - }*/ - return false; - } - - /** - * Set trust state for a remote device. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. - * @param value the trust state value (true or false) - * @hide - */ - public boolean setTrust(boolean value) { - //TODO(BT) - /* - try { - return sService.setTrust(this, value); - } catch (RemoteException e) { - Log.e(TAG, "", e); - }*/ - return false; - } - - /** * Returns the supported features (UUIDs) of the remote device. * * <p>This method does not start a service discovery procedure to retrieve the UUIDs @@ -947,12 +1011,29 @@ * was started. */ public boolean fetchUuidsWithSdp() { + IBluetooth service = sService; + if (service == null) { + Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp"); + return false; + } try { - return sService.fetchRemoteUuids(this); + return service.fetchRemoteUuids(this); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } + /** @hide */ + public boolean fetchMasInstances() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot query remote device for MAS instances"); + return false; + } + try { + return sService.fetchRemoteMasInstances(this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return false; + } + /** @hide */ public int getServiceChannel(ParcelUuid uuid) { //TODO(BT) @@ -1042,6 +1123,82 @@ } /** + * Requires {@link android.Manifest.permission#BLUETOOTH}. + * @return Whether the phonebook access is allowed to this device. Can be + * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. + * @hide + */ + public int getPhonebookAccessPermission() { + if (sService == null) { + return ACCESS_UNKNOWN; + } + try { + return sService.getPhonebookAccessPermission(this); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return ACCESS_UNKNOWN; + } + + /** + * Sets whether the phonebook access is allowed to this device. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or + * {@link #ACCESS_REJECTED}. + * @return Whether the value has been successfully set. + * @hide + */ + public boolean setPhonebookAccessPermission(int value) { + if (sService == null) { + return false; + } + try { + return sService.setPhonebookAccessPermission(this, value); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** + * Requires {@link android.Manifest.permission#BLUETOOTH}. + * @return Whether the message access is allowed to this device. Can be + * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. + * @hide + */ + public int getMessageAccessPermission() { + if (sService == null) { + return ACCESS_UNKNOWN; + } + try { + return sService.getMessageAccessPermission(this); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return ACCESS_UNKNOWN; + } + + /** + * Sets whether the message access is allowed to this device. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or + * {@link #ACCESS_REJECTED}. + * @return Whether the value has been successfully set. + * @hide + */ + public boolean setMessageAccessPermission(int value) { + if (sService == null) { + return false; + } + try { + return sService.setMessageAccessPermission(this, value); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** * Create an RFCOMM {@link BluetoothSocket} ready to start a secure * outgoing connection to this remote device on given channel. * <p>The remote device will be authenticated and communication on this @@ -1213,6 +1370,27 @@ */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) { + return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO)); + } + + /** + * Connect to GATT Server hosted by this device. Caller acts as GATT client. + * The callback is used to deliver results to Caller, such as connection status as well + * as any further GATT client operations. + * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct + * GATT client operations. + * @param callback GATT callback handler that will receive asynchronous callbacks. + * @param autoConnect Whether to directly connect to the remote device (false) + * or to automatically connect as soon as the remote + * device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices + * {@link BluetoothDevice#TRANSPORT_AUTO} or + * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} + * @throws IllegalArgumentException if callback is null + * @hide + */ + public BluetoothGatt connectGatt(Context context, boolean autoConnect, + BluetoothGattCallback callback, int transport) { // TODO(Bluetooth) check whether platform support BLE // Do the check here or in GattServer? BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); @@ -1223,7 +1401,7 @@ // BLE is not supported return null; } - BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this); + BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this, transport); gatt.connect(autoConnect, callback); return gatt; } catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index e7ab8de..c203a8e 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,20 +16,9 @@ package android.bluetooth; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothProfile.ServiceListener; -import android.bluetooth.IBluetoothManager; -import android.bluetooth.IBluetoothStateChangeCallback; - -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.util.ArrayList; @@ -50,7 +39,7 @@ public final class BluetoothGatt implements BluetoothProfile { private static final String TAG = "BluetoothGatt"; private static final boolean DBG = true; - private static final boolean VDBG = true; + private static final boolean VDBG = false; private final Context mContext; private IBluetoothGatt mService; @@ -62,6 +51,7 @@ private int mConnState; private final Object mStateLock = new Object(); private Boolean mDeviceBusy = false; + private int mTransport; private static final int CONN_STATE_IDLE = 0; private static final int CONN_STATE_CONNECTING = 1; @@ -95,10 +85,32 @@ /** A write operation exceeds the maximum length of the attribute */ public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd; + /** A remote device connection is congested. */ + public static final int GATT_CONNECTION_CONGESTED = 0x8f; + /** A GATT operation failed, errors other than the above */ public static final int GATT_FAILURE = 0x101; /** + * Connection paramter update - Use the connection paramters recommended by the + * Bluetooth SIG. This is the default value if no connection parameter update + * is requested. + */ + public static final int CONNECTION_PRIORITY_BALANCED = 0; + + /** + * Connection paramter update - Request a high priority, low latency connection. + * An application should only request high priority connection paramters to transfer + * large amounts of data over LE quickly. Once the transfer is complete, the application + * should request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connectoin parameters + * to reduce energy use. + */ + public static final int CONNECTION_PRIORITY_HIGH = 1; + + /** Connection paramter update - Request low power, reduced data rate connection parameters. */ + public static final int CONNECTION_PRIORITY_LOW_POWER = 2; + + /** * No authentication required. * @hide */ @@ -117,10 +129,10 @@ /*package*/ static final int AUTHENTICATION_MITM = 2; /** - * Bluetooth GATT interface callbacks + * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation. */ private final IBluetoothGattCallback mBluetoothGattCallback = - new IBluetoothGattCallback.Stub() { + new BluetoothGattCallbackWrapper() { /** * Application interface registered - app is ready to go * @hide @@ -146,7 +158,7 @@ } try { mService.clientConnect(mClientIf, mDevice.getAddress(), - !mAutoConnect); // autoConnect is inverse of "isDirect" + !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect" } catch (RemoteException e) { Log.e(TAG,"",e); } @@ -185,14 +197,6 @@ } /** - * Callback reporting an LE scan result. - * @hide - */ - public void onScanResult(String address, int rssi, byte[] advData) { - // no op - } - - /** * A new GATT service has been discovered. * The service is added to the internal list and the search * continues. @@ -200,7 +204,7 @@ */ public void onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid) { - if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid); + if (VDBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid); if (!address.equals(mDevice.getAddress())) { return; } @@ -217,7 +221,7 @@ int srvcInstId, ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid) { - if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address + if (VDBG) Log.d(TAG, "onGetIncludedService() - Device=" + address + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid); if (!address.equals(mDevice.getAddress())) { @@ -243,7 +247,7 @@ int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps) { - if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" + + if (VDBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" + charUuid); if (!address.equals(mDevice.getAddress())) { @@ -267,7 +271,7 @@ int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descUuid) { - if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid); + if (VDBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid); if (!address.equals(mDevice.getAddress())) { return; @@ -277,7 +281,7 @@ if (service == null) return; BluetoothGattCharacteristic characteristic = service.getCharacteristic( - charUuid.getUuid()); + charUuid.getUuid(), charInstId); if (characteristic == null) return; characteristic.addDescriptor(new BluetoothGattDescriptor( @@ -311,7 +315,7 @@ public void onCharacteristicRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) { - if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address + if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address + " UUID=" + charUuid + " Status=" + status); if (!address.equals(mDevice.getAddress())) { @@ -363,7 +367,7 @@ public void onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid) { - if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address + if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address + " UUID=" + charUuid + " Status=" + status); if (!address.equals(mDevice.getAddress())) { @@ -415,7 +419,7 @@ int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) { - if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid); + if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid); if (!address.equals(mDevice.getAddress())) { return; @@ -446,7 +450,7 @@ int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid, byte[] value) { - if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid); + if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid); if (!address.equals(mDevice.getAddress())) { return; @@ -478,6 +482,7 @@ mService.readDescriptor(mClientIf, address, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, descrInstId, descrUuid, AUTHENTICATION_MITM); + return; } catch (RemoteException e) { Log.e(TAG,"",e); } @@ -500,7 +505,7 @@ int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) { - if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid); + if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid); if (!address.equals(mDevice.getAddress())) { return; @@ -531,6 +536,7 @@ srvcType, srvcInstId, srvcUuid, charInstId, charUuid, descrInstId, descrUuid, characteristic.getWriteType(), AUTHENTICATION_MITM, descriptor.getValue()); + return; } catch (RemoteException e) { Log.e(TAG,"",e); } @@ -550,7 +556,7 @@ * @hide */ public void onExecuteWrite(String address, int status) { - if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address + if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address + " status=" + status); if (!address.equals(mDevice.getAddress())) { return; @@ -572,7 +578,7 @@ * @hide */ public void onReadRemoteRssi(String address, int rssi, int status) { - if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address + + if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address + " rssi=" + rssi + " status=" + status); if (!address.equals(mDevice.getAddress())) { return; @@ -585,15 +591,6 @@ } /** - * Advertise state change callback - * @hide - */ - public void onAdvertiseStateChange(int state, int status) { - if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = " - + state + " status=" + status); - } - - /** * Callback invoked when the MTU for a given connection changes * @hide */ @@ -604,17 +601,19 @@ return; } try { - mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status); + mCallback.onMtuChanged(BluetoothGatt.this, mtu, status); } catch (Exception ex) { Log.w(TAG, "Unhandled exception in callback", ex); } } }; - /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) { + /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device, + int transport) { mContext = context; mService = iGatt; mDevice = device; + mTransport = transport; mServices = new ArrayList<BluetoothGattService>(); mConnState = CONN_STATE_IDLE; @@ -705,7 +704,7 @@ * {@link BluetoothGattCallback#onConnectionStateChange} callback will be * invoked when the connection state changes as a result of this function. * - * <p>The autoConnect paramter determines whether to actively connect to + * <p>The autoConnect parameter determines whether to actively connect to * the remote device, or rather passively scan and finalize the connection * when the remote device is in range/available. Generally, the first ever * connection to a device should be direct (autoConnect set to false) and @@ -770,7 +769,7 @@ public boolean connect() { try { mService.clientConnect(mClientIf, mDevice.getAddress(), - false); // autoConnect is inverse of "isDirect" + false, mTransport); // autoConnect is inverse of "isDirect" return true; } catch (RemoteException e) { Log.e(TAG,"",e); @@ -883,7 +882,7 @@ if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false; - if (DBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid()); + if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid()); if (mService == null || mClientIf == 0) return false; BluetoothGattService service = characteristic.getService(); @@ -928,7 +927,7 @@ && (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false; - if (DBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid()); + if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid()); if (mService == null || mClientIf == 0) return false; BluetoothGattService service = characteristic.getService(); @@ -971,7 +970,7 @@ * @return true, if the read operation was initiated successfully */ public boolean readDescriptor(BluetoothGattDescriptor descriptor) { - if (DBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid()); + if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid()); if (mService == null || mClientIf == 0) return false; BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); @@ -1015,7 +1014,7 @@ * @return true, if the write operation was initiated successfully */ public boolean writeDescriptor(BluetoothGattDescriptor descriptor) { - if (DBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid()); + if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid()); if (mService == null || mClientIf == 0) return false; BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); @@ -1069,7 +1068,7 @@ * @return true, if the reliable write transaction has been initiated */ public boolean beginReliableWrite() { - if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress()); + if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; try { @@ -1096,7 +1095,7 @@ * @return true, if the request to execute the transaction has been sent */ public boolean executeReliableWrite() { - if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress()); + if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; synchronized(mDeviceBusy) { @@ -1124,7 +1123,7 @@ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. */ public void abortReliableWrite() { - if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress()); + if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return; try { @@ -1225,21 +1224,20 @@ } /** - * Configure the MTU used for a given connection. + * Request an MTU size used for a given connection. * * <p>When performing a write request operation (write without response), * the data sent is truncated to the MTU size. This function may be used - * to request a larget MTU size to be able to send more data at once. + * to request a larger MTU size to be able to send more data at once. * - * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate + * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate * whether this operation was successful. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @return true, if the new MTU value has been requested successfully - * @hide */ - public boolean configureMTU(int mtu) { + public boolean requestMtu(int mtu) { if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress() + " mtu: " + mtu); if (mService == null || mClientIf == 0) return false; @@ -1255,6 +1253,38 @@ } /** + * Request a connection parameter update. + * + * <p>This function will send a connection parameter update request to the + * remote device. + * + * @param connectionPriority Request a specific connection priority. Must be one of + * {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, + * {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH} + * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}. + * @throws IllegalArgumentException If the parameters are outside of their + * specified range. + */ + public boolean requestConnectionPriority(int connectionPriority) { + if (connectionPriority < CONNECTION_PRIORITY_BALANCED || + connectionPriority > CONNECTION_PRIORITY_LOW_POWER) { + throw new IllegalArgumentException("connectionPriority not within valid range"); + } + + if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority); + if (mService == null || mClientIf == 0) return false; + + try { + mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority); + } catch (RemoteException e) { + Log.e(TAG,"",e); + return false; + } + + return true; + } + + /** * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} * with {@link BluetoothProfile#GATT} as argument *
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java index 5180259..a915620 100644 --- a/core/java/android/bluetooth/BluetoothGattCallback.java +++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -143,14 +143,13 @@ * Callback indicating the MTU for a given device connection has changed. * * This callback is triggered in response to the - * {@link BluetoothGatt#configureMTU} function, or in response to a connection + * {@link BluetoothGatt#requestMtu} function, or in response to a connection * event. * - * @param gatt GATT client invoked {@link BluetoothGatt#configureMTU} + * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu} * @param mtu The new MTU size * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully - * @hide */ - public void onConfigureMTU(BluetoothGatt gatt, int mtu, int status) { + public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { } }
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java new file mode 100644 index 0000000..cdb24f4 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
@@ -0,0 +1,126 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.ScanResult; +import android.os.ParcelUuid; +import android.os.RemoteException; + +import java.util.List; + +/** + * Wrapper class for default implementation of IBluetoothGattCallback. + * + * @hide + */ +public class BluetoothGattCallbackWrapper extends IBluetoothGattCallback.Stub { + + @Override + public void onClientRegistered(int status, int clientIf) throws RemoteException { + } + + @Override + public void onClientConnectionState(int status, int clientIf, boolean connected, String address) + throws RemoteException { + } + + @Override + public void onScanResult(ScanResult scanResult) throws RemoteException { + } + + @Override + public void onBatchScanResults(List<ScanResult> batchResults) throws RemoteException { + } + + @Override + public void onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid) + throws RemoteException { + } + + @Override + public void onGetIncludedService(String address, int srvcType, int srvcInstId, + ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid) + throws RemoteException { + } + + @Override + public void onGetCharacteristic(String address, int srvcType, int srvcInstId, + ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps) + throws RemoteException { + } + + @Override + public void onGetDescriptor(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, + int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) + throws RemoteException { + } + + @Override + public void onSearchComplete(String address, int status) throws RemoteException { + } + + @Override + public void onCharacteristicRead(String address, int status, int srvcType, int srvcInstId, + ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) + throws RemoteException { + } + + @Override + public void onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId, + ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid) throws RemoteException { + } + + @Override + public void onExecuteWrite(String address, int status) throws RemoteException { + } + + @Override + public void onDescriptorRead(String address, int status, int srvcType, int srvcInstId, + ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, + ParcelUuid descrUuid, byte[] value) throws RemoteException { + } + + @Override + public void onDescriptorWrite(String address, int status, int srvcType, int srvcInstId, + ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, + ParcelUuid descrUuid) throws RemoteException { + } + + @Override + public void onNotify(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, + int charInstId, ParcelUuid charUuid, byte[] value) throws RemoteException { + } + + @Override + public void onReadRemoteRssi(String address, int rssi, int status) throws RemoteException { + } + + @Override + public void onMultiAdvertiseCallback(int status, boolean isStart, + AdvertiseSettings advertiseSettings) throws RemoteException { + } + + @Override + public void onConfigureMTU(String address, int mtu, int status) throws RemoteException { + } + + @Override + public void onFoundOrLost(boolean onFound, ScanResult scanResult) throws RemoteException { + } + +}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java index f0ecbb4..a86677c 100644 --- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java +++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -16,7 +16,6 @@ package android.bluetooth; import java.util.ArrayList; -import java.util.IllegalFormatConversionException; import java.util.List; import java.util.UUID;
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index 153215c..e94a8ce 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -19,18 +19,9 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothProfile.ServiceListener; -import android.bluetooth.IBluetoothManager; -import android.bluetooth.IBluetoothStateChangeCallback; - -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.util.ArrayList; @@ -41,16 +32,17 @@ * Public API for the Bluetooth GATT Profile server role. * * <p>This class provides Bluetooth GATT server role functionality, - * allowing applications to create and advertise Bluetooth Smart services - * and characteristics. + * allowing applications to create Bluetooth Smart services and + * characteristics. * * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service - * via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the - * BluetoothGatt proxy object. + * via IPC. Use {@link BluetoothManager#openGattServer} to get an instance + * of this class. */ public final class BluetoothGattServer implements BluetoothProfile { private static final String TAG = "BluetoothGattServer"; private static final boolean DBG = true; + private static final boolean VDBG = false; private final Context mContext; private BluetoothAdapter mAdapter; @@ -59,6 +51,7 @@ private Object mServerIfLock = new Object(); private int mServerIf; + private int mTransport; private List<BluetoothGattService> mServices; private static final int CALLBACK_REG_TIMEOUT = 10000; @@ -91,7 +84,7 @@ * @hide */ public void onScanResult(String address, int rssi, byte[] advData) { - if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi); + if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi); // no op } @@ -141,7 +134,7 @@ ParcelUuid srvcId, int charInstId, ParcelUuid charId) { UUID srvcUuid = srvcId.getUuid(); UUID charUuid = charId.getUuid(); - if (DBG) Log.d(TAG, "onCharacteristicReadRequest() - " + if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - " + "service=" + srvcUuid + ", characteristic=" + charUuid); BluetoothDevice device = mAdapter.getRemoteDevice(address); @@ -169,7 +162,7 @@ UUID srvcUuid = srvcId.getUuid(); UUID charUuid = charId.getUuid(); UUID descrUuid = descrId.getUuid(); - if (DBG) Log.d(TAG, "onCharacteristicReadRequest() - " + if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - " + "service=" + srvcUuid + ", characteristic=" + charUuid + "descriptor=" + descrUuid); @@ -200,7 +193,7 @@ int charInstId, ParcelUuid charId, byte[] value) { UUID srvcUuid = srvcId.getUuid(); UUID charUuid = charId.getUuid(); - if (DBG) Log.d(TAG, "onCharacteristicWriteRequest() - " + if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - " + "service=" + srvcUuid + ", characteristic=" + charUuid); BluetoothDevice device = mAdapter.getRemoteDevice(address); @@ -231,7 +224,7 @@ UUID srvcUuid = srvcId.getUuid(); UUID charUuid = charId.getUuid(); UUID descrUuid = descrId.getUuid(); - if (DBG) Log.d(TAG, "onDescriptorWriteRequest() - " + if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - " + "service=" + srvcUuid + ", characteristic=" + charUuid + "descriptor=" + descrUuid); @@ -273,17 +266,36 @@ Log.w(TAG, "Unhandled exception in callback", ex); } } + + /** + * A notification/indication has been sent. + * @hide + */ + public void onNotificationSent(String address, int status) { + if (VDBG) Log.d(TAG, "onNotificationSent() - " + + "device=" + address + ", status=" + status); + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onNotificationSent(device, status); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception: " + ex); + } + } }; /** * Create a BluetoothGattServer proxy object. */ - /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt) { + /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt, int transport) { mContext = context; mService = iGatt; mAdapter = BluetoothAdapter.getDefaultAdapter(); mCallback = null; mServerIf = 0; + mTransport = transport; mServices = new ArrayList<BluetoothGattService>(); } @@ -410,7 +422,7 @@ try { mService.serverConnect(mServerIf, device.getAddress(), - autoConnect ? false : true); // autoConnect is inverse of "isDirect" + autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect" } catch (RemoteException e) { Log.e(TAG,"",e); return false; @@ -461,7 +473,7 @@ */ public boolean sendResponse(BluetoothDevice device, int requestId, int status, int offset, byte[] value) { - if (DBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress()); + if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress()); if (mService == null || mServerIf == 0) return false; try { @@ -489,16 +501,22 @@ * @param characteristic The local characteristic that has been updated * @param confirm true to request confirmation from the client (indication), * false to send a notification + * @throws IllegalArgumentException * @return true, if the notification has been triggered successfully */ public boolean notifyCharacteristicChanged(BluetoothDevice device, BluetoothGattCharacteristic characteristic, boolean confirm) { - if (DBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress()); + if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress()); if (mService == null || mServerIf == 0) return false; BluetoothGattService service = characteristic.getService(); if (service == null) return false; + if (characteristic.getValue() == null) { + throw new IllegalArgumentException("Chracteristic value is empty. Use " + + "BluetoothGattCharacteristic#setvalue to update"); + } + try { mService.sendNotification(mServerIf, device.getAddress(), service.getType(), service.getInstanceId(), @@ -516,7 +534,7 @@ /** * Add a service to the list of services to be hosted. * - * <p>Once a service has been addded to the the list, the service and it's + * <p>Once a service has been addded to the the list, the service and its * included characteristics will be provided by the local device. * * <p>If the local device has already exposed services when this function
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java index f9f1d97..1dd06f2 100644 --- a/core/java/android/bluetooth/BluetoothGattServerCallback.java +++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -18,8 +18,6 @@ import android.bluetooth.BluetoothDevice; -import android.util.Log; - /** * This abstract class is used to implement {@link BluetoothGattServer} callbacks. */ @@ -133,4 +131,18 @@ */ public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) { } + + /** + * Callback invoked when a notification or indication has been sent to + * a remote device. + * + * <p>When multiple notifications are to be sent, an application must + * wait for this callback to be received before sending additional + * notifications. + * + * @param device The remote device the notification has been sent to + * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful + */ + public void onNotificationSent(BluetoothDevice device, int status) { + } }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 8ee955d..353f0fb 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -280,7 +280,8 @@ Intent intent = new Intent(IBluetoothHeadset.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth Headset Service with " + intent); return false; } @@ -885,6 +886,50 @@ return false; } + /** + * enable WBS codec setting. + * + * @return true if successful + * false if there was some error such as + * there is no connected headset + * @hide + */ + public boolean enableWBS() { + if (mService != null && isEnabled()) { + try { + return mService.enableWBS(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * disable WBS codec settting. It set NBS codec. + * + * @return true if successful + * false if there was some error such as + * there is no connected headset + * @hide + */ + public boolean disableWBS() { + if (mService != null && isEnabled()) { + try { + return mService.disableWBS(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java new file mode 100644 index 0000000..ff4ebee --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -0,0 +1,1167 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * Public API to control Hands Free Profile (HFP role only). + * <p> + * This class defines methods that shall be used by application to manage profile + * connection, calls states and calls actions. + * <p> + * + * @hide + * */ +public final class BluetoothHeadsetClient implements BluetoothProfile { + private static final String TAG = "BluetoothHeadsetClient"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** + * Intent sent whenever connection to remote changes. + * + * <p>It includes two extras: + * <code>BluetoothProfile.EXTRA_PREVIOUS_STATE</code> + * and <code>BluetoothProfile.EXTRA_STATE</code>, which + * are mandatory. + * <p>There are also non mandatory feature extras: + * {@link #EXTRA_AG_FEATURE_3WAY_CALLING}, + * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}, + * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}, + * {@link #EXTRA_AG_FEATURE_REJECT_CALL}, + * {@link #EXTRA_AG_FEATURE_ECC}, + * {@link #EXTRA_AG_FEATURE_RESPONSE_AND_HOLD}, + * {@link #EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL}, + * {@link #EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL}, + * {@link #EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT}, + * {@link #EXTRA_AG_FEATURE_MERGE}, + * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH}, + * sent as boolean values only when <code>EXTRA_STATE</code> + * is set to <code>STATE_CONNECTED</code>.</p> + * + * <p>Note that features supported by AG are being sent as + * booleans with value <code>true</code>, + * and not supported ones are <strong>not</strong> being sent at all.</p> + */ + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED"; + + /** + * Intent sent whenever audio state changes. + * + * <p>It includes two mandatory extras: + * {@link BluetoothProfile.EXTRA_STATE}, + * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE}, + * with possible values: + * {@link #STATE_AUDIO_CONNECTING}, + * {@link #STATE_AUDIO_CONNECTED}, + * {@link #STATE_AUDIO_DISCONNECTED}</p> + * <p>When <code>EXTRA_STATE</code> is set + * to </code>STATE_AUDIO_CONNECTED</code>, + * it also includes {@link #EXTRA_AUDIO_WBS} + * indicating wide band speech support.</p> + */ + public static final String ACTION_AUDIO_STATE_CHANGED = + "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED"; + + /** + * Intent sending updates of the Audio Gateway state. + * Each extra is being sent only when value it + * represents has been changed recently on AG. + * <p>It can contain one or more of the following extras: + * {@link #EXTRA_NETWORK_STATUS}, + * {@link #EXTRA_NETWORK_SIGNAL_STRENGTH}, + * {@link #EXTRA_NETWORK_ROAMING}, + * {@link #EXTRA_BATTERY_LEVEL}, + * {@link #EXTRA_OPERATOR_NAME}, + * {@link #EXTRA_VOICE_RECOGNITION}, + * {@link #EXTRA_IN_BAND_RING}</p> + */ + public static final String ACTION_AG_EVENT = + "android.bluetooth.headsetclient.profile.action.AG_EVENT"; + + /** + * Intent sent whenever state of a call changes. + * + * <p>It includes: + * {@link #EXTRA_CALL}, + * with value of {@link BluetoothHeadsetClientCall} instance, + * representing actual call state.</p> + */ + public static final String ACTION_CALL_CHANGED = + "android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED"; + + /** + * Intent that notifies about the result of the last issued action. + * Please note that not every action results in explicit action result code being sent. + * Instead other notifications about new Audio Gateway state might be sent, + * like <code>ACTION_AG_EVENT</code> with <code>EXTRA_VOICE_RECOGNITION</code> value + * when for example user started voice recognition from HF unit. + */ + public static final String ACTION_RESULT = + "android.bluetooth.headsetclient.profile.action.RESULT"; + + /** + * Intent that notifies about the number attached to the last voice tag + * recorded on AG. + * + * <p>It contains: + * {@link #EXTRA_NUMBER}, + * with a <code>String</code> value representing phone number.</p> + */ + public static final String ACTION_LAST_VTAG = + "android.bluetooth.headsetclient.profile.action.LAST_VTAG"; + + public static final int STATE_AUDIO_DISCONNECTED = 0; + public static final int STATE_AUDIO_CONNECTING = 1; + public static final int STATE_AUDIO_CONNECTED = 2; + + /** + * Extra with information if connected audio is WBS. + * <p>Possible values: <code>true</code>, + * <code>false</code>.</p> + */ + public static final String EXTRA_AUDIO_WBS = + "android.bluetooth.headsetclient.extra.AUDIO_WBS"; + + /** + * Extra for AG_EVENT indicates network status. + * <p>Value: 0 - network unavailable, + * 1 - network available </p> + */ + public static final String EXTRA_NETWORK_STATUS = + "android.bluetooth.headsetclient.extra.NETWORK_STATUS"; + /** + * Extra for AG_EVENT intent indicates network signal strength. + * <p>Value: <code>Integer</code> representing signal strength.</p> + */ + public static final String EXTRA_NETWORK_SIGNAL_STRENGTH = + "android.bluetooth.headsetclient.extra.NETWORK_SIGNAL_STRENGTH"; + /** + * Extra for AG_EVENT intent indicates roaming state. + * <p>Value: 0 - no roaming + * 1 - active roaming</p> + */ + public static final String EXTRA_NETWORK_ROAMING = + "android.bluetooth.headsetclient.extra.NETWORK_ROAMING"; + /** + * Extra for AG_EVENT intent indicates the battery level. + * <p>Value: <code>Integer</code> representing signal strength.</p> + */ + public static final String EXTRA_BATTERY_LEVEL = + "android.bluetooth.headsetclient.extra.BATTERY_LEVEL"; + /** + * Extra for AG_EVENT intent indicates operator name. + * <p>Value: <code>String</code> representing operator name.</p> + */ + public static final String EXTRA_OPERATOR_NAME = + "android.bluetooth.headsetclient.extra.OPERATOR_NAME"; + /** + * Extra for AG_EVENT intent indicates voice recognition state. + * <p>Value: + * 0 - voice recognition stopped, + * 1 - voice recognition started.</p> + */ + public static final String EXTRA_VOICE_RECOGNITION = + "android.bluetooth.headsetclient.extra.VOICE_RECOGNITION"; + /** + * Extra for AG_EVENT intent indicates in band ring state. + * <p>Value: + * 0 - in band ring tone not supported, or + * 1 - in band ring tone supported.</p> + */ + public static final String EXTRA_IN_BAND_RING = + "android.bluetooth.headsetclient.extra.IN_BAND_RING"; + + /** + * Extra for AG_EVENT intent indicates subscriber info. + * <p>Value: <code>String</code> containing subscriber information.</p> + */ + public static final String EXTRA_SUBSCRIBER_INFO = + "android.bluetooth.headsetclient.extra.SUBSCRIBER_INFO"; + + /** + * Extra for AG_CALL_CHANGED intent indicates the + * {@link BluetoothHeadsetClientCall} object that has changed. + */ + public static final String EXTRA_CALL = + "android.bluetooth.headsetclient.extra.CALL"; + + /** + * Extra for ACTION_LAST_VTAG intent. + * <p>Value: <code>String</code> representing phone number + * corresponding to last voice tag recorded on AG</p> + */ + public static final String EXTRA_NUMBER = + "android.bluetooth.headsetclient.extra.NUMBER"; + + /** + * Extra for ACTION_RESULT intent that shows the result code of + * last issued action. + * <p>Possible results: + * {@link #ACTION_RESULT_OK}, + * {@link #ACTION_RESULT_ERROR}, + * {@link #ACTION_RESULT_ERROR_NO_CARRIER}, + * {@link #ACTION_RESULT_ERROR_BUSY}, + * {@link #ACTION_RESULT_ERROR_NO_ANSWER}, + * {@link #ACTION_RESULT_ERROR_DELAYED}, + * {@link #ACTION_RESULT_ERROR_BLACKLISTED}, + * {@link #ACTION_RESULT_ERROR_CME}</p> + */ + public static final String EXTRA_RESULT_CODE = + "android.bluetooth.headsetclient.extra.RESULT_CODE"; + + /** + * Extra for ACTION_RESULT intent that shows the extended result code of + * last issued action. + * <p>Value: <code>Integer</code> - error code.</p> + */ + public static final String EXTRA_CME_CODE = + "android.bluetooth.headsetclient.extra.CME_CODE"; + + /* Extras for AG_FEATURES, extras type is boolean */ + // TODO verify if all of those are actually useful + /** + * AG feature: three way calling. + */ + public final static String EXTRA_AG_FEATURE_3WAY_CALLING = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_3WAY_CALLING"; + /** + * AG feature: voice recognition. + */ + public final static String EXTRA_AG_FEATURE_VOICE_RECOGNITION = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_VOICE_RECOGNITION"; + /** + * AG feature: fetching phone number for voice tagging procedure. + */ + public final static String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT"; + /** + * AG feature: ability to reject incoming call. + */ + public final static String EXTRA_AG_FEATURE_REJECT_CALL = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_REJECT_CALL"; + /** + * AG feature: enhanced call handling (terminate specific call, private consultation). + */ + public final static String EXTRA_AG_FEATURE_ECC = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ECC"; + /** + * AG feature: response and hold. + */ + public final static String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RESPONSE_AND_HOLD"; + /** + * AG call handling feature: accept held or waiting call in three way calling scenarios. + */ + public final static String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL"; + /** + * AG call handling feature: release held or waiting call in three way calling scenarios. + */ + public final static String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL"; + /** + * AG call handling feature: release active call and accept held or waiting call in three way + * calling scenarios. + */ + public final static String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT"; + /** + * AG call handling feature: merge two calls, held and active - multi party conference mode. + */ + public final static String EXTRA_AG_FEATURE_MERGE = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE"; + /** + * AG call handling feature: merge calls and disconnect from multi party + * conversation leaving peers connected to each other. + * Note that this feature needs to be supported by mobile network operator + * as it requires connection and billing transfer. + */ + public final static String EXTRA_AG_FEATURE_MERGE_AND_DETACH = + "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE_AND_DETACH"; + + /* Action result codes */ + public final static int ACTION_RESULT_OK = 0; + public final static int ACTION_RESULT_ERROR = 1; + public final static int ACTION_RESULT_ERROR_NO_CARRIER = 2; + public final static int ACTION_RESULT_ERROR_BUSY = 3; + public final static int ACTION_RESULT_ERROR_NO_ANSWER = 4; + public final static int ACTION_RESULT_ERROR_DELAYED = 5; + public final static int ACTION_RESULT_ERROR_BLACKLISTED = 6; + public final static int ACTION_RESULT_ERROR_CME = 7; + + /* Detailed CME error codes */ + public final static int CME_PHONE_FAILURE = 0; + public final static int CME_NO_CONNECTION_TO_PHONE = 1; + public final static int CME_OPERATION_NOT_ALLOWED = 3; + public final static int CME_OPERATION_NOT_SUPPORTED = 4; + public final static int CME_PHSIM_PIN_REQUIRED = 5; + public final static int CME_PHFSIM_PIN_REQUIRED = 6; + public final static int CME_PHFSIM_PUK_REQUIRED = 7; + public final static int CME_SIM_NOT_INSERTED = 10; + public final static int CME_SIM_PIN_REQUIRED = 11; + public final static int CME_SIM_PUK_REQUIRED = 12; + public final static int CME_SIM_FAILURE = 13; + public final static int CME_SIM_BUSY = 14; + public final static int CME_SIM_WRONG = 15; + public final static int CME_INCORRECT_PASSWORD = 16; + public final static int CME_SIM_PIN2_REQUIRED = 17; + public final static int CME_SIM_PUK2_REQUIRED = 18; + public final static int CME_MEMORY_FULL = 20; + public final static int CME_INVALID_INDEX = 21; + public final static int CME_NOT_FOUND = 22; + public final static int CME_MEMORY_FAILURE = 23; + public final static int CME_TEXT_STRING_TOO_LONG = 24; + public final static int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25; + public final static int CME_DIAL_STRING_TOO_LONG = 26; + public final static int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27; + public final static int CME_NO_NETWORK_SERVICE = 30; + public final static int CME_NETWORK_TIMEOUT = 31; + public final static int CME_EMERGENCY_SERVICE_ONLY = 32; + public final static int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33; + public final static int CME_NOT_SUPPORTED_FOR_VOIP = 34; + public final static int CME_SIP_RESPONSE_CODE = 35; + public final static int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40; + public final static int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41; + public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42; + public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43; + public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44; + public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45; + public final static int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46; + public final static int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47; + public final static int CME_HIDDEN_KEY_REQUIRED = 48; + public final static int CME_EAP_NOT_SUPPORTED = 49; + public final static int CME_INCORRECT_PARAMETERS = 50; + + /* Action policy for other calls when accepting call */ + public static final int CALL_ACCEPT_NONE = 0; + public static final int CALL_ACCEPT_HOLD = 1; + public static final int CALL_ACCEPT_TERMINATE = 2; + + private Context mContext; + private ServiceListener mServiceListener; + private IBluetoothHeadsetClient mService; + private BluetoothAdapter mAdapter; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + @Override + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + Intent intent = new Intent(IBluetoothHeadsetClient.class.getName()); + doBind(); + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + + /** + * Create a BluetoothHeadsetClient proxy object. + */ + /*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothHeadsetClient.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent); + return false; + } + return true; + } + + /** + * Close the connection to the backing service. + * Other public functions of BluetoothHeadsetClient will return default error + * results once close() has been called. Multiple invocations of close() + * are ok. + */ + /*package*/ void close() { + if (VDBG) log("close()"); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + mServiceListener = null; + } + + /** + * Connects to remote device. + * + * Currently, the system supports only 1 connection. So, in case of the + * second connection, this implementation will disconnect already connected + * device automatically and will process the new one. + * + * @param device a remote device we want connect to + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} + * intent. + */ + public boolean connect(BluetoothDevice device) { + if (DBG) log("connect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.connect(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Disconnects remote device + * + * @param device a remote device we want disconnect + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} + * intent. + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Return the list of connected remote devices + * + * @return list of connected devices; empty list if nothing is connected. + */ + @Override + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * Returns list of remote devices in a particular state + * + * @param states collection of states + * @return list of devices that state matches the states listed in + * <code>states</code>; empty list if nothing matches the + * <code>states</code> + */ + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * Returns state of the <code>device</code> + * + * @param device a remote device + * @return the state of connection of the device + */ + @Override + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getConnectionState(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + /** + * Set priority of the profile + * + * The device should already be paired. + */ + public boolean setPriority(BluetoothDevice device, int priority) { + if (DBG) log("setPriority(" + device + ", " + priority + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF && + priority != BluetoothProfile.PRIORITY_ON) { + return false; + } + try { + return mService.setPriority(device, priority); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Get the priority of the profile. + */ + public int getPriority(BluetoothDevice device) { + if (VDBG) log("getPriority(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getPriority(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return PRIORITY_OFF; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return PRIORITY_OFF; + } + + /** + * Starts voice recognition. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_AG_EVENT} + * intent. + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean startVoiceRecognition(BluetoothDevice device) { + if (DBG) log("startVoiceRecognition()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.startVoiceRecognition(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Stops voice recognition. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_AG_EVENT} + * intent. + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean stopVoiceRecognition(BluetoothDevice device) { + if (DBG) log("stopVoiceRecognition()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.stopVoiceRecognition(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Returns list of all calls in any state. + * + * @param device remote device + * @return list of calls; empty list if none call exists + */ + public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { + if (DBG) log("getCurrentCalls()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getCurrentCalls(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } + + /** + * Returns list of current values of AG indicators. + * + * @param device remote device + * @return bundle of AG indicators; null if device is not in + * CONNECTED state + */ + public Bundle getCurrentAgEvents(BluetoothDevice device) { + if (DBG) log("getCurrentCalls()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getCurrentAgEvents(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } + + /** + * Accepts a call + * + * @param device remote device + * @param flag action policy while accepting a call. Possible values + * {@link #CALL_ACCEPT_NONE}, {@link #CALL_ACCEPT_HOLD}, + * {@link #CALL_ACCEPT_TERMINATE} + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + */ + public boolean acceptCall(BluetoothDevice device, int flag) { + if (DBG) log("acceptCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.acceptCall(device, flag); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Holds a call. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + */ + public boolean holdCall(BluetoothDevice device) { + if (DBG) log("holdCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.holdCall(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Rejects a call. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_REJECT_CALL}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean rejectCall(BluetoothDevice device) { + if (DBG) log("rejectCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.rejectCall(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Terminates a specified call. + * + * Works only when Extended Call Control is supported by Audio Gateway. + * + * @param device remote device + * @param index index of the call to be terminated + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_ECC}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean terminateCall(BluetoothDevice device, int index) { + if (DBG) log("terminateCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.terminateCall(device, index); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Enters private mode with a specified call. + * + * Works only when Extended Call Control is supported by Audio Gateway. + * + * @param device remote device + * @param index index of the call to connect in private mode + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_ECC}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean enterPrivateMode(BluetoothDevice device, int index) { + if (DBG) log("enterPrivateMode()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.enterPrivateMode(device, index); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Performs explicit call transfer. + * + * That means connect other calls and disconnect. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean explicitCallTransfer(BluetoothDevice device) { + if (DBG) log("explicitCallTransfer()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.explicitCallTransfer(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Redials last number from Audio Gateway. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent in case of success; {@link #ACTION_RESULT} is sent + * otherwise; + */ + public boolean redial(BluetoothDevice device) { + if (DBG) log("redial()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.redial(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Places a call with specified number. + * + * @param device remote device + * @param number valid phone number + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent in case of success; {@link #ACTION_RESULT} is sent + * otherwise; + */ + public boolean dial(BluetoothDevice device, String number) { + if (DBG) log("dial()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.dial(device, number); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Places a call to the number under specified memory location. + * + * @param device remote device + * @param location valid memory location + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent in case of success; {@link #ACTION_RESULT} is sent + * otherwise; + */ + public boolean dialMemory(BluetoothDevice device, int location) { + if (DBG) log("dialMemory()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.dialMemory(device, location); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Sends DTMF code. + * + * Possible code values : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,# + * + * @param device remote device + * @param code ASCII code + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_RESULT} intent; + */ + public boolean sendDTMF(BluetoothDevice device, byte code) { + if (DBG) log("sendDTMF()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.sendDTMF(device, code); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Get a number corresponding to last voice tag recorded on AG. + * + * @param device remote device + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_LAST_VTAG} + * or {@link #ACTION_RESULT} intent; + * + * <p>Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}. + * This method invocation will fail silently when feature is not supported.</p> + */ + public boolean getLastVoiceTagNumber(BluetoothDevice device) { + if (DBG) log("getLastVoiceTagNumber()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getLastVoiceTagNumber(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Accept the incoming connection. + */ + public boolean acceptIncomingConnect(BluetoothDevice device) { + if (DBG) log("acceptIncomingConnect"); + if (mService != null && isEnabled()) { + try { + return mService.acceptIncomingConnect(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Reject the incoming connection. + */ + public boolean rejectIncomingConnect(BluetoothDevice device) { + if (DBG) log("rejectIncomingConnect"); + if (mService != null) { + try { + return mService.rejectIncomingConnect(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Returns current audio state of Audio Gateway. + * + * Note: This is an internal function and shouldn't be exposed + */ + public int getAudioState(BluetoothDevice device) { + if (VDBG) log("getAudioState"); + if (mService != null && isEnabled()) { + try { + return mService.getAudioState(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; + } + + /** + * Initiates a connection of audio channel. + * + * It setup SCO channel with remote connected Handsfree AG device. + * + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} + * intent; + */ + public boolean connectAudio() { + if (mService != null && isEnabled()) { + try { + return mService.connectAudio(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Disconnects audio channel. + * + * It tears down the SCO channel from remote AG device. + * + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} + * intent; + */ + public boolean disconnectAudio() { + if (mService != null && isEnabled()) { + try { + return mService.disconnectAudio(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Get Audio Gateway features + * + * @param device remote device + * @return bundle of AG features; null if no service or + * AG not connected + */ + public Bundle getCurrentAgFeatures(BluetoothDevice device) { + if (mService != null && isEnabled()) { + try { + return mService.getCurrentAgFeatures(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return null; + } + + + private ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "Proxy object connected"); + mService = IBluetoothHeadsetClient.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT, + BluetoothHeadsetClient.this); + } + } + @Override + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl b/core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl new file mode 100644 index 0000000..35f7923 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl
@@ -0,0 +1,18 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +parcelable BluetoothHeadsetClientCall;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java new file mode 100644 index 0000000..a15bd97 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -0,0 +1,218 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class represents a single call, its state and properties. + * It implements {@link Parcelable} for inter-process message passing. + * @hide + */ +public final class BluetoothHeadsetClientCall implements Parcelable { + + /* Call state */ + /** + * Call is active. + */ + public static final int CALL_STATE_ACTIVE = 0; + /** + * Call is in held state. + */ + public static final int CALL_STATE_HELD = 1; + /** + * Outgoing call that is being dialed right now. + */ + public static final int CALL_STATE_DIALING = 2; + /** + * Outgoing call that remote party has already been alerted about. + */ + public static final int CALL_STATE_ALERTING = 3; + /** + * Incoming call that can be accepted or rejected. + */ + public static final int CALL_STATE_INCOMING = 4; + /** + * Waiting call state when there is already an active call. + */ + public static final int CALL_STATE_WAITING = 5; + /** + * Call that has been held by response and hold + * (see Bluetooth specification for further references). + */ + public static final int CALL_STATE_HELD_BY_RESPONSE_AND_HOLD = 6; + /** + * Call that has been already terminated and should not be referenced as a valid call. + */ + public static final int CALL_STATE_TERMINATED = 7; + + private final int mId; + private int mState; + private String mNumber; + private boolean mMultiParty; + private final boolean mOutgoing; + + /** + * Creates BluetoothHeadsetClientCall instance. + */ + public BluetoothHeadsetClientCall(int id, int state, String number, boolean multiParty, + boolean outgoing) { + mId = id; + mState = state; + mNumber = number != null ? number : ""; + mMultiParty = multiParty; + mOutgoing = outgoing; + } + + /** + * Sets call's state. + * + * <p>Note: This is an internal function and shouldn't be exposed</p> + * + * @param state new call state. + */ + public void setState(int state) { + mState = state; + } + + /** + * Sets call's number. + * + * <p>Note: This is an internal function and shouldn't be exposed</p> + * + * @param number String representing phone number. + */ + public void setNumber(String number) { + mNumber = number; + } + + /** + * Sets this call as multi party call. + * + * <p>Note: This is an internal function and shouldn't be exposed</p> + * + * @param multiParty if <code>true</code> sets this call as a part + * of multi party conference. + */ + public void setMultiParty(boolean multiParty) { + mMultiParty = multiParty; + } + + /** + * Gets call's Id. + * + * @return call id. + */ + public int getId() { + return mId; + } + + /** + * Gets call's current state. + * + * @return state of this particular phone call. + */ + public int getState() { + return mState; + } + + /** + * Gets call's number. + * + * @return string representing phone number. + */ + public String getNumber() { + return mNumber; + } + + /** + * Checks if call is an active call in a conference mode (aka multi party). + * + * @return <code>true</code> if call is a multi party call, + * <code>false</code> otherwise. + */ + public boolean isMultiParty() { + return mMultiParty; + } + + /** + * Checks if this call is an outgoing call. + * + * @return <code>true</code> if its outgoing call, + * <code>false</code> otherwise. + */ + public boolean isOutgoing() { + return mOutgoing; + } + + public String toString() { + StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mId: "); + builder.append(mId); + builder.append(", mState: "); + switch (mState) { + case CALL_STATE_ACTIVE: builder.append("ACTIVE"); break; + case CALL_STATE_HELD: builder.append("HELD"); break; + case CALL_STATE_DIALING: builder.append("DIALING"); break; + case CALL_STATE_ALERTING: builder.append("ALERTING"); break; + case CALL_STATE_INCOMING: builder.append("INCOMING"); break; + case CALL_STATE_WAITING: builder.append("WAITING"); break; + case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD: builder.append("HELD_BY_RESPONSE_AND_HOLD"); break; + case CALL_STATE_TERMINATED: builder.append("TERMINATED"); break; + default: builder.append(mState); break; + } + builder.append(", mNumber: "); + builder.append(mNumber); + builder.append(", mMultiParty: "); + builder.append(mMultiParty); + builder.append(", mOutgoing: "); + builder.append(mOutgoing); + builder.append("}"); + return builder.toString(); + } + + /** + * {@link Parcelable.Creator} interface implementation. + */ + public static final Parcelable.Creator<BluetoothHeadsetClientCall> CREATOR = + new Parcelable.Creator<BluetoothHeadsetClientCall>() { + @Override + public BluetoothHeadsetClientCall createFromParcel(Parcel in) { + return new BluetoothHeadsetClientCall(in.readInt(), in.readInt(), + in.readString(), in.readInt() == 1, in.readInt() == 1); + } + + @Override + public BluetoothHeadsetClientCall[] newArray(int size) { + return new BluetoothHeadsetClientCall[size]; + } + }; + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mId); + out.writeInt(mState); + out.writeString(mNumber); + out.writeInt(mMultiParty ? 1 : 0); + out.writeInt(mOutgoing ? 1 : 0); + } + + @Override + public int describeContents() { + return 0; + } +}
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java index 2e950fae..4949c24 100644 --- a/core/java/android/bluetooth/BluetoothHealth.java +++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -23,7 +23,6 @@ import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.util.ArrayList; @@ -488,7 +487,8 @@ Intent intent = new Intent(IBluetoothHealth.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth Health Service with " + intent); return false; }
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index c48b15d..252e3d2 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -24,7 +24,6 @@ import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.util.ArrayList; @@ -260,7 +259,8 @@ Intent intent = new Intent(IBluetoothInputDevice.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent); return false; } @@ -640,7 +640,7 @@ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * * @param device Remote Bluetooth Device - * @param data Data to send + * @param report Report to send * @return false on immediate error, * true otherwise * @hide
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java index 172f3bc..b1618cf3 100644 --- a/core/java/android/bluetooth/BluetoothManager.java +++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -194,6 +194,26 @@ */ public BluetoothGattServer openGattServer(Context context, BluetoothGattServerCallback callback) { + + return (openGattServer (context, callback, BluetoothDevice.TRANSPORT_AUTO)); + } + + /** + * Open a GATT Server + * The callback is used to deliver results to Caller, such as connection status as well + * as the results of any other GATT server operations. + * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer + * to conduct GATT server operations. + * @param context App context + * @param callback GATT server callback handler that will receive asynchronous callbacks. + * @param transport preferred transport for GATT connections to remote dual-mode devices + * {@link BluetoothDevice#TRANSPORT_AUTO} or + * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} + * @return BluetoothGattServer instance + * @hide + */ + public BluetoothGattServer openGattServer(Context context, + BluetoothGattServerCallback callback,int transport) { if (context == null || callback == null) { throw new IllegalArgumentException("null parameter: " + context + " " + callback); } @@ -208,7 +228,7 @@ Log.e(TAG, "Fail to get GATT Server connection"); return null; } - BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt); + BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt,transport); Boolean regStatus = mGattServer.registerCallback(callback); return regStatus? mGattServer : null; } catch (RemoteException e) {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index 92a2f1e..7f57acf 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -22,9 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.RemoteException; -import android.os.IBinder; -import android.os.ServiceManager; +import android.os.*; import android.util.Log; /** @@ -106,7 +104,8 @@ Intent intent = new Intent(IBluetoothMap.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); return false; }
diff --git a/core/java/android/bluetooth/BluetoothMasInstance.java b/core/java/android/bluetooth/BluetoothMasInstance.java new file mode 100644 index 0000000..4459e2c --- /dev/null +++ b/core/java/android/bluetooth/BluetoothMasInstance.java
@@ -0,0 +1,103 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +/** @hide */ +public final class BluetoothMasInstance implements Parcelable { + private final int mId; + private final String mName; + private final int mChannel; + private final int mMsgTypes; + + public BluetoothMasInstance(int id, String name, int channel, int msgTypes) { + mId = id; + mName = name; + mChannel = channel; + mMsgTypes = msgTypes; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BluetoothMasInstance) { + return mId == ((BluetoothMasInstance)o).mId; + } + return false; + } + + @Override + public int hashCode() { + return mId + (mChannel << 8) + (mMsgTypes << 16); + } + + @Override + public String toString() { + return Integer.toString(mId) + ":" + mName + ":" + mChannel + ":" + + Integer.toHexString(mMsgTypes); + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<BluetoothMasInstance> CREATOR = + new Parcelable.Creator<BluetoothMasInstance>() { + public BluetoothMasInstance createFromParcel(Parcel in) { + return new BluetoothMasInstance(in.readInt(), in.readString(), + in.readInt(), in.readInt()); + } + public BluetoothMasInstance[] newArray(int size) { + return new BluetoothMasInstance[size]; + } + }; + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mId); + out.writeString(mName); + out.writeInt(mChannel); + out.writeInt(mMsgTypes); + } + + public static final class MessageType { + public static final int EMAIL = 0x01; + public static final int SMS_GSM = 0x02; + public static final int SMS_CDMA = 0x04; + public static final int MMS = 0x08; + } + + public int getId() { + return mId; + } + + public String getName() { + return mName; + } + + public int getChannel() { + return mChannel; + } + + public int getMsgTypes() { + return mMsgTypes; + } + + public boolean msgSupported(int msg) { + return (mMsgTypes & msg) != 0; + } +}
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index b7a37f4..4f81f98 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -24,7 +24,6 @@ import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.util.ArrayList; @@ -146,7 +145,8 @@ Intent intent = new Intent(IBluetoothPan.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent); return false; }
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index 7f45652..dc01fc7 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -22,7 +22,6 @@ import android.content.ServiceConnection; import android.os.RemoteException; import android.os.IBinder; -import android.os.ServiceManager; import android.util.Log; /** @@ -161,7 +160,8 @@ Intent intent = new Intent(IBluetoothPbap.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent); return false; }
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 1574090..1367405 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2010-2014 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. @@ -104,6 +104,24 @@ public static final int MAP = 9; /** + * A2DP Sink Profile + * @hide + */ + public static final int A2DP_SINK = 10; + + /** + * AVRCP Controller Profile + * @hide + */ + public static final int AVRCP_CONTROLLER = 11; + + /** + * Headset Client - HFP HF Role + * @hide + */ + public static final int HEADSET_CLIENT = 16; + + /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile * @hide
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java index 96be8a2..bc56e55 100644 --- a/core/java/android/bluetooth/BluetoothServerSocket.java +++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -17,7 +17,6 @@ package android.bluetooth; import android.os.Handler; -import android.os.Message; import android.os.ParcelUuid; import java.io.Closeable;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 5738b9a..36997e5 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -16,21 +16,16 @@ package android.bluetooth; -import android.os.IBinder; import android.os.ParcelUuid; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; import java.io.Closeable; import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.List; import java.util.Locale; import java.util.UUID; import android.net.LocalSocket; @@ -330,6 +325,7 @@ } } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); + throw new IOException("unable to send RPC: " + e.getMessage()); } } @@ -379,6 +375,14 @@ } // else ASSERT(mPort == channel) ret = 0; } catch (IOException e) { + if (mPfd != null) { + try { + mPfd.close(); + } catch (IOException e1) { + Log.e(TAG, "bindListen, close mPfd: " + e1); + } + mPfd = null; + } Log.e(TAG, "bindListen, fail to get port number, exception: " + e); return -1; } @@ -462,8 +466,10 @@ mSocket.close(); mSocket = null; } - if(mPfd != null) - mPfd.detachFd(); + if (mPfd != null) { + mPfd.close(); + mPfd = null; + } } } }
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java deleted file mode 100644 index fe5e52b..0000000 --- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java +++ /dev/null
@@ -1,441 +0,0 @@ -/* - * Copyright (C) 2010 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.bluetooth; - -import android.net.BaseNetworkStateTracker; -import android.os.IBinder; -import android.os.ServiceManager; -import android.os.INetworkManagementService; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.DhcpResults; -import android.net.LinkCapabilities; -import android.net.LinkProperties; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkStateTracker; -import android.net.NetworkUtils; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.text.TextUtils; -import android.util.Log; -import java.net.InterfaceAddress; -import android.net.LinkAddress; -import android.net.RouteInfo; -import java.net.Inet4Address; -import android.os.SystemProperties; - -import com.android.internal.util.AsyncChannel; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -/** - * This class tracks the data connection associated with Bluetooth - * reverse tethering. This is a singleton class and an instance will be - * created by ConnectivityService. BluetoothService will call into this - * when a reverse tethered connection needs to be activated. - * - * @hide - */ -public class BluetoothTetheringDataTracker extends BaseNetworkStateTracker { - private static final String NETWORKTYPE = "BLUETOOTH_TETHER"; - private static final String TAG = "BluetoothTethering"; - private static final boolean DBG = true; - private static final boolean VDBG = true; - - // Event sent to the mBtdtHandler when DHCP fails so we can tear down the network. - private static final int EVENT_NETWORK_FAILED = 1; - - private AtomicBoolean mTeardownRequested = new AtomicBoolean(false); - private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false); - private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0); - private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false); - - private final Object mLinkPropertiesLock = new Object(); - private final Object mNetworkInfoLock = new Object(); - - private BluetoothPan mBluetoothPan; - private static String mRevTetheredIface; - /* For sending events to connectivity service handler */ - private Handler mCsHandler; - private static BluetoothTetheringDataTracker sInstance; - private BtdtHandler mBtdtHandler; - private AtomicReference<AsyncChannel> mAsyncChannel = new AtomicReference<AsyncChannel>(null); - - private BluetoothTetheringDataTracker() { - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, ""); - mLinkProperties = new LinkProperties(); - mLinkCapabilities = new LinkCapabilities(); - - mNetworkInfo.setIsAvailable(false); - setTeardownRequested(false); - } - - public static synchronized BluetoothTetheringDataTracker getInstance() { - if (sInstance == null) sInstance = new BluetoothTetheringDataTracker(); - return sInstance; - } - - public Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } - - public void setTeardownRequested(boolean isRequested) { - mTeardownRequested.set(isRequested); - } - - public boolean isTeardownRequested() { - return mTeardownRequested.get(); - } - - /** - * Begin monitoring connectivity - */ - public void startMonitoring(Context context, Handler target) { - if (DBG) Log.d(TAG, "startMonitoring: target: " + target); - mContext = context; - mCsHandler = target; - if (VDBG) Log.d(TAG, "startMonitoring: mCsHandler: " + mCsHandler); - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter != null) { - adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN); - } - mBtdtHandler = new BtdtHandler(target.getLooper(), this); - } - - private BluetoothProfile.ServiceListener mProfileServiceListener = - new BluetoothProfile.ServiceListener() { - public void onServiceConnected(int profile, BluetoothProfile proxy) { - mBluetoothPan = (BluetoothPan) proxy; - } - public void onServiceDisconnected(int profile) { - mBluetoothPan = null; - } - }; - - /** - * Disable connectivity to a network - * TODO: do away with return value after making MobileDataStateTracker async - */ - public boolean teardown() { - mTeardownRequested.set(true); - if (mBluetoothPan != null) { - for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) { - mBluetoothPan.disconnect(device); - } - } - return true; - } - - @Override - public void captivePortalCheckComplete() { - // not implemented - } - - @Override - public void captivePortalCheckCompleted(boolean isCaptivePortal) { - // not implemented - } - - /** - * Re-enable connectivity to a network after a {@link #teardown()}. - */ - public boolean reconnect() { - mTeardownRequested.set(false); - //Ignore - return true; - } - - /** - * Turn the wireless radio off for a network. - * @param turnOn {@code true} to turn the radio on, {@code false} - */ - public boolean setRadio(boolean turnOn) { - return true; - } - - /** - * @return true - If are we currently tethered with another device. - */ - public synchronized boolean isAvailable() { - return mNetworkInfo.isAvailable(); - } - - /** - * Tells the underlying networking system that the caller wants to - * begin using the named feature. The interpretation of {@code feature} - * is completely up to each networking implementation. - * @param feature the name of the feature to be used - * @param callingPid the process ID of the process that is issuing this request - * @param callingUid the user ID of the process that is issuing this request - * @return an integer value representing the outcome of the request. - * The interpretation of this value is specific to each networking - * implementation+feature combination, except that the value {@code -1} - * always indicates failure. - * TODO: needs to go away - */ - public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) { - return -1; - } - - /** - * Tells the underlying networking system that the caller is finished - * using the named feature. The interpretation of {@code feature} - * is completely up to each networking implementation. - * @param feature the name of the feature that is no longer needed. - * @param callingPid the process ID of the process that is issuing this request - * @param callingUid the user ID of the process that is issuing this request - * @return an integer value representing the outcome of the request. - * The interpretation of this value is specific to each networking - * implementation+feature combination, except that the value {@code -1} - * always indicates failure. - * TODO: needs to go away - */ - public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) { - return -1; - } - - @Override - public void setUserDataEnable(boolean enabled) { - Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")"); - } - - @Override - public void setPolicyDataEnable(boolean enabled) { - Log.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")"); - } - - /** - * Check if private DNS route is set for the network - */ - public boolean isPrivateDnsRouteSet() { - return mPrivateDnsRouteSet.get(); - } - - /** - * Set a flag indicating private DNS route is set - */ - public void privateDnsRouteSet(boolean enabled) { - mPrivateDnsRouteSet.set(enabled); - } - - /** - * Fetch NetworkInfo for the network - */ - public NetworkInfo getNetworkInfo() { - synchronized (mNetworkInfoLock) { - return new NetworkInfo(mNetworkInfo); - } - } - - /** - * Fetch LinkProperties for the network - */ - public LinkProperties getLinkProperties() { - synchronized (mLinkPropertiesLock) { - return new LinkProperties(mLinkProperties); - } - } - - /** - * A capability is an Integer/String pair, the capabilities - * are defined in the class LinkSocket#Key. - * - * @return a copy of this connections capabilities, may be empty but never null. - */ - public LinkCapabilities getLinkCapabilities() { - return new LinkCapabilities(mLinkCapabilities); - } - - /** - * Fetch default gateway address for the network - */ - public int getDefaultGatewayAddr() { - return mDefaultGatewayAddr.get(); - } - - /** - * Check if default route is set - */ - public boolean isDefaultRouteSet() { - return mDefaultRouteSet.get(); - } - - /** - * Set a flag indicating default route is set for the network - */ - public void defaultRouteSet(boolean enabled) { - mDefaultRouteSet.set(enabled); - } - - /** - * Return the system properties name associated with the tcp buffer sizes - * for this network. - */ - public String getTcpBufferSizesPropName() { - return "net.tcp.buffersize.wifi"; - } - - private static short countPrefixLength(byte [] mask) { - short count = 0; - for (byte b : mask) { - for (int i = 0; i < 8; ++i) { - if ((b & (1 << i)) != 0) { - ++count; - } - } - } - return count; - } - - void startReverseTether(final LinkProperties linkProperties) { - if (linkProperties == null || TextUtils.isEmpty(linkProperties.getInterfaceName())) { - Log.e(TAG, "attempted to reverse tether with empty interface"); - return; - } - synchronized (mLinkPropertiesLock) { - if (mLinkProperties.getInterfaceName() != null) { - Log.e(TAG, "attempted to reverse tether while already in process"); - return; - } - mLinkProperties = linkProperties; - } - Thread dhcpThread = new Thread(new Runnable() { - public void run() { - //Currently this thread runs independently. - DhcpResults dhcpResults = new DhcpResults(); - boolean success = NetworkUtils.runDhcp(linkProperties.getInterfaceName(), - dhcpResults); - synchronized (mLinkPropertiesLock) { - if (linkProperties.getInterfaceName() != mLinkProperties.getInterfaceName()) { - Log.e(TAG, "obsolete DHCP run aborted"); - return; - } - if (!success) { - Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); - mBtdtHandler.obtainMessage(EVENT_NETWORK_FAILED).sendToTarget(); - return; - } - mLinkProperties = dhcpResults.linkProperties; - synchronized (mNetworkInfoLock) { - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); - if (mCsHandler != null) { - Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, - new NetworkInfo(mNetworkInfo)); - msg.sendToTarget(); - } - } - return; - } - } - }); - dhcpThread.start(); - } - - void stopReverseTether() { - synchronized (mLinkPropertiesLock) { - if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) { - Log.e(TAG, "attempted to stop reverse tether with nothing tethered"); - return; - } - NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName()); - mLinkProperties.clear(); - synchronized (mNetworkInfoLock) { - mNetworkInfo.setIsAvailable(false); - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); - - if (mCsHandler != null) { - mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)). - sendToTarget(); - } - } - } - } - - public void setDependencyMet(boolean met) { - // not supported on this network - } - - @Override - public void addStackedLink(LinkProperties link) { - mLinkProperties.addStackedLink(link); - } - - @Override - public void removeStackedLink(LinkProperties link) { - mLinkProperties.removeStackedLink(link); - } - - static class BtdtHandler extends Handler { - private AsyncChannel mStackChannel; - private final BluetoothTetheringDataTracker mBtdt; - - BtdtHandler(Looper looper, BluetoothTetheringDataTracker parent) { - super(looper); - mBtdt = parent; - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (VDBG) Log.d(TAG, "got CMD_CHANNEL_HALF_CONNECTED"); - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - AsyncChannel ac = (AsyncChannel)msg.obj; - if (mBtdt.mAsyncChannel.compareAndSet(null, ac) == false) { - Log.e(TAG, "Trying to set mAsyncChannel twice!"); - } else { - ac.sendMessage( - AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); - } - } - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - if (VDBG) Log.d(TAG, "got CMD_CHANNEL_DISCONNECTED"); - mBtdt.stopReverseTether(); - mBtdt.mAsyncChannel.set(null); - break; - case NetworkStateTracker.EVENT_NETWORK_CONNECTED: - LinkProperties linkProperties = (LinkProperties)(msg.obj); - if (VDBG) Log.d(TAG, "got EVENT_NETWORK_CONNECTED, " + linkProperties); - mBtdt.startReverseTether(linkProperties); - break; - case NetworkStateTracker.EVENT_NETWORK_DISCONNECTED: - linkProperties = (LinkProperties)(msg.obj); - if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties); - mBtdt.stopReverseTether(); - break; - case EVENT_NETWORK_FAILED: - if (VDBG) Log.d(TAG, "got EVENT_NETWORK_FAILED"); - mBtdt.teardown(); - break; - } - } - } - - @Override - public void supplyMessenger(Messenger messenger) { - if (messenger != null) { - new AsyncChannel().connect(mContext, mBtdtHandler, messenger); - } - } -}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 4b28516..1e22eb3 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -18,6 +18,8 @@ import android.os.ParcelUuid; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Arrays; import java.util.HashSet; import java.util.UUID; @@ -76,6 +78,12 @@ public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); + /** Length of bytes for 16 bit UUID */ + public static final int UUID_BYTES_16_BIT = 2; + /** Length of bytes for 32 bit UUID */ + public static final int UUID_BYTES_32_BIT = 4; + /** Length of bytes for 128 bit UUID */ + public static final int UUID_BYTES_128_BIT = 16; public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, @@ -216,15 +224,78 @@ } /** + * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID, + * but the returned UUID is always in 128-bit format. + * Note UUID is little endian in Bluetooth. + * + * @param uuidBytes Byte representation of uuid. + * @return {@link ParcelUuid} parsed from bytes. + * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed. + */ + public static ParcelUuid parseUuidFrom(byte[] uuidBytes) { + if (uuidBytes == null) { + throw new IllegalArgumentException("uuidBytes cannot be null"); + } + int length = uuidBytes.length; + if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT && + length != UUID_BYTES_128_BIT) { + throw new IllegalArgumentException("uuidBytes length invalid - " + length); + } + + // Construct a 128 bit UUID. + if (length == UUID_BYTES_128_BIT) { + ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); + long msb = buf.getLong(8); + long lsb = buf.getLong(0); + return new ParcelUuid(new UUID(msb, lsb)); + } + + // For 16 bit and 32 bit UUID we need to convert them to 128 bit value. + // 128_bit_value = uuid * 2^96 + BASE_UUID + long shortUuid; + if (length == UUID_BYTES_16_BIT) { + shortUuid = uuidBytes[0] & 0xFF; + shortUuid += (uuidBytes[1] & 0xFF) << 8; + } else { + shortUuid = uuidBytes[0] & 0xFF ; + shortUuid += (uuidBytes[1] & 0xFF) << 8; + shortUuid += (uuidBytes[2] & 0xFF) << 16; + shortUuid += (uuidBytes[3] & 0xFF) << 24; + } + long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32); + long lsb = BASE_UUID.getUuid().getLeastSignificantBits(); + return new ParcelUuid(new UUID(msb, lsb)); + } + + /** * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. + * * @param parcelUuid * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. */ - public static boolean isShortUuid(ParcelUuid parcelUuid) { - UUID uuid = parcelUuid.getUuid(); - if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { - return false; - } - return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); + public static boolean is16BitUuid(ParcelUuid parcelUuid) { + UUID uuid = parcelUuid.getUuid(); + if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { + return false; + } + return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); + } + + + /** + * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid. + * + * @param parcelUuid + * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise. + */ + public static boolean is32BitUuid(ParcelUuid parcelUuid) { + UUID uuid = parcelUuid.getUuid(); + if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { + return false; + } + if (is16BitUuid(parcelUuid)) { + return false; + } + return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L); } }
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index 07db8cc..cf2a343 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -18,6 +18,7 @@ import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothStateChangeCallback; +import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothDevice; import android.os.ParcelUuid; import android.os.ParcelFileDescriptor; @@ -54,10 +55,11 @@ int getProfileConnectionState(int profile); BluetoothDevice[] getBondedDevices(); - boolean createBond(in BluetoothDevice device); + boolean createBond(in BluetoothDevice device, in int transport); boolean cancelBondProcess(in BluetoothDevice device); boolean removeBond(in BluetoothDevice device); int getBondState(in BluetoothDevice device); + boolean isConnected(in BluetoothDevice device); String getRemoteName(in BluetoothDevice device); int getRemoteType(in BluetoothDevice device); @@ -66,12 +68,18 @@ int getRemoteClass(in BluetoothDevice device); ParcelUuid[] getRemoteUuids(in BluetoothDevice device); boolean fetchRemoteUuids(in BluetoothDevice device); + boolean fetchRemoteMasInstances(in BluetoothDevice device); boolean setPin(in BluetoothDevice device, boolean accept, int len, in byte[] pinCode); boolean setPasskey(in BluetoothDevice device, boolean accept, int len, in byte[] passkey); boolean setPairingConfirmation(in BluetoothDevice device, boolean accept); + int getPhonebookAccessPermission(in BluetoothDevice device); + boolean setPhonebookAccessPermission(in BluetoothDevice device, int value); + int getMessageAccessPermission(in BluetoothDevice device); + boolean setMessageAccessPermission(in BluetoothDevice device, int value); + void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState); void registerCallback(in IBluetoothCallback callback); @@ -82,4 +90,11 @@ ParcelFileDescriptor createSocketChannel(int type, in String serviceName, in ParcelUuid uuid, int port, int flag); boolean configHciSnoopLog(boolean enable); + + boolean isMultiAdvertisementSupported(); + boolean isOffloadedFilteringSupported(); + boolean isOffloadedScanBatchingSupported(); + boolean isActivityAndEnergyReportingSupported(); + void getActivityEnergyInfoFromController(); + BluetoothActivityEnergyInfo reportActivityInfo(); }
diff --git a/core/java/android/bluetooth/IBluetoothA2dpSink.aidl b/core/java/android/bluetooth/IBluetoothA2dpSink.aidl new file mode 100644 index 0000000..b7c6476 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothA2dpSink.aidl
@@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.bluetooth.BluetoothAudioConfig; +import android.bluetooth.BluetoothDevice; + +/** + * APIs for Bluetooth A2DP sink service + * + * @hide + */ +interface IBluetoothA2dpSink { + boolean connect(in BluetoothDevice device); + boolean disconnect(in BluetoothDevice device); + List<BluetoothDevice> getConnectedDevices(); + List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); + BluetoothAudioConfig getAudioConfig(in BluetoothDevice device); +}
diff --git a/core/java/android/bluetooth/IBluetoothAvrcpController.aidl b/core/java/android/bluetooth/IBluetoothAvrcpController.aidl new file mode 100644 index 0000000..f917a50 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothAvrcpController.aidl
@@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.bluetooth.BluetoothDevice; + +/** + * APIs for Bluetooth AVRCP controller service + * + * @hide + */ +interface IBluetoothAvrcpController { + List<BluetoothDevice> getConnectedDevices(); + List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); + void sendPassThroughCmd(in BluetoothDevice device, int keyCode, int keyState); +}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index c6b5c3d..7070bae 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -17,6 +17,11 @@ package android.bluetooth; import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanSettings; +import android.bluetooth.le.ResultStorageDescriptor; import android.os.ParcelUuid; import android.bluetooth.IBluetoothGattCallback; @@ -29,23 +34,20 @@ interface IBluetoothGatt { List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); - void startScan(in int appIf, in boolean isServer); - void startScanWithUuids(in int appIf, in boolean isServer, in ParcelUuid[] ids); + void startScan(in int appIf, in boolean isServer, in ScanSettings settings, + in List<ScanFilter> filters, + in List scanStorages); void stopScan(in int appIf, in boolean isServer); - + void flushPendingBatchResults(in int appIf, in boolean isServer); + void startMultiAdvertising(in int appIf, + in AdvertiseData advertiseData, + in AdvertiseData scanResponse, + in AdvertiseSettings settings); + void stopMultiAdvertising(in int appIf); void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback); void unregisterClient(in int clientIf); - void clientConnect(in int clientIf, in String address, in boolean isDirect); + void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport); void clientDisconnect(in int clientIf, in String address); - void startAdvertising(in int appIf); - void stopAdvertising(); - boolean setAdvServiceData(in byte[] serviceData); - byte[] getAdvServiceData(); - boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData); - byte[] getAdvManufacturerData(); - List<ParcelUuid> getAdvServiceUuids(); - void removeAdvManufacturerCodeAndData(int manufacturerCode); - boolean isAdvertising(); void refreshDevice(in int clientIf, in String address); void discoverServices(in int clientIf, in String address); void readCharacteristic(in int clientIf, in String address, in int srvcType, @@ -74,10 +76,11 @@ void endReliableWrite(in int clientIf, in String address, in boolean execute); void readRemoteRssi(in int clientIf, in String address); void configureMTU(in int clientIf, in String address, in int mtu); + void connectionParameterUpdate(in int clientIf, in String address, in int connectionPriority); void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback); void unregisterServer(in int serverIf); - void serverConnect(in int servertIf, in String address, in boolean isDirect); + void serverConnect(in int servertIf, in String address, in boolean isDirect, in int transport); void serverDisconnect(in int serverIf, in String address); void beginServiceDeclaration(in int serverIf, in int srvcType, in int srvcInstanceId, in int minHandles,
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl index a78c29b..91e62ea 100644 --- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -16,17 +16,19 @@ package android.bluetooth; import android.os.ParcelUuid; - +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.ScanResult; /** * Callback definitions for interacting with BLE / GATT * @hide */ -interface IBluetoothGattCallback { +oneway interface IBluetoothGattCallback { void onClientRegistered(in int status, in int clientIf); void onClientConnectionState(in int status, in int clientIf, in boolean connected, in String address); - void onScanResult(in String address, in int rssi, in byte[] advData); + void onScanResult(in ScanResult scanResult); + void onBatchScanResults(in List<ScanResult> batchResults); void onGetService(in String address, in int srvcType, in int srvcInstId, in ParcelUuid srvcUuid); void onGetIncludedService(in String address, in int srvcType, in int srvcInstId, @@ -63,6 +65,8 @@ in int charInstId, in ParcelUuid charUuid, in byte[] value); void onReadRemoteRssi(in String address, in int rssi, in int status); - oneway void onAdvertiseStateChange(in int advertiseState, in int status); + void onMultiAdvertiseCallback(in int status, boolean isStart, + in AdvertiseSettings advertiseSettings); void onConfigureMTU(in String address, in int mtu, in int status); + void onFoundOrLost(in boolean onFound, in ScanResult scanResult); }
diff --git a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl index ae9bffc..5d4d6c6 100644 --- a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
@@ -22,7 +22,7 @@ * Callback definitions for interacting with BLE / GATT * @hide */ -interface IBluetoothGattServerCallback { +oneway interface IBluetoothGattServerCallback { void onServerRegistered(in int status, in int serverIf); void onScanResult(in String address, in int rssi, in byte[] advData); void onServerConnectionState(in int status, in int serverIf, @@ -58,4 +58,5 @@ in ParcelUuid descrId, in byte[] value); void onExecuteWrite(in String address, in int transId, in boolean execWrite); + void onNotificationSent(in String address, in int status); }
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl index 524ca6f..0e23fad 100755 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -55,4 +55,6 @@ void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type); void clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type); + boolean enableWBS(); + boolean disableWBS(); }
diff --git a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl new file mode 100644 index 0000000..e518b7d --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl
@@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadsetClientCall; +import android.os.Bundle; + +/** + * API for Bluetooth Headset Client service (HFP HF Role) + * + * {@hide} + */ +interface IBluetoothHeadsetClient { + boolean connect(in BluetoothDevice device); + boolean disconnect(in BluetoothDevice device); + + boolean acceptIncomingConnect(in BluetoothDevice device); + boolean rejectIncomingConnect(in BluetoothDevice device); + + List<BluetoothDevice> getConnectedDevices(); + List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); + boolean setPriority(in BluetoothDevice device, int priority); + int getPriority(in BluetoothDevice device); + + boolean startVoiceRecognition(in BluetoothDevice device); + boolean stopVoiceRecognition(in BluetoothDevice device); + + List<BluetoothHeadsetClientCall> getCurrentCalls(in BluetoothDevice device); + Bundle getCurrentAgEvents(in BluetoothDevice device); + + boolean acceptCall(in BluetoothDevice device, int flag); + boolean holdCall(in BluetoothDevice device); + boolean rejectCall(in BluetoothDevice device); + boolean terminateCall(in BluetoothDevice device, int index); + + boolean enterPrivateMode(in BluetoothDevice device, int index); + boolean explicitCallTransfer(in BluetoothDevice device); + + boolean redial(in BluetoothDevice device); + boolean dial(in BluetoothDevice device, String number); + boolean dialMemory(in BluetoothDevice device, int location); + + boolean sendDTMF(in BluetoothDevice device, byte code); + boolean getLastVoiceTagNumber(in BluetoothDevice device); + + int getAudioState(in BluetoothDevice device); + boolean connectAudio(); + boolean disconnectAudio(); + + Bundle getCurrentAgFeatures(in BluetoothDevice device); +}
diff --git a/core/java/android/bluetooth/le/AdvertiseCallback.java b/core/java/android/bluetooth/le/AdvertiseCallback.java new file mode 100644 index 0000000..706f469 --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertiseCallback.java
@@ -0,0 +1,74 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +/** + * Bluetooth LE advertising callbacks, used to deliver advertising operation status. + */ +public abstract class AdvertiseCallback { + + /** + * The requested operation was successful. + * + * @hide + */ + public static final int ADVERTISE_SUCCESS = 0; + + /** + * Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes. + */ + public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; + + /** + * Failed to start advertising because no advertising instance is available. + */ + public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; + + /** + * Failed to start advertising as the advertising is already started. + */ + public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; + + /** + * Operation failed due to an internal error. + */ + public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; + + /** + * This feature is not supported on this platform. + */ + public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; + + /** + * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertising} indicating + * that the advertising has been started successfully. + * + * @param settingsInEffect The actual settings used for advertising, which may be different from + * what has been requested. + */ + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + } + + /** + * Callback when advertising could not be started. + * + * @param errorCode Error code (see ADVERTISE_FAILED_* constants) for advertising start + * failures. + */ + public void onStartFailure(int errorCode) { + } +}
diff --git a/core/java/android/bluetooth/le/AdvertiseData.aidl b/core/java/android/bluetooth/le/AdvertiseData.aidl new file mode 100644 index 0000000..bcbf224 --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertiseData.aidl
@@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +parcelable AdvertiseData;
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java new file mode 100644 index 0000000..ff0db9a --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -0,0 +1,310 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.ParcelUuid; +import android.os.Parcelable; +import android.util.ArrayMap; +import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Advertise data packet container for Bluetooth LE advertising. This represents the data to be + * advertised as well as the scan response data for active scans. + * <p> + * Use {@link AdvertiseData.Builder} to create an instance of {@link AdvertiseData} to be + * advertised. + * + * @see BluetoothLeAdvertiser + * @see ScanRecord + */ +public final class AdvertiseData implements Parcelable { + + @Nullable + private final List<ParcelUuid> mServiceUuids; + + private final SparseArray<byte[]> mManufacturerSpecificData; + private final Map<ParcelUuid, byte[]> mServiceData; + private final boolean mIncludeTxPowerLevel; + private final boolean mIncludeDeviceName; + + private AdvertiseData(List<ParcelUuid> serviceUuids, + SparseArray<byte[]> manufacturerData, + Map<ParcelUuid, byte[]> serviceData, + boolean includeTxPowerLevel, + boolean includeDeviceName) { + mServiceUuids = serviceUuids; + mManufacturerSpecificData = manufacturerData; + mServiceData = serviceData; + mIncludeTxPowerLevel = includeTxPowerLevel; + mIncludeDeviceName = includeDeviceName; + } + + /** + * Returns a list of service UUIDs within the advertisement that are used to identify the + * Bluetooth GATT services. + */ + public List<ParcelUuid> getServiceUuids() { + return mServiceUuids; + } + + /** + * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The + * manufacturer id is a non-negative number assigned by Bluetooth SIG. + */ + public SparseArray<byte[]> getManufacturerSpecificData() { + return mManufacturerSpecificData; + } + + /** + * Returns a map of 16-bit UUID and its corresponding service data. + */ + public Map<ParcelUuid, byte[]> getServiceData() { + return mServiceData; + } + + /** + * Whether the transmission power level will be included in the advertisement packet. + */ + public boolean getIncludeTxPowerLevel() { + return mIncludeTxPowerLevel; + } + + /** + * Whether the device name will be included in the advertisement packet. + */ + public boolean getIncludeDeviceName() { + return mIncludeDeviceName; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData, + mIncludeDeviceName, mIncludeTxPowerLevel); + } + + /** + * @hide + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + AdvertiseData other = (AdvertiseData) obj; + return Objects.equals(mServiceUuids, other.mServiceUuids) && + BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && + BluetoothLeUtils.equals(mServiceData, other.mServiceData) && + mIncludeDeviceName == other.mIncludeDeviceName && + mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; + } + + @Override + public String toString() { + return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData=" + + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + + BluetoothLeUtils.toString(mServiceData) + + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + + mIncludeDeviceName + "]"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeList(mServiceUuids); + + // mManufacturerSpecificData could not be null. + dest.writeInt(mManufacturerSpecificData.size()); + for (int i = 0; i < mManufacturerSpecificData.size(); ++i) { + dest.writeInt(mManufacturerSpecificData.keyAt(i)); + byte[] data = mManufacturerSpecificData.valueAt(i); + if (data == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + dest.writeInt(data.length); + dest.writeByteArray(data); + } + } + dest.writeInt(mServiceData.size()); + for (ParcelUuid uuid : mServiceData.keySet()) { + dest.writeParcelable(uuid, flags); + byte[] data = mServiceData.get(uuid); + if (data == null) { + dest.writeInt(0); + } else { + dest.writeInt(1); + dest.writeInt(data.length); + dest.writeByteArray(data); + } + } + dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); + dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); + } + + public static final Parcelable.Creator<AdvertiseData> CREATOR = + new Creator<AdvertiseData>() { + @Override + public AdvertiseData[] newArray(int size) { + return new AdvertiseData[size]; + } + + @Override + public AdvertiseData createFromParcel(Parcel in) { + Builder builder = new Builder(); + @SuppressWarnings("unchecked") + List<ParcelUuid> uuids = in.readArrayList(ParcelUuid.class.getClassLoader()); + if (uuids != null) { + for (ParcelUuid uuid : uuids) { + builder.addServiceUuid(uuid); + } + } + int manufacturerSize = in.readInt(); + for (int i = 0; i < manufacturerSize; ++i) { + int manufacturerId = in.readInt(); + if (in.readInt() == 1) { + int manufacturerDataLength = in.readInt(); + byte[] manufacturerData = new byte[manufacturerDataLength]; + in.readByteArray(manufacturerData); + builder.addManufacturerData(manufacturerId, manufacturerData); + } + } + int serviceDataSize = in.readInt(); + for (int i = 0; i < serviceDataSize; ++i) { + ParcelUuid serviceDataUuid = in.readParcelable( + ParcelUuid.class.getClassLoader()); + if (in.readInt() == 1) { + int serviceDataLength = in.readInt(); + byte[] serviceData = new byte[serviceDataLength]; + in.readByteArray(serviceData); + builder.addServiceData(serviceDataUuid, serviceData); + } + } + builder.setIncludeTxPowerLevel(in.readByte() == 1); + builder.setIncludeDeviceName(in.readByte() == 1); + return builder.build(); + } + }; + + /** + * Builder for {@link AdvertiseData}. + */ + public static final class Builder { + @Nullable + private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); + private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>(); + private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); + private boolean mIncludeTxPowerLevel; + private boolean mIncludeDeviceName; + + /** + * Add a service UUID to advertise data. + * + * @param serviceUuid A service UUID to be advertised. + * @throws IllegalArgumentException If the {@code serviceUuids} are null. + */ + public Builder addServiceUuid(ParcelUuid serviceUuid) { + if (serviceUuid == null) { + throw new IllegalArgumentException("serivceUuids are null"); + } + mServiceUuids.add(serviceUuid); + return this; + } + + /** + * Add service data to advertise data. + * + * @param serviceDataUuid 16-bit UUID of the service the data is associated with + * @param serviceData Service data + * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is + * empty. + */ + public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { + if (serviceDataUuid == null || serviceData == null) { + throw new IllegalArgumentException( + "serviceDataUuid or serviceDataUuid is null"); + } + mServiceData.put(serviceDataUuid, serviceData); + return this; + } + + /** + * Add manufacturer specific data. + * <p> + * Please refer to the Bluetooth Assigned Numbers document provided by the <a + * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company + * identifiers. + * + * @param manufacturerId Manufacturer ID assigned by Bluetooth SIG. + * @param manufacturerSpecificData Manufacturer specific data + * @throws IllegalArgumentException If the {@code manufacturerId} is negative or + * {@code manufacturerSpecificData} is null. + */ + public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { + if (manufacturerId < 0) { + throw new IllegalArgumentException( + "invalid manufacturerId - " + manufacturerId); + } + if (manufacturerSpecificData == null) { + throw new IllegalArgumentException("manufacturerSpecificData is null"); + } + mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData); + return this; + } + + /** + * Whether the transmission power level should be included in the advertise packet. Tx power + * level field takes 3 bytes in advertise packet. + */ + public Builder setIncludeTxPowerLevel(boolean includeTxPowerLevel) { + mIncludeTxPowerLevel = includeTxPowerLevel; + return this; + } + + /** + * Set whether the device name should be included in advertise packet. + */ + public Builder setIncludeDeviceName(boolean includeDeviceName) { + mIncludeDeviceName = includeDeviceName; + return this; + } + + /** + * Build the {@link AdvertiseData}. + */ + public AdvertiseData build() { + return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData, + mIncludeTxPowerLevel, mIncludeDeviceName); + } + } +}
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.aidl b/core/java/android/bluetooth/le/AdvertiseSettings.aidl new file mode 100644 index 0000000..9f47d74 --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertiseSettings.aidl
@@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +parcelable AdvertiseSettings; \ No newline at end of file
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java new file mode 100644 index 0000000..62c68a4 --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertiseSettings.java
@@ -0,0 +1,234 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * The {@link AdvertiseSettings} provide a way to adjust advertising preferences for each + * Bluetooth LE advertisement instance. Use {@link AdvertiseSettings.Builder} to create an + * instance of this class. + */ +public final class AdvertiseSettings implements Parcelable { + /** + * Perform Bluetooth LE advertising in low power mode. This is the default and preferred + * advertising mode as it consumes the least power. + */ + public static final int ADVERTISE_MODE_LOW_POWER = 0; + + /** + * Perform Bluetooth LE advertising in balanced power mode. This is balanced between advertising + * frequency and power consumption. + */ + public static final int ADVERTISE_MODE_BALANCED = 1; + + /** + * Perform Bluetooth LE advertising in low latency, high power mode. This has the highest power + * consumption and should not be used for continuous background advertising. + */ + public static final int ADVERTISE_MODE_LOW_LATENCY = 2; + + /** + * Advertise using the lowest transmission (TX) power level. Low transmission power can be used + * to restrict the visibility range of advertising packets. + */ + public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; + + /** + * Advertise using low TX power level. + */ + public static final int ADVERTISE_TX_POWER_LOW = 1; + + /** + * Advertise using medium TX power level. + */ + public static final int ADVERTISE_TX_POWER_MEDIUM = 2; + + /** + * Advertise using high TX power level. This corresponds to largest visibility range of the + * advertising packet. + */ + public static final int ADVERTISE_TX_POWER_HIGH = 3; + + /** + * The maximum limited advertisement duration as specified by the Bluetooth SIG + */ + private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000; + + private final int mAdvertiseMode; + private final int mAdvertiseTxPowerLevel; + private final int mAdvertiseTimeoutMillis; + private final boolean mAdvertiseConnectable; + + private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel, + boolean advertiseConnectable, int advertiseTimeout) { + mAdvertiseMode = advertiseMode; + mAdvertiseTxPowerLevel = advertiseTxPowerLevel; + mAdvertiseConnectable = advertiseConnectable; + mAdvertiseTimeoutMillis = advertiseTimeout; + } + + private AdvertiseSettings(Parcel in) { + mAdvertiseMode = in.readInt(); + mAdvertiseTxPowerLevel = in.readInt(); + mAdvertiseConnectable = in.readInt() != 0 ? true : false; + mAdvertiseTimeoutMillis = in.readInt(); + } + + /** + * Returns the advertise mode. + */ + public int getMode() { + return mAdvertiseMode; + } + + /** + * Returns the TX power level for advertising. + */ + public int getTxPowerLevel() { + return mAdvertiseTxPowerLevel; + } + + /** + * Returns whether the advertisement will indicate connectable. + */ + public boolean isConnectable() { + return mAdvertiseConnectable; + } + + /** + * Returns the advertising time limit in milliseconds. + */ + public int getTimeout() { + return mAdvertiseTimeoutMillis; + } + + @Override + public String toString() { + return "Settings [mAdvertiseMode=" + mAdvertiseMode + + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel + + ", mAdvertiseConnectable=" + mAdvertiseConnectable + + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mAdvertiseMode); + dest.writeInt(mAdvertiseTxPowerLevel); + dest.writeInt(mAdvertiseConnectable ? 1 : 0); + dest.writeInt(mAdvertiseTimeoutMillis); + } + + public static final Parcelable.Creator<AdvertiseSettings> CREATOR = + new Creator<AdvertiseSettings>() { + @Override + public AdvertiseSettings[] newArray(int size) { + return new AdvertiseSettings[size]; + } + + @Override + public AdvertiseSettings createFromParcel(Parcel in) { + return new AdvertiseSettings(in); + } + }; + + /** + * Builder class for {@link AdvertiseSettings}. + */ + public static final class Builder { + private int mMode = ADVERTISE_MODE_LOW_POWER; + private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM; + private int mTimeoutMillis = 0; + private boolean mConnectable = true; + + /** + * Set advertise mode to control the advertising power and latency. + * + * @param advertiseMode Bluetooth LE Advertising mode, can only be one of + * {@link AdvertiseSettings#ADVERTISE_MODE_LOW_POWER}, + * {@link AdvertiseSettings#ADVERTISE_MODE_BALANCED}, or + * {@link AdvertiseSettings#ADVERTISE_MODE_LOW_LATENCY}. + * @throws IllegalArgumentException If the advertiseMode is invalid. + */ + public Builder setAdvertiseMode(int advertiseMode) { + if (advertiseMode < ADVERTISE_MODE_LOW_POWER + || advertiseMode > ADVERTISE_MODE_LOW_LATENCY) { + throw new IllegalArgumentException("unknown mode " + advertiseMode); + } + mMode = advertiseMode; + return this; + } + + /** + * Set advertise TX power level to control the transmission power level for the advertising. + * + * @param txPowerLevel Transmission power of Bluetooth LE Advertising, can only be one of + * {@link AdvertiseSettings#ADVERTISE_TX_POWER_ULTRA_LOW}, + * {@link AdvertiseSettings#ADVERTISE_TX_POWER_LOW}, + * {@link AdvertiseSettings#ADVERTISE_TX_POWER_MEDIUM} or + * {@link AdvertiseSettings#ADVERTISE_TX_POWER_HIGH}. + * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid. + */ + public Builder setTxPowerLevel(int txPowerLevel) { + if (txPowerLevel < ADVERTISE_TX_POWER_ULTRA_LOW + || txPowerLevel > ADVERTISE_TX_POWER_HIGH) { + throw new IllegalArgumentException("unknown tx power level " + txPowerLevel); + } + mTxPowerLevel = txPowerLevel; + return this; + } + + /** + * Set whether the advertisement type should be connectable or non-connectable. + * + * @param connectable Controls whether the advertisment type will be connectable (true) + * or non-connectable (false). + */ + public Builder setConnectable(boolean connectable) { + mConnectable = connectable; + return this; + } + + /** + * Limit advertising to a given amount of time. + * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds. + * A value of 0 will disable the time limit. + * @throws IllegalArgumentException If the provided timeout is over 180000 ms. + */ + public Builder setTimeout(int timeoutMillis) { + if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) { + throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" + + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)"); + } + mTimeoutMillis = timeoutMillis; + return this; + } + + /** + * Build the {@link AdvertiseSettings} object. + */ + public AdvertiseSettings build() { + return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis); + } + } +}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java new file mode 100644 index 0000000..d468508 --- /dev/null +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -0,0 +1,373 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallbackWrapper; +import android.bluetooth.BluetoothUuid; +import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothManager; +import android.os.Handler; +import android.os.Looper; +import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * This class provides a way to perform Bluetooth LE advertise operations, such as starting and + * stopping advertising. An advertiser can broadcast up to 31 bytes of advertisement data + * represented by {@link AdvertiseData}. + * <p> + * To get an instance of {@link BluetoothLeAdvertiser}, call the + * {@link BluetoothAdapter#getBluetoothLeAdvertiser()} method. + * <p> + * <b>Note:</b> Most of the methods here require {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @see AdvertiseData + */ +public final class BluetoothLeAdvertiser { + + private static final String TAG = "BluetoothLeAdvertiser"; + + private static final int MAX_ADVERTISING_DATA_BYTES = 31; + // Each fields need one byte for field length and another byte for field type. + private static final int OVERHEAD_BYTES_PER_FIELD = 2; + // Flags field will be set by system. + private static final int FLAGS_FIELD_BYTES = 3; + private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2; + private static final int SERVICE_DATA_UUID_LENGTH = 2; + + private final IBluetoothManager mBluetoothManager; + private final Handler mHandler; + private BluetoothAdapter mBluetoothAdapter; + private final Map<AdvertiseCallback, AdvertiseCallbackWrapper> + mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>(); + + /** + * Use BluetoothAdapter.getLeAdvertiser() instead. + * + * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management + * @hide + */ + public BluetoothLeAdvertiser(IBluetoothManager bluetoothManager) { + mBluetoothManager = bluetoothManager; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + mHandler = new Handler(Looper.getMainLooper()); + } + + /** + * Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be broadcasted. + * Returns immediately, the operation status is delivered through {@code callback}. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param settings Settings for Bluetooth LE advertising. + * @param advertiseData Advertisement data to be broadcasted. + * @param callback Callback for advertising status. + */ + public void startAdvertising(AdvertiseSettings settings, + AdvertiseData advertiseData, final AdvertiseCallback callback) { + startAdvertising(settings, advertiseData, null, callback); + } + + /** + * Start Bluetooth LE Advertising. The {@code advertiseData} will be broadcasted if the + * operation succeeds. The {@code scanResponse} is returned when a scanning device sends an + * active scan request. This method returns immediately, the operation status is delivered + * through {@code callback}. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * + * @param settings Settings for Bluetooth LE advertising. + * @param advertiseData Advertisement data to be advertised in advertisement packet. + * @param scanResponse Scan response associated with the advertisement data. + * @param callback Callback for advertising status. + */ + public void startAdvertising(AdvertiseSettings settings, + AdvertiseData advertiseData, AdvertiseData scanResponse, + final AdvertiseCallback callback) { + synchronized (mLeAdvertisers) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null"); + } + if (!mBluetoothAdapter.isMultipleAdvertisementSupported()) { + postStartFailure(callback, + AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED); + return; + } + if (totalBytes(advertiseData) > MAX_ADVERTISING_DATA_BYTES || + totalBytes(scanResponse) > MAX_ADVERTISING_DATA_BYTES) { + postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); + return; + } + if (mLeAdvertisers.containsKey(callback)) { + postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); + return; + } + + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + return; + } + AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData, + scanResponse, settings, gatt); + wrapper.startRegisteration(); + } + } + + /** + * Stop Bluetooth LE advertising. The {@code callback} must be the same one use in + * {@link BluetoothLeAdvertiser#startAdvertising}. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param callback {@link AdvertiseCallback} identifies the advertising instance to stop. + */ + public void stopAdvertising(final AdvertiseCallback callback) { + synchronized (mLeAdvertisers) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null"); + } + AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback); + if (wrapper == null) return; + wrapper.stopAdvertising(); + } + } + + /** + * Cleans up advertise clients. Should be called when bluetooth is down. + * + * @hide + */ + public void cleanup() { + mLeAdvertisers.clear(); + } + + // Compute the size of the advertise data. + private int totalBytes(AdvertiseData data) { + if (data == null) return 0; + int size = FLAGS_FIELD_BYTES; // flags field is always set. + if (data.getServiceUuids() != null) { + int num16BitUuids = 0; + int num32BitUuids = 0; + int num128BitUuids = 0; + for (ParcelUuid uuid : data.getServiceUuids()) { + if (BluetoothUuid.is16BitUuid(uuid)) { + ++num16BitUuids; + } else if (BluetoothUuid.is32BitUuid(uuid)) { + ++num32BitUuids; + } else { + ++num128BitUuids; + } + } + // 16 bit service uuids are grouped into one field when doing advertising. + if (num16BitUuids != 0) { + size += OVERHEAD_BYTES_PER_FIELD + + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT; + } + // 32 bit service uuids are grouped into one field when doing advertising. + if (num32BitUuids != 0) { + size += OVERHEAD_BYTES_PER_FIELD + + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT; + } + // 128 bit service uuids are grouped into one field when doing advertising. + if (num128BitUuids != 0) { + size += OVERHEAD_BYTES_PER_FIELD + + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; + } + } + for (ParcelUuid uuid : data.getServiceData().keySet()) { + size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH + + byteLength(data.getServiceData().get(uuid)); + } + for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) { + size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + + byteLength(data.getManufacturerSpecificData().valueAt(i)); + } + if (data.getIncludeTxPowerLevel()) { + size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. + } + if (data.getIncludeDeviceName() && mBluetoothAdapter.getName() != null) { + size += OVERHEAD_BYTES_PER_FIELD + mBluetoothAdapter.getName().length(); + } + return size; + } + + private int byteLength(byte[] array) { + return array == null ? 0 : array.length; + } + + /** + * Bluetooth GATT interface callbacks for advertising. + */ + private class AdvertiseCallbackWrapper extends BluetoothGattCallbackWrapper { + private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000; + private final AdvertiseCallback mAdvertiseCallback; + private final AdvertiseData mAdvertisement; + private final AdvertiseData mScanResponse; + private final AdvertiseSettings mSettings; + private final IBluetoothGatt mBluetoothGatt; + + // mClientIf 0: not registered + // -1: scan stopped + // >0: registered and scan started + private int mClientIf; + private boolean mIsAdvertising = false; + + public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback, + AdvertiseData advertiseData, AdvertiseData scanResponse, + AdvertiseSettings settings, + IBluetoothGatt bluetoothGatt) { + mAdvertiseCallback = advertiseCallback; + mAdvertisement = advertiseData; + mScanResponse = scanResponse; + mSettings = settings; + mBluetoothGatt = bluetoothGatt; + mClientIf = 0; + } + + public void startRegisteration() { + synchronized (this) { + if (mClientIf == -1) return; + + try { + UUID uuid = UUID.randomUUID(); + mBluetoothGatt.registerClient(new ParcelUuid(uuid), this); + wait(LE_CALLBACK_TIMEOUT_MILLIS); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Failed to start registeration", e); + } + if (mClientIf > 0 && mIsAdvertising) { + mLeAdvertisers.put(mAdvertiseCallback, this); + } else if (mClientIf <= 0) { + // Post internal error if registration failed. + postStartFailure(mAdvertiseCallback, + AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + } else { + // Unregister application if it's already registered but advertise failed. + try { + mBluetoothGatt.unregisterClient(mClientIf); + mClientIf = -1; + } catch (RemoteException e) { + Log.e(TAG, "remote exception when unregistering", e); + } + } + } + } + + public void stopAdvertising() { + synchronized (this) { + try { + mBluetoothGatt.stopMultiAdvertising(mClientIf); + wait(LE_CALLBACK_TIMEOUT_MILLIS); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Failed to stop advertising", e); + } + // Advertise callback should have been removed from LeAdvertisers when + // onMultiAdvertiseCallback was called. In case onMultiAdvertiseCallback is never + // invoked and wait timeout expires, remove callback here. + if (mLeAdvertisers.containsKey(mAdvertiseCallback)) { + mLeAdvertisers.remove(mAdvertiseCallback); + } + } + } + + /** + * Application interface registered - app is ready to go + */ + @Override + public void onClientRegistered(int status, int clientIf) { + Log.d(TAG, "onClientRegistered() - status=" + status + " clientIf=" + clientIf); + synchronized (this) { + if (status == BluetoothGatt.GATT_SUCCESS) { + mClientIf = clientIf; + try { + mBluetoothGatt.startMultiAdvertising(mClientIf, mAdvertisement, + mScanResponse, mSettings); + return; + } catch (RemoteException e) { + Log.e(TAG, "failed to start advertising", e); + } + } + // Registration failed. + mClientIf = -1; + notifyAll(); + } + } + + @Override + public void onMultiAdvertiseCallback(int status, boolean isStart, + AdvertiseSettings settings) { + synchronized (this) { + if (isStart) { + if (status == AdvertiseCallback.ADVERTISE_SUCCESS) { + // Start success + mIsAdvertising = true; + postStartSuccess(mAdvertiseCallback, settings); + } else { + // Start failure. + postStartFailure(mAdvertiseCallback, status); + } + } else { + // unregister client for stop. + try { + mBluetoothGatt.unregisterClient(mClientIf); + mClientIf = -1; + mIsAdvertising = false; + mLeAdvertisers.remove(mAdvertiseCallback); + } catch (RemoteException e) { + Log.e(TAG, "remote exception when unregistering", e); + } + } + notifyAll(); + } + + } + } + + private void postStartFailure(final AdvertiseCallback callback, final int error) { + mHandler.post(new Runnable() { + @Override + public void run() { + callback.onStartFailure(error); + } + }); + } + + private void postStartSuccess(final AdvertiseCallback callback, + final AdvertiseSettings settings) { + mHandler.post(new Runnable() { + + @Override + public void run() { + callback.onStartSuccess(settings); + } + }); + } +}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java new file mode 100644 index 0000000..a57c3ca --- /dev/null +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -0,0 +1,396 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import android.annotation.SystemApi; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallbackWrapper; +import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothManager; +import android.os.Handler; +import android.os.Looper; +import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * This class provides methods to perform scan related operations for Bluetooth LE devices. An + * application can scan for a particular type of Bluetotoh LE devices using {@link ScanFilter}. It + * can also request different types of callbacks for delivering the result. + * <p> + * Use {@link BluetoothAdapter#getBluetoothLeScanner()} to get an instance of + * {@link BluetoothLeScanner}. + * <p> + * <b>Note:</b> Most of the scan methods here require + * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @see ScanFilter + */ +public final class BluetoothLeScanner { + + private static final String TAG = "BluetoothLeScanner"; + private static final boolean DBG = true; + + private final IBluetoothManager mBluetoothManager; + private final Handler mHandler; + private BluetoothAdapter mBluetoothAdapter; + private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients; + + /** + * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead. + * + * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management. + * @hide + */ + public BluetoothLeScanner(IBluetoothManager bluetoothManager) { + mBluetoothManager = bluetoothManager; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + mHandler = new Handler(Looper.getMainLooper()); + mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>(); + } + + /** + * Start Bluetooth LE scan with default parameters and no filters. The scan results will be + * delivered through {@code callback}. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param callback Callback used to deliver scan results. + * @throws IllegalArgumentException If {@code callback} is null. + */ + public void startScan(final ScanCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("callback is null"); + } + startScan(null, new ScanSettings.Builder().build(), callback); + } + + /** + * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param filters {@link ScanFilter}s for finding exact BLE devices. + * @param settings Settings for the scan. + * @param callback Callback used to deliver scan results. + * @throws IllegalArgumentException If {@code settings} or {@code callback} is null. + */ + public void startScan(List<ScanFilter> filters, ScanSettings settings, + final ScanCallback callback) { + startScan(filters, settings, callback, null); + } + + private void startScan(List<ScanFilter> filters, ScanSettings settings, + final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + if (settings == null || callback == null) { + throw new IllegalArgumentException("settings or callback is null"); + } + synchronized (mLeScanClients) { + if (mLeScanClients.containsKey(callback)) { + postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED); + return; + } + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + gatt = null; + } + if (gatt == null) { + postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); + return; + } + if (!isSettingsConfigAllowedForScan(settings)) { + postCallbackError(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + return; + } + BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, + settings, callback, resultStorages); + wrapper.startRegisteration(); + } + } + + /** + * Stops an ongoing Bluetooth LE scan. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param callback + */ + public void stopScan(ScanCallback callback) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + synchronized (mLeScanClients) { + BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback); + if (wrapper == null) { + if (DBG) Log.d(TAG, "could not find callback wrapper"); + return; + } + wrapper.stopLeScan(); + } + } + + /** + * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth + * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data + * will be delivered through the {@code callback}. + * + * @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one + * used to start scan. + */ + public void flushPendingScanResults(ScanCallback callback) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null!"); + } + synchronized (mLeScanClients) { + BleScanCallbackWrapper wrapper = mLeScanClients.get(callback); + if (wrapper == null) { + return; + } + wrapper.flushPendingBatchResults(); + } + } + + /** + * Start truncated scan. + * + * @hide + */ + @SystemApi + public void startTruncatedScan(List<TruncatedFilter> truncatedFilters, ScanSettings settings, + final ScanCallback callback) { + int filterSize = truncatedFilters.size(); + List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(filterSize); + List<List<ResultStorageDescriptor>> scanStorages = + new ArrayList<List<ResultStorageDescriptor>>(filterSize); + for (TruncatedFilter filter : truncatedFilters) { + scanFilters.add(filter.getFilter()); + scanStorages.add(filter.getStorageDescriptors()); + } + startScan(scanFilters, settings, callback, scanStorages); + } + + /** + * Cleans up scan clients. Should be called when bluetooth is down. + * + * @hide + */ + public void cleanup() { + mLeScanClients.clear(); + } + + /** + * Bluetooth GATT interface callbacks + */ + private class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper { + private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000; + + private final ScanCallback mScanCallback; + private final List<ScanFilter> mFilters; + private ScanSettings mSettings; + private IBluetoothGatt mBluetoothGatt; + private List<List<ResultStorageDescriptor>> mResultStorages; + + // mLeHandle 0: not registered + // -1: scan stopped + // > 0: registered and scan started + private int mClientIf; + + public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt, + List<ScanFilter> filters, ScanSettings settings, + ScanCallback scanCallback, List<List<ResultStorageDescriptor>> resultStorages) { + mBluetoothGatt = bluetoothGatt; + mFilters = filters; + mSettings = settings; + mScanCallback = scanCallback; + mClientIf = 0; + mResultStorages = resultStorages; + } + + public void startRegisteration() { + synchronized (this) { + // Scan stopped. + if (mClientIf == -1) return; + try { + UUID uuid = UUID.randomUUID(); + mBluetoothGatt.registerClient(new ParcelUuid(uuid), this); + wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "application registeration exception", e); + postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); + } + if (mClientIf > 0) { + mLeScanClients.put(mScanCallback, this); + } else { + postCallbackError(mScanCallback, + ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED); + } + } + } + + public void stopLeScan() { + synchronized (this) { + if (mClientIf <= 0) { + Log.e(TAG, "Error state, mLeHandle: " + mClientIf); + return; + } + try { + mBluetoothGatt.stopScan(mClientIf, false); + mBluetoothGatt.unregisterClient(mClientIf); + } catch (RemoteException e) { + Log.e(TAG, "Failed to stop scan and unregister", e); + } + mClientIf = -1; + } + } + + void flushPendingBatchResults() { + synchronized (this) { + if (mClientIf <= 0) { + Log.e(TAG, "Error state, mLeHandle: " + mClientIf); + return; + } + try { + mBluetoothGatt.flushPendingBatchResults(mClientIf, false); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get pending scan results", e); + } + } + } + + /** + * Application interface registered - app is ready to go + */ + @Override + public void onClientRegistered(int status, int clientIf) { + Log.d(TAG, "onClientRegistered() - status=" + status + + " clientIf=" + clientIf); + synchronized (this) { + if (mClientIf == -1) { + if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled"); + } + + if (status == BluetoothGatt.GATT_SUCCESS) { + mClientIf = clientIf; + try { + mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters, + mResultStorages); + } catch (RemoteException e) { + Log.e(TAG, "fail to start le scan: " + e); + mClientIf = -1; + } + } else { + // registration failed + mClientIf = -1; + } + notifyAll(); + } + } + + /** + * Callback reporting an LE scan result. + * + * @hide + */ + @Override + public void onScanResult(final ScanResult scanResult) { + if (DBG) Log.d(TAG, "onScanResult() - " + scanResult.toString()); + + // Check null in case the scan has been stopped + synchronized (this) { + if (mClientIf <= 0) return; + } + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult); + } + }); + + } + + @Override + public void onBatchScanResults(final List<ScanResult> results) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + mScanCallback.onBatchScanResults(results); + } + }); + } + + @Override + public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) { + if (DBG) { + Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + + " " + scanResult.toString()); + } + + // Check null in case the scan has been stopped + synchronized (this) { + if (mClientIf <= 0) + return; + } + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + if (onFound) { + mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH, + scanResult); + } else { + mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST, + scanResult); + } + } + }); + } + } + + private void postCallbackError(final ScanCallback callback, final int errorCode) { + mHandler.post(new Runnable() { + @Override + public void run() { + callback.onScanFailed(errorCode); + } + }); + } + + private boolean isSettingsConfigAllowedForScan(ScanSettings settings) { + if (mBluetoothAdapter.isOffloadedFilteringSupported()) { + return true; + } + final int callbackType = settings.getCallbackType(); + // Only support regular scan if no offloaded filter support. + if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES + && settings.getReportDelayMillis() == 0) { + return true; + } + return false; + } +}
diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java new file mode 100644 index 0000000..4916bd9 --- /dev/null +++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java
@@ -0,0 +1,140 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import android.bluetooth.BluetoothAdapter; +import android.util.SparseArray; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Helper class for Bluetooth LE utils. + * + * @hide + */ +public class BluetoothLeUtils { + + /** + * Returns a string composed from a {@link SparseArray}. + */ + static String toString(SparseArray<byte[]> array) { + if (array == null) { + return "null"; + } + if (array.size() == 0) { + return "{}"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append('{'); + for (int i = 0; i < array.size(); ++i) { + buffer.append(array.keyAt(i)).append("=").append(Arrays.toString(array.valueAt(i))); + } + buffer.append('}'); + return buffer.toString(); + } + + /** + * Returns a string composed from a {@link Map}. + */ + static <T> String toString(Map<T, byte[]> map) { + if (map == null) { + return "null"; + } + if (map.isEmpty()) { + return "{}"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append('{'); + Iterator<Map.Entry<T, byte[]>> it = map.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<T, byte[]> entry = it.next(); + Object key = entry.getKey(); + buffer.append(key).append("=").append(Arrays.toString(map.get(key))); + if (it.hasNext()) { + buffer.append(", "); + } + } + buffer.append('}'); + return buffer.toString(); + } + + /** + * Check whether two {@link SparseArray} equal. + */ + static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) { + if (array == otherArray) { + return true; + } + if (array == null || otherArray == null) { + return false; + } + if (array.size() != otherArray.size()) { + return false; + } + + // Keys are guaranteed in ascending order when indices are in ascending order. + for (int i = 0; i < array.size(); ++i) { + if (array.keyAt(i) != otherArray.keyAt(i) || + !Arrays.equals(array.valueAt(i), otherArray.valueAt(i))) { + return false; + } + } + return true; + } + + /** + * Check whether two {@link Map} equal. + */ + static <T> boolean equals(Map<T, byte[]> map, Map<T, byte[]> otherMap) { + if (map == otherMap) { + return true; + } + if (map == null || otherMap == null) { + return false; + } + if (map.size() != otherMap.size()) { + return false; + } + Set<T> keys = map.keySet(); + if (!keys.equals(otherMap.keySet())) { + return false; + } + for (T key : keys) { + if (!Objects.deepEquals(map.get(key), otherMap.get(key))) { + return false; + } + } + return true; + } + + /** + * Ensure Bluetooth is turned on. + * + * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not + * {@link BluetoothAdapter#STATE_ON}. + */ + static void checkAdapterStateOn(BluetoothAdapter adapter) { + if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON) { + throw new IllegalStateException("BT Adapter is not turned ON"); + } + } + +}
diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.aidl b/core/java/android/bluetooth/le/ResultStorageDescriptor.aidl new file mode 100644 index 0000000..f218a01 --- /dev/null +++ b/core/java/android/bluetooth/le/ResultStorageDescriptor.aidl
@@ -0,0 +1,23 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +/** + * {@hide} + */ + +parcelable ResultStorageDescriptor;
diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.java b/core/java/android/bluetooth/le/ResultStorageDescriptor.java new file mode 100644 index 0000000..748f97d --- /dev/null +++ b/core/java/android/bluetooth/le/ResultStorageDescriptor.java
@@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Describes the way to store scan result. + * + * @hide + */ +@SystemApi +public final class ResultStorageDescriptor implements Parcelable { + private int mType; + private int mOffset; + private int mLength; + + public int getType() { + return mType; + } + + public int getOffset() { + return mOffset; + } + + public int getLength() { + return mLength; + } + + /** + * Constructor of {@link ResultStorageDescriptor} + * + * @param type Type of the data. + * @param offset Offset from start of the advertise packet payload. + * @param length Byte length of the data + */ + public ResultStorageDescriptor(int type, int offset, int length) { + mType = type; + mOffset = offset; + mLength = length; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mType); + dest.writeInt(mOffset); + dest.writeInt(mLength); + } + + private ResultStorageDescriptor(Parcel in) { + ReadFromParcel(in); + } + + private void ReadFromParcel(Parcel in) { + mType = in.readInt(); + mOffset = in.readInt(); + mLength = in.readInt(); + } + + public static final Parcelable.Creator<ResultStorageDescriptor> + CREATOR = new Creator<ResultStorageDescriptor>() { + @Override + public ResultStorageDescriptor createFromParcel(Parcel source) { + return new ResultStorageDescriptor(source); + } + + @Override + public ResultStorageDescriptor[] newArray(int size) { + return new ResultStorageDescriptor[size]; + } + }; +}
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java new file mode 100644 index 0000000..05782a8 --- /dev/null +++ b/core/java/android/bluetooth/le/ScanCallback.java
@@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 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.bluetooth.le; + +import java.util.List; + +/** + * Bluetooth LE scan callbacks. Scan results are reported using these callbacks. + * + * @see BluetoothLeScanner#startScan + */ +public abstract class ScanCallback { + /** + * Fails to start scan as BLE scan with the same settings is already started by the app. + */ + public static final int SCAN_FAILED_ALREADY_STARTED = 1; + + /** + * Fails to start scan as app cannot be registered. + */ + public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2; + + /** + * Fails to start scan due an internal error + */ + public static final int SCAN_FAILED_INTERNAL_ERROR = 3; + + /** + * Fails to start power optimized scan as this feature is not supported. + */ + public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; + + /** + * Callback when a BLE advertisement has been found. + * + * @param callbackType Determines how this callback was triggered. Currently could only be + * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}. + * @param result A Bluetooth LE scan result. + */ + public void onScanResult(int callbackType, ScanResult result) { + } + + /** + * Callback when batch results are delivered. + * + * @param results List of scan results that are previously scanned. + */