diff options
62 files changed, 2496 insertions, 603 deletions
diff --git a/Android.mk b/Android.mk index ea75b19c7ff8..71720a1740a5 100644 --- a/Android.mk +++ b/Android.mk @@ -36,7 +36,7 @@ aidl_parcelables := define stubs-to-aidl-parcelables gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/$1.aidl aidl_parcelables += $$(gen) - $$(gen): $(call java-lib-header-files,$1) | $(HOST_OUT_EXECUTABLES)/sdkparcelables + $$(gen): $(call java-lib-header-files,$1) $(HOST_OUT_EXECUTABLES)/sdkparcelables @echo Extract SDK parcelables: $$@ rm -f $$@ $(HOST_OUT_EXECUTABLES)/sdkparcelables $$< $$@ diff --git a/api/current.txt b/api/current.txt index 6f315be07039..cd29286aacc6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6534,6 +6534,7 @@ package android.app.admin { field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 + field public static final int WIPE_EUICC = 4; // 0x4 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } @@ -9048,6 +9049,7 @@ package android.content { field public static final java.lang.String DISPLAY_SERVICE = "display"; field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; + field public static final java.lang.String EUICC_SERVICE = "euicc"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; @@ -10851,6 +10853,7 @@ package android.content.pm { field public static final java.lang.String FEATURE_SIP_VOIP = "android.software.sip.voip"; 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_EUICC = "android.hardware.telephony.euicc"; field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm"; field public static final java.lang.String FEATURE_TELEPHONY_MBMS = "android.hardware.telephony.mbms"; field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television"; @@ -35550,6 +35553,13 @@ package android.provider { field public static final java.lang.String ADDRESS = "address"; } + public static final class Telephony.CarrierIdentification implements android.provider.BaseColumns { + method public static android.net.Uri getUriForSubscriptionId(int); + field public static final java.lang.String CID = "carrier_id"; + field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String NAME = "carrier_name"; + } + public static final class Telephony.Carriers implements android.provider.BaseColumns { field public static final java.lang.String APN = "apn"; field public static final java.lang.String AUTH_TYPE = "authtype"; @@ -39333,8 +39343,8 @@ package android.telecom { method public final void setActive(); method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); method public final void setConnectionCapabilities(int); - method public final void setConnectionElapsedTime(long); method public final void setConnectionProperties(int); + method public final void setConnectionStartElapsedRealTime(long); method public final void setConnectionTime(long); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); @@ -40770,13 +40780,16 @@ package android.telephony { method public java.lang.String getNumber(); method public int getSimSlotIndex(); method public int getSubscriptionId(); + method public boolean isEmbedded(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR; } public class SubscriptionManager { method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + method public boolean canManageSubscription(android.telephony.SubscriptionInfo); method public static android.telephony.SubscriptionManager from(android.content.Context); + method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList(); method public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int); method public int getActiveSubscriptionInfoCount(); method public int getActiveSubscriptionInfoCountMax(); @@ -41119,6 +41132,44 @@ package android.telephony.data { } +package android.telephony.euicc { + + public final class DownloadableSubscription implements android.os.Parcelable { + method public int describeContents(); + method public static android.telephony.euicc.DownloadableSubscription forActivationCode(java.lang.String); + method public java.lang.String getConfirmationCode(); + method public java.lang.String getEncodedActivationCode(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.euicc.DownloadableSubscription> CREATOR; + } + + public final class EuiccInfo implements android.os.Parcelable { + ctor public EuiccInfo(java.lang.String); + method public int describeContents(); + method public java.lang.String getOsVersion(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccInfo> CREATOR; + } + + public class EuiccManager { + method public void deleteSubscription(int, android.app.PendingIntent); + method public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent); + method public java.lang.String getEid(); + method public android.telephony.euicc.EuiccInfo getEuiccInfo(); + method public boolean isEnabled(); + method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException; + method public void switchToSubscription(int, android.app.PendingIntent); + field public static final java.lang.String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS"; + field public static final java.lang.String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE"; + field public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2; // 0x2 + field public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; // 0x0 + field public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; // 0x1 + field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE"; + field public static final java.lang.String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon"; + } + +} + package android.telephony.gsm { public class GsmCellLocation extends android.telephony.CellLocation { diff --git a/api/system-current.txt b/api/system-current.txt index 6441b7f0fcb4..56b5923f1911 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -20,6 +20,7 @@ package android { field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET"; field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE"; field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH"; + field public static final java.lang.String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE"; field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE"; field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; field public static final java.lang.String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"; @@ -172,6 +173,7 @@ package android { field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY"; field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS"; field public static final java.lang.String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE"; + field public static final java.lang.String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"; field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES"; field public static final java.lang.String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE"; field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS"; @@ -695,6 +697,7 @@ package android.content { method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); field public static final java.lang.String BACKUP_SERVICE = "backup"; field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub"; + field public static final java.lang.String EUICC_CARD_SERVICE = "euicc_card"; field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score"; field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock"; @@ -3506,6 +3509,7 @@ package android.provider { public static final class Settings.Global extends android.provider.Settings.NameValueTable { method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean); method public static void resetToDefaults(android.content.ContentResolver, java.lang.String); + field public static final java.lang.String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus"; field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update"; field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on"; field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess"; @@ -3548,6 +3552,125 @@ package android.security.keystore { } +package android.service.euicc { + + public final class EuiccProfileInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.service.carrier.CarrierIdentifier getCarrierIdentifier(); + method public java.lang.String getIccid(); + method public java.lang.String getNickname(); + method public int getPolicyRules(); + method public int getProfileClass(); + method public java.lang.String getProfileName(); + method public java.lang.String getServiceProviderName(); + method public int getState(); + method public java.util.List<android.telephony.UiccAccessRule> getUiccAccessRules(); + method public boolean hasPolicyRule(int); + method public boolean hasPolicyRules(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.euicc.EuiccProfileInfo> CREATOR; + field public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 4; // 0x4 + field public static final int POLICY_RULE_DO_NOT_DELETE = 2; // 0x2 + field public static final int POLICY_RULE_DO_NOT_DISABLE = 1; // 0x1 + field public static final int PROFILE_CLASS_OPERATIONAL = 2; // 0x2 + field public static final int PROFILE_CLASS_PROVISIONING = 1; // 0x1 + field public static final int PROFILE_CLASS_TESTING = 0; // 0x0 + field public static final int PROFILE_STATE_DISABLED = 0; // 0x0 + field public static final int PROFILE_STATE_ENABLED = 1; // 0x1 + } + + public static final class EuiccProfileInfo.Builder { + ctor public EuiccProfileInfo.Builder(java.lang.String); + ctor public EuiccProfileInfo.Builder(android.service.euicc.EuiccProfileInfo); + method public android.service.euicc.EuiccProfileInfo build(); + method public android.service.euicc.EuiccProfileInfo.Builder setCarrierIdentifier(android.service.carrier.CarrierIdentifier); + method public android.service.euicc.EuiccProfileInfo.Builder setIccid(java.lang.String); + method public android.service.euicc.EuiccProfileInfo.Builder setNickname(java.lang.String); + method public android.service.euicc.EuiccProfileInfo.Builder setPolicyRules(int); + method public android.service.euicc.EuiccProfileInfo.Builder setProfileClass(int); + method public android.service.euicc.EuiccProfileInfo.Builder setProfileName(java.lang.String); + method public android.service.euicc.EuiccProfileInfo.Builder setServiceProviderName(java.lang.String); + method public android.service.euicc.EuiccProfileInfo.Builder setState(int); + method public android.service.euicc.EuiccProfileInfo.Builder setUiccAccessRule(java.util.List<android.telephony.UiccAccessRule>); + } + + public static abstract class EuiccProfileInfo.PolicyRule implements java.lang.annotation.Annotation { + } + + public static abstract class EuiccProfileInfo.ProfileClass implements java.lang.annotation.Annotation { + } + + public static abstract class EuiccProfileInfo.ProfileState implements java.lang.annotation.Annotation { + } + + public abstract class EuiccService extends android.app.Service { + ctor public EuiccService(); + method public android.os.IBinder onBind(android.content.Intent); + method public abstract int onDeleteSubscription(int, java.lang.String); + method public abstract int onDownloadSubscription(int, android.telephony.euicc.DownloadableSubscription, boolean, boolean); + method public abstract int onEraseSubscriptions(int); + method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean); + method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean); + method public abstract java.lang.String onGetEid(int); + method public abstract android.telephony.euicc.EuiccInfo onGetEuiccInfo(int); + method public abstract android.service.euicc.GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int); + method public abstract int onGetOtaStatus(int); + method public abstract int onRetainSubscriptionsForFactoryReset(int); + method public abstract void onStartOtaIfNecessary(int, android.service.euicc.EuiccService.OtaStatusChangedCallback); + method public abstract int onSwitchToSubscription(int, java.lang.String, boolean); + method public abstract int onUpdateSubscriptionNickname(int, java.lang.String, java.lang.String); + field public static final java.lang.String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS"; + field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; + field public static final java.lang.String ACTION_RESOLVE_CONFIRMATION_CODE = "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE"; + field public static final java.lang.String ACTION_RESOLVE_DEACTIVATE_SIM = "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM"; + field public static final java.lang.String ACTION_RESOLVE_NO_PRIVILEGES = "android.service.euicc.action.RESOLVE_NO_PRIVILEGES"; + field public static final java.lang.String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI"; + field public static final java.lang.String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService"; + field public static final java.lang.String EXTRA_RESOLUTION_CALLING_PACKAGE = "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE"; + field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE"; + field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED"; + field public static final java.lang.String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT"; + field public static final int RESULT_FIRST_USER = 1; // 0x1 + field public static final int RESULT_MUST_DEACTIVATE_SIM = -1; // 0xffffffff + field public static final int RESULT_NEED_CONFIRMATION_CODE = -2; // 0xfffffffe + field public static final int RESULT_OK = 0; // 0x0 + } + + public static abstract class EuiccService.OtaStatusChangedCallback { + ctor public EuiccService.OtaStatusChangedCallback(); + method public abstract void onOtaStatusChanged(int); + } + + public final class GetDefaultDownloadableSubscriptionListResult implements android.os.Parcelable { + ctor public GetDefaultDownloadableSubscriptionListResult(int, android.telephony.euicc.DownloadableSubscription[]); + method public int describeContents(); + method public java.util.List<android.telephony.euicc.DownloadableSubscription> getDownloadableSubscriptions(); + method public int getResult(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.euicc.GetDefaultDownloadableSubscriptionListResult> CREATOR; + } + + public final class GetDownloadableSubscriptionMetadataResult implements android.os.Parcelable { + ctor public GetDownloadableSubscriptionMetadataResult(int, android.telephony.euicc.DownloadableSubscription); + method public int describeContents(); + method public android.telephony.euicc.DownloadableSubscription getDownloadableSubscription(); + method public int getResult(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.euicc.GetDownloadableSubscriptionMetadataResult> CREATOR; + } + + public final class GetEuiccProfileInfoListResult implements android.os.Parcelable { + ctor public GetEuiccProfileInfoListResult(int, android.service.euicc.EuiccProfileInfo[], boolean); + method public int describeContents(); + method public boolean getIsRemovable(); + method public java.util.List<android.service.euicc.EuiccProfileInfo> getProfiles(); + method public int getResult(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.euicc.GetEuiccProfileInfoListResult> CREATOR; + } + +} + package android.service.notification { public final class Adjustment implements android.os.Parcelable { @@ -4066,8 +4189,14 @@ package android.telephony { field public static final int RESULT_SYSTEM_ERROR = 15; // 0xf } + public class SubscriptionInfo implements android.os.Parcelable { + method public java.util.List<android.telephony.UiccAccessRule> getAccessRules(); + } + public class SubscriptionManager { + method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList(); method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int); + method public void requestEmbeddedSubscriptionInfoListRefresh(); method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>); } @@ -4186,23 +4315,30 @@ package android.telephony { field public static final int SIM_STATE_PRESENT = 11; // 0xb } + public final class UiccAccessRule implements android.os.Parcelable { + ctor public UiccAccessRule(byte[], java.lang.String, long); + method public int describeContents(); + method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo); + method public int getCarrierPrivilegeStatus(android.content.pm.Signature, java.lang.String); + method public java.lang.String getPackageName(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR; + } + public class UiccSlotInfo implements android.os.Parcelable { - ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int); + ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int); method public int describeContents(); method public java.lang.String getCardId(); method public int getCardStateInfo(); method public boolean getIsActive(); method public boolean getIsEuicc(); + method public int getLogicalSlotIdx(); method public void writeToParcel(android.os.Parcel, int); field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1 field public static final int CARD_STATE_INFO_ERROR = 3; // 0x3 field public static final int CARD_STATE_INFO_PRESENT = 2; // 0x2 field public static final int CARD_STATE_INFO_RESTRICTED = 4; // 0x4 field public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR; - field public final java.lang.String cardId; - field public final int cardStateInfo; - field public final boolean isActive; - field public final boolean isEuicc; } public abstract class VisualVoicemailService extends android.app.Service { @@ -4299,6 +4435,125 @@ package android.telephony.data { } +package android.telephony.euicc { + + public final class DownloadableSubscription implements android.os.Parcelable { + method public java.util.List<android.telephony.UiccAccessRule> getAccessRules(); + method public java.lang.String getCarrierName(); + } + + public static final class DownloadableSubscription.Builder { + ctor public DownloadableSubscription.Builder(); + ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription); + method public android.telephony.euicc.DownloadableSubscription build(); + method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>); + method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(java.lang.String); + method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(java.lang.String); + method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(java.lang.String); + } + + public class EuiccCardManager { + method public void authenticateServer(java.lang.String, java.lang.String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void cancelSession(java.lang.String, byte[], int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void deleteProfile(java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void disableProfile(java.lang.String, java.lang.String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void listNotifications(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); + method public void loadBoundProfilePackage(java.lang.String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void prepareDownload(java.lang.String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void removeNotificationFromList(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void requestAllProfiles(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo[]>); + method public void requestDefaultSmdpAddress(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>); + method public void requestEuiccChallenge(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void requestEuiccInfo1(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void requestEuiccInfo2(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void requestProfile(java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); + method public void requestRulesAuthTable(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccRulesAuthTable>); + method public void requestSmdsAddress(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>); + method public void resetMemory(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void retrieveNotification(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification>); + method public void retrieveNotificationList(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); + method public void setDefaultSmdpAddress(java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void setNickname(java.lang.String, java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void switchToProfile(java.lang.String, java.lang.String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); + field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0 + field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1 + field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3 + field public static final int CANCEL_REASON_TIMEOUT = 2; // 0x2 + field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2 + field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1 + field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4 + field public static final int RESULT_OK = 0; // 0x0 + field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff + } + + public static abstract class EuiccCardManager.CancelReason implements java.lang.annotation.Annotation { + } + + public static abstract class EuiccCardManager.ResetOption implements java.lang.annotation.Annotation { + } + + public static abstract interface EuiccCardManager.ResultCallback<T> { + method public abstract void onComplete(int, T); + } + + public class EuiccManager { + method public void continueOperation(android.content.Intent, android.os.Bundle); + method public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent); + method public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent); + method public int getOtaStatus(); + field public static final java.lang.String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED"; + field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; + field public static final int EUICC_OTA_FAILED = 2; // 0x2 + field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1 + field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4 + field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5 + field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3 + field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION"; + field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS"; + } + + public static abstract class EuiccManager.OtaStatus implements java.lang.annotation.Annotation { + } + + public final class EuiccNotification implements android.os.Parcelable { + ctor public EuiccNotification(int, java.lang.String, int, byte[]); + method public int describeContents(); + method public byte[] getData(); + method public int getEvent(); + method public int getSeq(); + method public java.lang.String getTargetAddr(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int ALL_EVENTS = 15; // 0xf + field public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccNotification> CREATOR; + field public static final int EVENT_DELETE = 8; // 0x8 + field public static final int EVENT_DISABLE = 4; // 0x4 + field public static final int EVENT_ENABLE = 2; // 0x2 + field public static final int EVENT_INSTALL = 1; // 0x1 + } + + public static abstract class EuiccNotification.Event implements java.lang.annotation.Annotation { + } + + public final class EuiccRulesAuthTable implements android.os.Parcelable { + method public int describeContents(); + method public int findIndex(int, android.service.carrier.CarrierIdentifier); + method public boolean hasPolicyRuleFlag(int, int); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccRulesAuthTable> CREATOR; + field public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1; // 0x1 + } + + public static final class EuiccRulesAuthTable.Builder { + ctor public EuiccRulesAuthTable.Builder(int); + method public android.telephony.euicc.EuiccRulesAuthTable.Builder add(int, java.util.List<android.service.carrier.CarrierIdentifier>, int); + method public android.telephony.euicc.EuiccRulesAuthTable build(); + } + + public static abstract class EuiccRulesAuthTable.PolicyRuleFlag implements java.lang.annotation.Annotation { + } + +} + package android.telephony.ims { public final class ImsCallForwardInfo implements android.os.Parcelable { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 121b58a2b104..d1500a860883 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3134,9 +3134,6 @@ public class DevicePolicyManager { /** * Flag for {@link #wipeData(int)}: also erase the device's eUICC data. - * - * TODO(b/35851809): make this public. - * @hide */ public static final int WIPE_EUICC = 0x0004; diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 6c8fe2e399fa..dc761521fbdc 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -2303,6 +2303,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.HID_DEVICE) { BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener); return true; + } else if (profile == BluetoothProfile.HEARING_AID) { + BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener); + return true; } else { return false; } @@ -2385,6 +2388,9 @@ public final class BluetoothAdapter { BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy; hidDevice.close(); break; + case BluetoothProfile.HEARING_AID: + BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; + hearingAid.close(); } } diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java new file mode 100644 index 000000000000..647e0d033fb7 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -0,0 +1,693 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.Manifest; +import android.annotation.RequiresPermission; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * This class provides the public APIs to control the Bluetooth Hearing Aid + * profile. + * + * <p>BluetoothHearingAid is a proxy object for controlling the Bluetooth Hearing Aid + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothHearingAid proxy object. + * + * <p> Each method is protected with its appropriate permission. + * @hide + */ +public final class BluetoothHearingAid implements BluetoothProfile { + private static final String TAG = "BluetoothHearingAid"; + private static final boolean DBG = false; + private static final boolean VDBG = false; + + /** + * Intent used to broadcast the change in connection state of the Hearing Aid + * 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. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED"; + + /** + * Intent used to broadcast the change in the Playing state of the Hearing Aid + * 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. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PLAYING_STATE_CHANGED = + "android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED"; + + /** + * Intent used to broadcast the selection of a connected device as active. + * + * <p>This intent will have one extra: + * <ul> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can + * be null if no device is active. </li> + * </ul> + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_ACTIVE_DEVICE_CHANGED = + "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED"; + + /** + * Hearing Aid 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; + + /** + * Hearing Aid 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; + + /** This device represents Left Hearing Aid. */ + public static final int SIDE_LEFT = IBluetoothHearingAid.SIDE_LEFT; + + /** This device represents Right Hearing Aid. */ + public static final int SIDE_RIGHT = IBluetoothHearingAid.SIDE_RIGHT; + + /** This device is Monaural. */ + public static final int MODE_MONAURAL = IBluetoothHearingAid.MODE_MONAURAL; + + /** This device is Binaural (should receive only left or right audio). */ + public static final int MODE_BINAURAL = IBluetoothHearingAid.MODE_BINAURAL; + + /** Can't read ClientID for this device */ + public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID; + + private Context mContext; + private ServiceListener mServiceListener; + private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); + @GuardedBy("mServiceLock") + private IBluetoothHearingAid mService; + private BluetoothAdapter mAdapter; + + private final 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..."); + try { + mServiceLock.writeLock().lock(); + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.writeLock().unlock(); + } + } else { + try { + mServiceLock.readLock().lock(); + if (mService == null) { + if (VDBG) Log.d(TAG, "Binding service..."); + doBind(); + } + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.readLock().unlock(); + } + } + } + }; + + /** + * Create a BluetoothHearingAid proxy object for interacting with the local + * Bluetooth Hearing Aid service. + */ + /*package*/ BluetoothHearingAid(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(); + } + + void doBind() { + Intent intent = new Intent(IBluetoothHearingAid.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 Hearing Aid Service with " + intent); + return; + } + } + + /*package*/ void close() { + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG, "", e); + } + } + + try { + mServiceLock.writeLock().lock(); + if (mService != null) { + mService = null; + mContext.unbindService(mConnection); + } + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.writeLock().unlock(); + } + } + + @Override + public void finalize() { + // The empty finalize needs to be kept or the + // cts signature tests would fail. + } + + /** + * Initiate connection to a profile of the remote bluetooth device. + * + * <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 + ")"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() && isValidDevice(device)) { + return mService.connect(device); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * 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 + ")"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() && isValidDevice(device)) { + return mService.disconnect(device); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getConnectedDevices(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getDevicesMatchingConnectionStates(states); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { + return mService.getConnectionState(device); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Set priority of the profile + * + * <p> The device should already be paired. + * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager + * {@link #PRIORITY_OFF}, + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @param device Paired bluetooth device + * @param priority + * @return true if priority is set, false on error + * @hide + */ + public boolean setPriority(BluetoothDevice device, int priority) { + if (DBG) log("setPriority(" + device + ", " + priority + ")"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; + } + return mService.setPriority(device, priority); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Get the priority of the profile. + * + * <p> The priority can be any of: + * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, + * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} + * + * @param device Bluetooth device + * @return priority of the device + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getPriority(BluetoothDevice device) { + if (VDBG) log("getPriority(" + device + ")"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { + return mService.getPriority(device); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.PRIORITY_OFF; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.PRIORITY_OFF; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * 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 + ">"; + } + } + + /** + * Get the volume of the device. + * + * <p> The volume is between -128 dB (mute) to 0 dB. + * + * @return volume of the hearing aid device. + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getVolume() { + if (VDBG) { + log("getVolume()"); + } + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getVolume(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return 0; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return 0; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Tells remote device to adjust volume. Uses the following values: + * <ul> + * <li>{@link AudioManager#ADJUST_LOWER}</li> + * <li>{@link AudioManager#ADJUST_RAISE}</li> + * <li>{@link AudioManager#ADJUST_MUTE}</li> + * <li>{@link AudioManager#ADJUST_UNMUTE}</li> + * </ul> + * + * @param direction One of the supported adjust values. + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public void adjustVolume(int direction) { + if (DBG) log("adjustVolume(" + direction + ")"); + + try { + mServiceLock.readLock().lock(); + + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + return; + } + + if (!isEnabled()) return; + + mService.adjustVolume(direction); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Tells remote device to set an absolute volume. + * + * @param volume Absolute volume to be set on remote + * @hide + */ + public void setVolume(int volume) { + if (DBG) Log.d(TAG, "setVolume(" + volume + ")"); + + try { + mServiceLock.readLock().lock(); + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + return; + } + + if (!isEnabled()) return; + + mService.setVolume(volume); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Get the CustomerId of the device. + * + * @param device Bluetooth device + * @return the CustomerId of the device + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public long getHiSyncId(BluetoothDevice device) { + if (VDBG) { + log("getCustomerId(" + device + ")"); + } + try { + mServiceLock.readLock().lock(); + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + return HI_SYNC_ID_INVALID; + } + + if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID; + + return mService.getHiSyncId(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return HI_SYNC_ID_INVALID; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Get the side of the device. + * + * @param device Bluetooth device. + * @return SIDE_LEFT or SIDE_RIGHT + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getDeviceSide(BluetoothDevice device) { + if (VDBG) { + log("getDeviceSide(" + device + ")"); + } + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { + return mService.getDeviceSide(device); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return SIDE_LEFT; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return SIDE_LEFT; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Get the mode of the device. + * + * @param device Bluetooth device + * @return MODE_MONAURAL or MODE_BINAURAL + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getDeviceMode(BluetoothDevice device) { + if (VDBG) { + log("getDeviceMode(" + device + ")"); + } + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { + return mService.getDeviceMode(device); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return MODE_MONAURAL; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return MODE_MONAURAL; + } finally { + mServiceLock.readLock().unlock(); + } + } + + private final ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "Proxy object connected"); + try { + mServiceLock.writeLock().lock(); + mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service)); + } finally { + mServiceLock.writeLock().unlock(); + } + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID, + BluetoothHearingAid.this); + } + } + + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "Proxy object disconnected"); + try { + mServiceLock.writeLock().lock(); + mService = null; + } finally { + mServiceLock.writeLock().unlock(); + } + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID); + } + } + }; + + 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/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 0e2263f773b8..656188fbdfb8 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -165,12 +165,19 @@ public interface BluetoothProfile { public static final int OPP = 20; /** + * Hearing Aid Device + * + * @hide + */ + int HEARING_AID = 21; + + /** * Max profile ID. This value should be updated whenever a new profile is added to match * the largest value assigned to a profile. * * @hide */ - public static final int MAX_PROFILE_ID = 20; + int MAX_PROFILE_ID = 21; /** * Default priority for devices that we try to auto-connect to and diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 76cb3f5b548e..0a0d21498032 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -79,6 +79,9 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid SAP = ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); + /* TODO: b/69623109 update this value. It will change to 16bit UUID!! */ + public static final ParcelUuid HearingAid = + ParcelUuid.fromString("7312C48F-22CC-497F-85FD-A0616A3B9E05"); public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 2859326107b8..d13575822d4a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3583,10 +3583,8 @@ public abstract class Context { * * @see #getSystemService * @see android.telephony.euicc.EuiccManager - * TODO(b/35851809): Unhide this API. - * @hide */ - public static final String EUICC_SERVICE = "euicc_service"; + public static final String EUICC_SERVICE = "euicc"; /** * Use with {@link #getSystemService(String)} to retrieve a @@ -3594,10 +3592,10 @@ public abstract class Context { * * @see #getSystemService(String) * @see android.telephony.euicc.EuiccCardManager - * TODO(b/35851809): Make this a SystemApi. * @hide */ - public static final String EUICC_CARD_SERVICE = "euicc_card_service"; + @SystemApi + public static final String EUICC_CARD_SERVICE = "euicc_card"; /** * Use with {@link #getSystemService(String)} to retrieve a diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 89751dadd29d..e7bf974aee20 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2078,8 +2078,6 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device * supports embedded subscriptions on eUICCs. - * TODO(b/35851809): Make this public. - * @hide */ @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_TELEPHONY_EUICC = "android.hardware.telephony.euicc"; diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 6a262e2c87ca..8599f47c6245 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -218,6 +218,25 @@ public final class IpSecConfig implements Parcelable { @VisibleForTesting public IpSecConfig() {} + /** Copy constructor */ + @VisibleForTesting + public IpSecConfig(IpSecConfig c) { + mMode = c.mMode; + mSourceAddress = c.mSourceAddress; + mDestinationAddress = c.mDestinationAddress; + mNetwork = c.mNetwork; + mSpiResourceId = c.mSpiResourceId; + mEncryption = c.mEncryption; + mAuthentication = c.mAuthentication; + mAuthenticatedEncryption = c.mAuthenticatedEncryption; + mEncapType = c.mEncapType; + mEncapSocketResourceId = c.mEncapSocketResourceId; + mEncapRemotePort = c.mEncapRemotePort; + mNattKeepaliveInterval = c.mNattKeepaliveInterval; + mMarkValue = c.mMarkValue; + mMarkMask = c.mMarkMask; + } + private IpSecConfig(Parcel in) { mMode = in.readInt(); mSourceAddress = in.readString(); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 38759a9183f2..60e96f943401 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -84,9 +84,11 @@ public final class IpSecTransform implements AutoCloseable { @Retention(RetentionPolicy.SOURCE) public @interface EncapType {} - private IpSecTransform(Context context, IpSecConfig config) { + /** @hide */ + @VisibleForTesting + public IpSecTransform(Context context, IpSecConfig config) { mContext = context; - mConfig = config; + mConfig = new IpSecConfig(config); mResourceId = INVALID_RESOURCE_ID; } @@ -143,6 +145,18 @@ public final class IpSecTransform implements AutoCloseable { } /** + * Equals method used for testing + * + * @hide + */ + @VisibleForTesting + public static boolean equals(IpSecTransform lhs, IpSecTransform rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return IpSecConfig.equals(lhs.getConfig(), rhs.getConfig()) + && lhs.mResourceId == rhs.mResourceId; + } + + /** * Deactivate this {@code IpSecTransform} and free allocated resources. * * <p>Deactivating a transform while it is still applied to a socket will result in errors on diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index 3a40cf4bf8a3..3cd37bf4fbdd 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -1,3 +1,5 @@ +set noparent + ek@google.com jsharkey@android.com jchalard@google.com diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 670f7949dd19..4a976403e7a8 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -61,18 +61,27 @@ public class ZygoteProcess { /** * The name of the socket used to communicate with the primary zygote. */ - private final String mSocket; + private final LocalSocketAddress mSocket; /** * The name of the secondary (alternate ABI) zygote socket. */ - private final String mSecondarySocket; + private final LocalSocketAddress mSecondarySocket; public ZygoteProcess(String primarySocket, String secondarySocket) { + this(new LocalSocketAddress(primarySocket, LocalSocketAddress.Namespace.RESERVED), + new LocalSocketAddress(secondarySocket, LocalSocketAddress.Namespace.RESERVED)); + } + + public ZygoteProcess(LocalSocketAddress primarySocket, LocalSocketAddress secondarySocket) { mSocket = primarySocket; mSecondarySocket = secondarySocket; } + public LocalSocketAddress getPrimarySocketAddress() { + return mSocket; + } + /** * State for communicating with the zygote process. */ @@ -92,14 +101,13 @@ public class ZygoteProcess { this.abiList = abiList; } - public static ZygoteState connect(String socketAddress) throws IOException { + public static ZygoteState connect(LocalSocketAddress address) throws IOException { DataInputStream zygoteInputStream = null; BufferedWriter zygoteWriter = null; final LocalSocket zygoteSocket = new LocalSocket(); try { - zygoteSocket.connect(new LocalSocketAddress(socketAddress, - LocalSocketAddress.Namespace.RESERVED)); + zygoteSocket.connect(address); zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream()); @@ -115,8 +123,8 @@ public class ZygoteProcess { } String abiListString = getAbiList(zygoteWriter, zygoteInputStream); - Log.i("Zygote", "Process: zygote socket " + socketAddress + " opened, supported ABIS: " - + abiListString); + Log.i("Zygote", "Process: zygote socket " + address.getNamespace() + "/" + + address.getName() + " opened, supported ABIS: " + abiListString); return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter, Arrays.asList(abiListString.split(","))); @@ -514,9 +522,19 @@ public class ZygoteProcess { * @param socketName The name of the socket to connect to. */ public static void waitForConnectionToZygote(String socketName) { + final LocalSocketAddress address = + new LocalSocketAddress(socketName, LocalSocketAddress.Namespace.RESERVED); + waitForConnectionToZygote(address); + } + + /** + * Try connecting to the Zygote over and over again until we hit a time-out. + * @param address The name of the socket to connect to. + */ + public static void waitForConnectionToZygote(LocalSocketAddress address) { for (int n = 20; n >= 0; n--) { try { - final ZygoteState zs = ZygoteState.connect(socketName); + final ZygoteState zs = ZygoteState.connect(address); zs.close(); return; } catch (IOException ioe) { @@ -529,6 +547,6 @@ public class ZygoteProcess { } catch (InterruptedException ie) { } } - Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + socketName); + Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + address.getName()); } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7ad4373e7907..5dd4681112f9 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7838,9 +7838,8 @@ public final class Settings { * * @see android.service.euicc.EuiccService * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus"; /** diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java index 8e752d1c6c1d..cb4f10455ec9 100644 --- a/core/java/android/service/euicc/EuiccProfileInfo.java +++ b/core/java/android/service/euicc/EuiccProfileInfo.java @@ -17,6 +17,7 @@ package android.service.euicc; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.service.carrier.CarrierIdentifier; @@ -26,15 +27,15 @@ import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import java.util.List; import java.util.Objects; /** * Information about an embedded profile (subscription) on an eUICC. * * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ +@SystemApi public final class EuiccProfileInfo implements Parcelable { /** Profile policy rules (bit mask) */ @@ -44,6 +45,7 @@ public final class EuiccProfileInfo implements Parcelable { POLICY_RULE_DO_NOT_DELETE, POLICY_RULE_DELETE_AFTER_DISABLING }) + /** @hide */ public @interface PolicyRule {} /** Once this profile is enabled, it cannot be disabled. */ public static final int POLICY_RULE_DO_NOT_DISABLE = 1; @@ -60,6 +62,7 @@ public final class EuiccProfileInfo implements Parcelable { PROFILE_CLASS_OPERATIONAL, PROFILE_CLASS_UNSET }) + /** @hide */ public @interface ProfileClass {} /** Testing profiles */ public static final int PROFILE_CLASS_TESTING = 0; @@ -80,6 +83,7 @@ public final class EuiccProfileInfo implements Parcelable { PROFILE_STATE_ENABLED, PROFILE_STATE_UNSET }) + /** @hide */ public @interface ProfileState {} /** Disabled profiles */ public static final int PROFILE_STATE_DISABLED = 0; @@ -92,34 +96,34 @@ public final class EuiccProfileInfo implements Parcelable { public static final int PROFILE_STATE_UNSET = -1; /** The iccid of the subscription. */ - public final String iccid; + private final String mIccid; /** An optional nickname for the subscription. */ - public final @Nullable String nickname; + private final @Nullable String mNickname; /** The service provider name for the subscription. */ - public final String serviceProviderName; + private final String mServiceProviderName; /** The profile name for the subscription. */ - public final String profileName; + private final String mProfileName; /** Profile class for the subscription. */ - @ProfileClass public final int profileClass; + @ProfileClass private final int mProfileClass; /** The profile state of the subscription. */ - @ProfileState public final int state; + @ProfileState private final int mState; /** The operator Id of the subscription. */ - public final CarrierIdentifier carrierIdentifier; + private final CarrierIdentifier mCarrierIdentifier; /** The policy rules of the subscription. */ - @PolicyRule public final int policyRules; + @PolicyRule private final int mPolicyRules; /** * Optional access rules defining which apps can manage this subscription. If unset, only the * platform can manage it. */ - public final @Nullable UiccAccessRule[] accessRules; + private final @Nullable UiccAccessRule[] mAccessRules; public static final Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() { @Override @@ -144,51 +148,51 @@ public final class EuiccProfileInfo implements Parcelable { if (!TextUtils.isDigitsOnly(iccid)) { throw new IllegalArgumentException("iccid contains invalid characters: " + iccid); } - this.iccid = iccid; - this.accessRules = accessRules; - this.nickname = nickname; - - this.serviceProviderName = null; - this.profileName = null; - this.profileClass = PROFILE_CLASS_UNSET; - this.state = PROFILE_CLASS_UNSET; - this.carrierIdentifier = null; - this.policyRules = 0; + this.mIccid = iccid; + this.mAccessRules = accessRules; + this.mNickname = nickname; + + this.mServiceProviderName = null; + this.mProfileName = null; + this.mProfileClass = PROFILE_CLASS_UNSET; + this.mState = PROFILE_STATE_UNSET; + this.mCarrierIdentifier = null; + this.mPolicyRules = 0; } private EuiccProfileInfo(Parcel in) { - iccid = in.readString(); - nickname = in.readString(); - serviceProviderName = in.readString(); - profileName = in.readString(); - profileClass = in.readInt(); - state = in.readInt(); + mIccid = in.readString(); + mNickname = in.readString(); + mServiceProviderName = in.readString(); + mProfileName = in.readString(); + mProfileClass = in.readInt(); + mState = in.readInt(); byte exist = in.readByte(); if (exist == (byte) 1) { - carrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in); + mCarrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in); } else { - carrierIdentifier = null; + mCarrierIdentifier = null; } - policyRules = in.readInt(); - accessRules = in.createTypedArray(UiccAccessRule.CREATOR); + mPolicyRules = in.readInt(); + mAccessRules = in.createTypedArray(UiccAccessRule.CREATOR); } @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(iccid); - dest.writeString(nickname); - dest.writeString(serviceProviderName); - dest.writeString(profileName); - dest.writeInt(profileClass); - dest.writeInt(state); - if (carrierIdentifier != null) { + dest.writeString(mIccid); + dest.writeString(mNickname); + dest.writeString(mServiceProviderName); + dest.writeString(mProfileName); + dest.writeInt(mProfileClass); + dest.writeInt(mState); + if (mCarrierIdentifier != null) { dest.writeByte((byte) 1); - carrierIdentifier.writeToParcel(dest, flags); + mCarrierIdentifier.writeToParcel(dest, flags); } else { dest.writeByte((byte) 0); } - dest.writeInt(policyRules); - dest.writeTypedArray(accessRules, flags); + dest.writeInt(mPolicyRules); + dest.writeTypedArray(mAccessRules, flags); } @Override @@ -198,45 +202,50 @@ public final class EuiccProfileInfo implements Parcelable { /** The builder to build a new {@link EuiccProfileInfo} instance. */ public static final class Builder { - public String iccid; - public UiccAccessRule[] accessRules; - public String nickname; - public String serviceProviderName; - public String profileName; - @ProfileClass public int profileClass; - @ProfileState public int state; - public CarrierIdentifier carrierIdentifier; - @PolicyRule public int policyRules; - - public Builder() {} + private String mIccid; + private List<UiccAccessRule> mAccessRules; + private String mNickname; + private String mServiceProviderName; + private String mProfileName; + @ProfileClass private int mProfileClass; + @ProfileState private int mState; + private CarrierIdentifier mCarrierIdentifier; + @PolicyRule private int mPolicyRules; + + public Builder(String value) { + if (!TextUtils.isDigitsOnly(value)) { + throw new IllegalArgumentException("iccid contains invalid characters: " + value); + } + mIccid = value; + } public Builder(EuiccProfileInfo baseProfile) { - iccid = baseProfile.iccid; - nickname = baseProfile.nickname; - serviceProviderName = baseProfile.serviceProviderName; - profileName = baseProfile.profileName; - profileClass = baseProfile.profileClass; - state = baseProfile.state; - carrierIdentifier = baseProfile.carrierIdentifier; - policyRules = baseProfile.policyRules; - accessRules = baseProfile.accessRules; + mIccid = baseProfile.mIccid; + mNickname = baseProfile.mNickname; + mServiceProviderName = baseProfile.mServiceProviderName; + mProfileName = baseProfile.mProfileName; + mProfileClass = baseProfile.mProfileClass; + mState = baseProfile.mState; + mCarrierIdentifier = baseProfile.mCarrierIdentifier; + mPolicyRules = baseProfile.mPolicyRules; + mAccessRules = Arrays.asList(baseProfile.mAccessRules); } /** Builds the profile instance. */ public EuiccProfileInfo build() { - if (iccid == null) { + if (mIccid == null) { throw new IllegalStateException("ICCID must be set for a profile."); } return new EuiccProfileInfo( - iccid, - nickname, - serviceProviderName, - profileName, - profileClass, - state, - carrierIdentifier, - policyRules, - accessRules); + mIccid, + mNickname, + mServiceProviderName, + mProfileName, + mProfileClass, + mState, + mCarrierIdentifier, + mPolicyRules, + mAccessRules); } /** Sets the iccId of the subscription. */ @@ -244,55 +253,55 @@ public final class EuiccProfileInfo implements Parcelable { if (!TextUtils.isDigitsOnly(value)) { throw new IllegalArgumentException("iccid contains invalid characters: " + value); } - iccid = value; + mIccid = value; return this; } /** Sets the nickname of the subscription. */ public Builder setNickname(String value) { - nickname = value; + mNickname = value; return this; } /** Sets the service provider name of the subscription. */ public Builder setServiceProviderName(String value) { - serviceProviderName = value; + mServiceProviderName = value; return this; } /** Sets the profile name of the subscription. */ public Builder setProfileName(String value) { - profileName = value; + mProfileName = value; return this; } /** Sets the profile class of the subscription. */ public Builder setProfileClass(@ProfileClass int value) { - profileClass = value; + mProfileClass = value; return this; } /** Sets the state of the subscription. */ public Builder setState(@ProfileState int value) { - state = value; + mState = value; return this; } /** Sets the carrier identifier of the subscription. */ public Builder setCarrierIdentifier(CarrierIdentifier value) { - carrierIdentifier = value; + mCarrierIdentifier = value; return this; } /** Sets the policy rules of the subscription. */ public Builder setPolicyRules(@PolicyRule int value) { - policyRules = value; + mPolicyRules = value; return this; } /** Sets the access rules of the subscription. */ - public Builder setUiccAccessRule(@Nullable UiccAccessRule[] value) { - accessRules = value; + public Builder setUiccAccessRule(@Nullable List<UiccAccessRule> value) { + mAccessRules = value; return this; } } @@ -306,75 +315,81 @@ public final class EuiccProfileInfo implements Parcelable { @ProfileState int state, CarrierIdentifier carrierIdentifier, @PolicyRule int policyRules, - @Nullable UiccAccessRule[] accessRules) { - this.iccid = iccid; - this.nickname = nickname; - this.serviceProviderName = serviceProviderName; - this.profileName = profileName; - this.profileClass = profileClass; - this.state = state; - this.carrierIdentifier = carrierIdentifier; - this.policyRules = policyRules; - this.accessRules = accessRules; + @Nullable List<UiccAccessRule> accessRules) { + this.mIccid = iccid; + this.mNickname = nickname; + this.mServiceProviderName = serviceProviderName; + this.mProfileName = profileName; + this.mProfileClass = profileClass; + this.mState = state; + this.mCarrierIdentifier = carrierIdentifier; + this.mPolicyRules = policyRules; + if (accessRules != null && accessRules.size() > 0) { + this.mAccessRules = accessRules.toArray(new UiccAccessRule[accessRules.size()]); + } else { + this.mAccessRules = null; + } } /** Gets the ICCID string. */ public String getIccid() { - return iccid; + return mIccid; } /** Gets the access rules. */ @Nullable - public UiccAccessRule[] getUiccAccessRules() { - return accessRules; + public List<UiccAccessRule> getUiccAccessRules() { + if (mAccessRules == null) return null; + return Arrays.asList(mAccessRules); } /** Gets the nickname. */ + @Nullable public String getNickname() { - return nickname; + return mNickname; } /** Gets the service provider name. */ public String getServiceProviderName() { - return serviceProviderName; + return mServiceProviderName; } /** Gets the profile name. */ public String getProfileName() { - return profileName; + return mProfileName; } /** Gets the profile class. */ @ProfileClass public int getProfileClass() { - return profileClass; + return mProfileClass; } /** Gets the state of the subscription. */ @ProfileState public int getState() { - return state; + return mState; } /** Gets the carrier identifier. */ public CarrierIdentifier getCarrierIdentifier() { - return carrierIdentifier; + return mCarrierIdentifier; } /** Gets the policy rules. */ @PolicyRule public int getPolicyRules() { - return policyRules; + return mPolicyRules; } /** Returns whether any policy rule exists. */ public boolean hasPolicyRules() { - return policyRules != 0; + return mPolicyRules != 0; } /** Checks whether a certain policy rule exists. */ public boolean hasPolicyRule(@PolicyRule int policy) { - return (policyRules & policy) != 0; + return (mPolicyRules & policy) != 0; } @Override @@ -387,50 +402,50 @@ public final class EuiccProfileInfo implements Parcelable { } EuiccProfileInfo that = (EuiccProfileInfo) obj; - return Objects.equals(iccid, that.iccid) - && Objects.equals(nickname, that.nickname) - && Objects.equals(serviceProviderName, that.serviceProviderName) - && Objects.equals(profileName, that.profileName) - && profileClass == that.profileClass - && state == that.state - && Objects.equals(carrierIdentifier, that.carrierIdentifier) - && policyRules == that.policyRules - && Arrays.equals(accessRules, that.accessRules); + return Objects.equals(mIccid, that.mIccid) + && Objects.equals(mNickname, that.mNickname) + && Objects.equals(mServiceProviderName, that.mServiceProviderName) + && Objects.equals(mProfileName, that.mProfileName) + && mProfileClass == that.mProfileClass + && mState == that.mState + && Objects.equals(mCarrierIdentifier, that.mCarrierIdentifier) + && mPolicyRules == that.mPolicyRules + && Arrays.equals(mAccessRules, that.mAccessRules); } @Override public int hashCode() { int result = 1; - result = 31 * result + Objects.hashCode(iccid); - result = 31 * result + Objects.hashCode(nickname); - result = 31 * result + Objects.hashCode(serviceProviderName); - result = 31 * result + Objects.hashCode(profileName); - result = 31 * result + profileClass; - result = 31 * result + state; - result = 31 * result + Objects.hashCode(carrierIdentifier); - result = 31 * result + policyRules; - result = 31 * result + Arrays.hashCode(accessRules); + result = 31 * result + Objects.hashCode(mIccid); + result = 31 * result + Objects.hashCode(mNickname); + result = 31 * result + Objects.hashCode(mServiceProviderName); + result = 31 * result + Objects.hashCode(mProfileName); + result = 31 * result + mProfileClass; + result = 31 * result + mState; + result = 31 * result + Objects.hashCode(mCarrierIdentifier); + result = 31 * result + mPolicyRules; + result = 31 * result + Arrays.hashCode(mAccessRules); return result; } @Override public String toString() { return "EuiccProfileInfo (nickname=" - + nickname + + mNickname + ", serviceProviderName=" - + serviceProviderName + + mServiceProviderName + ", profileName=" - + profileName + + mProfileName + ", profileClass=" - + profileClass + + mProfileClass + ", state=" - + state + + mState + ", CarrierIdentifier=" - + carrierIdentifier.toString() + + mCarrierIdentifier.toString() + ", policyRules=" - + policyRules + + mPolicyRules + ", accessRules=" - + Arrays.toString(accessRules) + + Arrays.toString(mAccessRules) + ")"; } } diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index be8580074f73..b87faef5bb44 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -17,6 +17,7 @@ package android.service.euicc; import android.annotation.CallSuper; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; import android.os.IBinder; @@ -41,8 +42,11 @@ import java.util.concurrent.atomic.AtomicInteger; * <p>To implement the LPA backend, you must extend this class and declare this service in your * manifest file. The service must require the * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission and include an intent filter - * with the {@link #EUICC_SERVICE_INTERFACE} action. The priority of the intent filter must be set - * to a non-zero value in case multiple implementations are present on the device. For example: + * with the {@link #EUICC_SERVICE_INTERFACE} action. It's suggested that the priority of the intent + * filter to be set to a non-zero value in case multiple implementations are present on the device. + * See the below example. Note that there will be problem if two LPAs are present and they have the + * same priority. + * Example: * * <pre>{@code * <service android:name=".MyEuiccService" @@ -65,9 +69,9 @@ import java.util.concurrent.atomic.AtomicInteger; * filter with the appropriate action, the {@link #CATEGORY_EUICC_UI} category, and a non-zero * priority. * - * TODO(b/35851809): Make this a SystemApi. * @hide */ +@SystemApi public abstract class EuiccService extends Service { /** Action which must be included in this service's intent filter. */ public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService"; @@ -77,7 +81,10 @@ public abstract class EuiccService extends Service { // LUI actions. These are passthroughs of the corresponding EuiccManager actions. - /** @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS */ + /** + * @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS + * The difference is this one is used by system to bring up the LUI. + */ public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS"; /** @see android.telephony.euicc.EuiccManager#ACTION_PROVISION_EMBEDDED_SUBSCRIPTION */ @@ -88,7 +95,10 @@ public abstract class EuiccService extends Service { // require user interaction. // TODO(b/33075886): Define extras for any input parameters to these dialogs once they are // more scoped out. - /** Alert the user that this action will result in an active SIM being deactivated. */ + /** + * Alert the user that this action will result in an active SIM being deactivated. + * To implement the LUI triggered by the system, you need to define this in AndroidManifest.xml. + */ public static final String ACTION_RESOLVE_DEACTIVATE_SIM = "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM"; /** @@ -102,7 +112,11 @@ public abstract class EuiccService extends Service { public static final String ACTION_RESOLVE_CONFIRMATION_CODE = "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE"; - /** Intent extra set for resolution requests containing the package name of the calling app. */ + /** + * Intent extra set for resolution requests containing the package name of the calling app. + * This is used by the above actions including ACTION_RESOLVE_DEACTIVATE_SIM, + * ACTION_RESOLVE_NO_PRIVILEGES and ACTION_RESOLVE_CONFIRMATION_CODE. + */ public static final String EXTRA_RESOLUTION_CALLING_PACKAGE = "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE"; @@ -136,10 +150,18 @@ public abstract class EuiccService extends Service { RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE); } - /** Boolean extra for resolution actions indicating whether the user granted consent. */ - public static final String RESOLUTION_EXTRA_CONSENT = "consent"; - /** String extra for resolution actions indicating the carrier confirmation code. */ - public static final String RESOLUTION_EXTRA_CONFIRMATION_CODE = "confirmation_code"; + /** + * Boolean extra for resolution actions indicating whether the user granted consent. + * This is used and set by the implementation and used in {@code EuiccOperation}. + */ + public static final String EXTRA_RESOLUTION_CONSENT = + "android.service.euicc.extra.RESOLUTION_CONSENT"; + /** + * String extra for resolution actions indicating the carrier confirmation code. + * This is used and set by the implementation and used in {@code EuiccOperation}. + */ + public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE = + "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE"; private final IEuiccService.Stub mStubWrapper; @@ -199,9 +221,9 @@ public abstract class EuiccService extends Service { * * @see IEuiccService#startOtaIfNecessary */ - public interface OtaStatusChangedCallback { + public abstract static class OtaStatusChangedCallback { /** Called when OTA status is changed. */ - void onOtaStatusChanged(int status); + public abstract void onOtaStatusChanged(int status); } /** @@ -238,8 +260,7 @@ public abstract class EuiccService extends Service { /** * Populate {@link DownloadableSubscription} metadata for the given downloadable subscription. * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @param subscription A subscription whose metadata needs to be populated. * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM)} @@ -267,8 +288,7 @@ public abstract class EuiccService extends Service { /** * Download the given subscription. * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @param subscription The subscription to download. * @param switchAfterDownload If true, the subscription should be enabled upon successful * download. @@ -286,8 +306,7 @@ public abstract class EuiccService extends Service { /** * Return a list of all @link EuiccProfileInfo}s. * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @return The result of the operation. * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList @@ -297,8 +316,7 @@ public abstract class EuiccService extends Service { /** * Return info about the eUICC chip/device. * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @return the {@link EuiccInfo} for the eUICC chip/device. * @see android.telephony.euicc.EuiccManager#getEuiccInfo */ @@ -310,8 +328,7 @@ public abstract class EuiccService extends Service { * <p>If the subscription is currently active, it should be deactivated first (equivalent to a * physical SIM being ejected). * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @param iccid the ICCID of the subscription to delete. * @return the result of the delete operation. May be one of the predefined {@code RESULT_} * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}. @@ -322,8 +339,7 @@ public abstract class EuiccService extends Service { /** * Switch to the given subscription. * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @param iccid the ICCID of the subscription to enable. May be null, in which case the current * profile should be deactivated and no profile should be activated to replace it - this is * equivalent to a physical SIM being ejected. @@ -340,8 +356,7 @@ public abstract class EuiccService extends Service { /** * Update the nickname of the given subscription. * - * @param slotId ID of the SIM slot to use for the operation. This is currently not populated - * but is here to future-proof the APIs. + * @param slotId ID of the SIM slot to use for the operation. * @param iccid the ICCID of the subscription to update. * @param nickname the new nickname to apply. * @return the result of the update operation. May be one of the predefined {@code RESULT_} diff --git a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java index 5a24492007f3..e2171ae6bc76 100644 --- a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java +++ b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java @@ -16,16 +16,19 @@ package android.service.euicc; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.euicc.DownloadableSubscription; +import java.util.Arrays; +import java.util.List; + /** * Result of a {@link EuiccService#onGetDefaultDownloadableSubscriptionList} operation. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ +@SystemApi public final class GetDefaultDownloadableSubscriptionListResult implements Parcelable { public static final Creator<GetDefaultDownloadableSubscriptionListResult> CREATOR = @@ -42,20 +45,35 @@ public final class GetDefaultDownloadableSubscriptionListResult implements Parce }; /** - * Result of the operation. + * @hide + * @deprecated - Do no use. Use getResult() instead. + */ + @Deprecated + public final int result; + + @Nullable + private final DownloadableSubscription[] mSubscriptions; + + /** + * Gets the result of the operation. * * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}. */ - public final int result; + public int getResult() { + return result; + } /** - * The available {@link DownloadableSubscription}s (with filled-in metadata). + * Gets the available {@link DownloadableSubscription}s (with filled-in metadata). * * <p>Only non-null if {@link #result} is {@link EuiccService#RESULT_OK}. */ @Nullable - public final DownloadableSubscription[] subscriptions; + public List<DownloadableSubscription> getDownloadableSubscriptions() { + if (mSubscriptions == null) return null; + return Arrays.asList(mSubscriptions); + } /** * Construct a new {@link GetDefaultDownloadableSubscriptionListResult}. @@ -70,25 +88,25 @@ public final class GetDefaultDownloadableSubscriptionListResult implements Parce @Nullable DownloadableSubscription[] subscriptions) { this.result = result; if (this.result == EuiccService.RESULT_OK) { - this.subscriptions = subscriptions; + this.mSubscriptions = subscriptions; } else { if (subscriptions != null) { throw new IllegalArgumentException( "Error result with non-null subscriptions: " + result); } - this.subscriptions = null; + this.mSubscriptions = null; } } private GetDefaultDownloadableSubscriptionListResult(Parcel in) { this.result = in.readInt(); - this.subscriptions = in.createTypedArray(DownloadableSubscription.CREATOR); + this.mSubscriptions = in.createTypedArray(DownloadableSubscription.CREATOR); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(result); - dest.writeTypedArray(subscriptions, flags); + dest.writeTypedArray(mSubscriptions, flags); } @Override diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java index de8a30706945..1edb5398add4 100644 --- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java +++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java @@ -16,6 +16,7 @@ package android.service.euicc; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.euicc.DownloadableSubscription; @@ -23,9 +24,8 @@ import android.telephony.euicc.DownloadableSubscription; /** * Result of a {@link EuiccService#onGetDownloadableSubscriptionMetadata} operation. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ +@SystemApi public final class GetDownloadableSubscriptionMetadataResult implements Parcelable { public static final Creator<GetDownloadableSubscriptionMetadataResult> CREATOR = @@ -42,20 +42,34 @@ public final class GetDownloadableSubscriptionMetadataResult implements Parcelab }; /** - * Result of the operation. + * @hide + * @deprecated - Do no use. Use getResult() instead. + */ + @Deprecated + public final int result; + + @Nullable + private final DownloadableSubscription mSubscription; + + /** + * Gets the result of the operation. * * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}. */ - public final int result; + public int getResult() { + return result; + } /** - * The {@link DownloadableSubscription} with filled-in metadata. + * Gets the {@link DownloadableSubscription} with filled-in metadata. * * <p>Only non-null if {@link #result} is {@link EuiccService#RESULT_OK}. */ @Nullable - public final DownloadableSubscription subscription; + public DownloadableSubscription getDownloadableSubscription() { + return mSubscription; + } /** * Construct a new {@link GetDownloadableSubscriptionMetadataResult}. @@ -70,25 +84,25 @@ public final class GetDownloadableSubscriptionMetadataResult implements Parcelab @Nullable DownloadableSubscription subscription) { this.result = result; if (this.result == EuiccService.RESULT_OK) { - this.subscription = subscription; + this.mSubscription = subscription; } else { if (subscription != null) { throw new IllegalArgumentException( "Error result with non-null subscription: " + result); } - this.subscription = null; + this.mSubscription = null; } } private GetDownloadableSubscriptionMetadataResult(Parcel in) { this.result = in.readInt(); - this.subscription = in.readTypedObject(DownloadableSubscription.CREATOR); + this.mSubscription = in.readTypedObject(DownloadableSubscription.CREATOR); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(result); - dest.writeTypedObject(this.subscription, flags); + dest.writeTypedObject(this.mSubscription, flags); } @Override diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java index 7ad84888dc82..464d136e70e5 100644 --- a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java +++ b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java @@ -16,15 +16,18 @@ package android.service.euicc; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.util.Arrays; +import java.util.List; + /** * Result of a {@link EuiccService#onGetEuiccProfileInfoList} operation. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ +@SystemApi public final class GetEuiccProfileInfoListResult implements Parcelable { public static final Creator<GetEuiccProfileInfoListResult> CREATOR = @@ -41,19 +44,38 @@ public final class GetEuiccProfileInfoListResult implements Parcelable { }; /** - * Result of the operation. + * @hide + * @deprecated - Do no use. Use getResult() instead. + */ + @Deprecated + public final int result; + + @Nullable + private final EuiccProfileInfo[] mProfiles; + + private final boolean mIsRemovable; + + /** + * Gets the result of the operation. * * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}. */ - public final int result; + public int getResult() { + return result; + } - /** The profile list (only upon success). */ + /** Gets the profile list (only upon success). */ @Nullable - public final EuiccProfileInfo[] profiles; + public List<EuiccProfileInfo> getProfiles() { + if (mProfiles == null) return null; + return Arrays.asList(mProfiles); + } - /** Whether the eUICC is removable. */ - public final boolean isRemovable; + /** Gets whether the eUICC is removable. */ + public boolean getIsRemovable() { + return mIsRemovable; + } /** * Construct a new {@link GetEuiccProfileInfoListResult}. @@ -71,30 +93,29 @@ public final class GetEuiccProfileInfoListResult implements Parcelable { public GetEuiccProfileInfoListResult( int result, @Nullable EuiccProfileInfo[] profiles, boolean isRemovable) { this.result = result; - this.isRemovable = isRemovable; + this.mIsRemovable = isRemovable; if (this.result == EuiccService.RESULT_OK) { - this.profiles = profiles; + this.mProfiles = profiles; } else { if (profiles != null) { throw new IllegalArgumentException( "Error result with non-null profiles: " + result); } - this.profiles = null; + this.mProfiles = null; } - } private GetEuiccProfileInfoListResult(Parcel in) { this.result = in.readInt(); - this.profiles = in.createTypedArray(EuiccProfileInfo.CREATOR); - this.isRemovable = in.readBoolean(); + this.mProfiles = in.createTypedArray(EuiccProfileInfo.CREATOR); + this.mIsRemovable = in.readBoolean(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(result); - dest.writeTypedArray(profiles, flags); - dest.writeBoolean(isRemovable); + dest.writeTypedArray(mProfiles, flags); + dest.writeBoolean(mIsRemovable); } @Override diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 66475e445efa..895be082c679 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -71,10 +71,11 @@ public class RuntimeInit { public void uncaughtException(Thread t, Throwable e) { // Don't re-enter if KillApplicationHandler has already run if (mCrashing) return; - if (mApplicationObject == null) { - // The "FATAL EXCEPTION" string is still used on Android even though - // apps can set a custom UncaughtExceptionHandler that renders uncaught - // exceptions non-fatal. + + // mApplicationObject is null for non-zygote java programs (e.g. "am") + // There are also apps running with the system UID. We don't want the + // first clause in either of these two cases, only for system_server. + if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) { Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); } else { StringBuilder message = new StringBuilder(); diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 03e5667666c1..89d63f60ebdd 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -55,8 +55,8 @@ public final class Zygote { public static final int DISABLE_VERIFIER = 1 << 9; /** Only use oat files located in /system. Otherwise use dex/jar/apk . */ public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10; - /** Do not enfore hidden API access restrictions. */ - public static final int DISABLE_HIDDEN_API_CHECKS = 1 << 11; + /** Do enfore hidden API access restrictions. */ + public static final int ENABLE_HIDDEN_API_CHECKS = 1 << 11; /** Force generation of native debugging information for backtraces. */ public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12; @@ -162,9 +162,6 @@ public final class Zygote { */ public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { - // SystemServer is always allowed to use hidden APIs. - runtimeFlags |= DISABLE_HIDDEN_API_CHECKS; - VM_HOOKS.preFork(); // Resets nice priority for zygote process. resetNicePriority(); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 89a70fc0c9a2..21f1fb652794 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -98,10 +98,6 @@ public class ZygoteInit { private static final String SOCKET_NAME_ARG = "--socket-name="; - /* Dexopt flag to disable hidden API access checks when dexopting SystemServer. - * Must be kept in sync with com.android.server.pm.Installer. */ - private static final int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10; - /** * Used to pre-load resources. */ @@ -569,10 +565,7 @@ public class ZygoteInit { if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { final String packageName = "*"; final String outputPath = null; - // Dexopt with a flag which lifts restrictions on hidden API usage. - // Offending methods would otherwise be re-verified at runtime and - // we want to avoid the performance overhead of that. - final int dexFlags = DEXOPT_DISABLE_HIDDEN_API_CHECKS; + final int dexFlags = 0; final String compilerFilter = systemServerFilter; final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; final String seInfo = null; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index b165ab122ba1..ae49070a3676 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -173,6 +173,10 @@ <protected-broadcast android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" /> <protected-broadcast + android:name="android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED" /> + <protected-broadcast + android:name="android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" /> @@ -1774,19 +1778,20 @@ <permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" android:protectionLevel="signature" /> - <!-- Allows an application to manage embedded subscriptions (those on a eUICC) through - EuiccManager APIs. + <!-- @SystemApi Allows an application to manage embedded subscriptions (those on a eUICC) + through EuiccManager APIs. <p>Protection level: signature|privileged|development - TODO(b/35851809): Mark this as a SystemApi and remove com. prefix. - @hide --> - <permission android:name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" + @hide + --> + <permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" android:protectionLevel="signature|privileged|development" /> - <!-- Must be required by an EuiccService to ensure that only the system can bind to it. + <!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to + it. <p>Protection level: signature - TODO(b/35851809): Mark this as a SystemApi and remove com. prefix. - @hide --> - <permission android:name="com.android.permission.BIND_EUICC_SERVICE" + @hide + --> + <permission android:name="android.permission.BIND_EUICC_SERVICE" android:protectionLevel="signature" /> <!-- ================================== --> diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java index 1e3ddf3226af..e69d1e7505d1 100644 --- a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java +++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java @@ -30,14 +30,15 @@ import android.telephony.UiccAccessRule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; + @SmallTest @RunWith(AndroidJUnit4.class) public class EuiccProfileInfoTest { @Test public void testWriteToParcel() { EuiccProfileInfo p = - new EuiccProfileInfo.Builder() - .setIccid("21430000000000006587") + new EuiccProfileInfo.Builder("21430000000000006587") .setNickname("profile nickname") .setServiceProviderName("service provider") .setProfileName("profile name") @@ -50,9 +51,7 @@ public class EuiccProfileInfoTest { "45")) .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE) .setUiccAccessRule( - new UiccAccessRule[] { - new UiccAccessRule(new byte[] {}, "package", 12345L) - }) + Arrays.asList(new UiccAccessRule(new byte[] {}, "package", 12345L))) .build(); Parcel parcel = Parcel.obtain(); @@ -68,8 +67,7 @@ public class EuiccProfileInfoTest { @Test public void testWriteToParcelNullCarrierId() { EuiccProfileInfo p = - new EuiccProfileInfo.Builder() - .setIccid("21430000000000006587") + new EuiccProfileInfo.Builder("21430000000000006587") .setNickname("profile nickname") .setServiceProviderName("service provider") .setProfileName("profile name") @@ -77,9 +75,8 @@ public class EuiccProfileInfoTest { .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED) .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE) .setUiccAccessRule( - new UiccAccessRule[] { - new UiccAccessRule(new byte[] {}, "package", 12345L) - }) + Arrays.asList(new UiccAccessRule(new byte[] {}, "package", 12345L)) + ) .build(); Parcel parcel = Parcel.obtain(); @@ -95,8 +92,7 @@ public class EuiccProfileInfoTest { @Test public void testBuilderAndGetters() { EuiccProfileInfo p = - new EuiccProfileInfo.Builder() - .setIccid("21430000000000006587") + new EuiccProfileInfo.Builder("21430000000000006587") .setNickname("profile nickname") .setProfileName("profile name") .setServiceProviderName("service provider") @@ -108,10 +104,7 @@ public class EuiccProfileInfoTest { .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED) .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL) .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE) - .setUiccAccessRule( - new UiccAccessRule[] { - new UiccAccessRule(new byte[0], null, 0) - }) + .setUiccAccessRule(Arrays.asList(new UiccAccessRule(new byte[0], null, 0))) .build(); assertEquals("21430000000000006587", p.getIccid()); @@ -130,14 +123,13 @@ public class EuiccProfileInfoTest { assertFalse(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE)); assertArrayEquals( new UiccAccessRule[] {new UiccAccessRule(new byte[0], null, 0)}, - p.getUiccAccessRules()); + p.getUiccAccessRules().toArray()); } @Test public void testBuilder_BasedOnAnotherProfile() { EuiccProfileInfo p = - new EuiccProfileInfo.Builder() - .setIccid("21430000000000006587") + new EuiccProfileInfo.Builder("21430000000000006587") .setNickname("profile nickname") .setProfileName("profile name") .setServiceProviderName("service provider") @@ -150,9 +142,7 @@ public class EuiccProfileInfoTest { .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL) .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE) .setUiccAccessRule( - new UiccAccessRule[] { - new UiccAccessRule(new byte[0], null, 0) - }) + Arrays.asList(new UiccAccessRule(new byte[] {}, "package", 12345L))) .build(); EuiccProfileInfo copied = new EuiccProfileInfo.Builder(p).build(); @@ -164,8 +154,7 @@ public class EuiccProfileInfoTest { @Test public void testEqualsHashCode() { EuiccProfileInfo p = - new EuiccProfileInfo.Builder() - .setIccid("21430000000000006587") + new EuiccProfileInfo.Builder("21430000000000006587") .setNickname("profile nickname") .setProfileName("profile name") .setServiceProviderName("service provider") @@ -177,10 +166,7 @@ public class EuiccProfileInfoTest { .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED) .setProfileClass(EuiccProfileInfo.PROFILE_STATE_ENABLED) .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE) - .setUiccAccessRule( - new UiccAccessRule[] { - new UiccAccessRule(new byte[0], null, 0) - }) + .setUiccAccessRule(Arrays.asList(new UiccAccessRule(new byte[0], null, 0))) .build(); assertTrue(p.equals(p)); @@ -229,13 +215,13 @@ public class EuiccProfileInfoTest { } @Test(expected = IllegalStateException.class) - public void testBuilderBuild_NoIccid() { - new EuiccProfileInfo.Builder().build(); + public void testBuilderBuild_IllegalIccid() { + new EuiccProfileInfo.Builder("abc").build(); } @Test(expected = IllegalArgumentException.class) public void testBuilderSetOperatorMccMnc_Illegal() { - new EuiccProfileInfo.Builder() + new EuiccProfileInfo.Builder("21430000000000006587") .setCarrierIdentifier(new CarrierIdentifier(new byte[] {1, 2, 3, 4}, null, null)); } diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk index 994131a22ab3..9b9e8113f234 100644 --- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk +++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk @@ -29,13 +29,10 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES:= \ native.cpp -# All of the shard libraries we link against. -LOCAL_SHARED_LIBRARIES := liblog +LOCAL_LDLIBS := -llog LOCAL_CFLAGS += -Wall -Wextra -Werror -# Also need the JNI headers. -LOCAL_C_INCLUDES += \ - $(JNI_H_INCLUDE) +LOCAL_SDK_VERSION := current include $(BUILD_SHARED_LIBRARY) diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp index 99cf587af2a6..fe32454aa10d 100644 --- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp +++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp @@ -15,12 +15,15 @@ */ #define LOG_TAG "pmtest32 native.cpp" -#include <utils/Log.h> +#include <android/log.h> #include <stdio.h> #include "jni.h" +#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) + static jint add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) { int result = a + b; diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk index 6c2679b30bfb..600a5d148740 100644 --- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk +++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk @@ -30,14 +30,10 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES:= \ native.cpp -# All of the shared libraries we link against. -LOCAL_SHARED_LIBRARIES := \ - libutils liblog +LOCAL_LDLIBS := -llog LOCAL_CFLAGS += -Wall -Wextra -Werror -# Also need the JNI headers. -LOCAL_C_INCLUDES += \ - $(JNI_H_INCLUDE) +LOCAL_SDK_VERSION := current include $(BUILD_SHARED_LIBRARY) diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp index 0b6d7501dcae..ad9e7469d1b8 100644 --- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp +++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp @@ -15,12 +15,15 @@ */ #define LOG_TAG "pmtest64 native.cpp" -#include <utils/Log.h> +#include <android/log.h> #include <stdio.h> #include "jni.h" +#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) + static jint add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) { int result = a + b; diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk index d668f29456c8..8e9ac6b5de95 100644 --- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk +++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk @@ -29,14 +29,10 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES:= \ native.cpp -# All of the shard libraries we link against. LOCAL_LDLIBS = -llog -LOCAL_SHARED_LIBRARIES := liblog LOCAL_CFLAGS += -Wall -Wextra -Werror -# Also need the JNI headers. -LOCAL_C_INCLUDES += \ - $(JNI_H_INCLUDE) +LOCAL_SDK_VERSION := current include $(BUILD_SHARED_LIBRARY) diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp index 3947e21a77bd..5c5088f40a94 100644 --- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp +++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp @@ -15,12 +15,15 @@ */ #define LOG_TAG "pmtestdual native.cpp" -#include <utils/Log.h> +#include <android/log.h> #include <stdio.h> #include "jni.h" +#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) + static jint add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) { int result = a + b; diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 6974bbb08cc0..16c2b6894fc8 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -165,7 +165,7 @@ applications that come with the platform <permission name="android.permission.UPDATE_LOCK"/> <permission name="android.permission.WRITE_APN_SETTINGS"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> - <permission name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/> + <permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/> <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/> <permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/> </privapp-permissions> @@ -348,6 +348,7 @@ applications that come with the platform <permission name="android.permission.WRITE_DREAM_STATE"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/> </privapp-permissions> <privapp-permissions package="com.android.tv"> diff --git a/native/android/OWNERS b/native/android/OWNERS new file mode 100644 index 000000000000..11d4be43571e --- /dev/null +++ b/native/android/OWNERS @@ -0,0 +1,11 @@ +set noparent + +per-file libandroid_net.map.txt=ek@google.com +per-file libandroid_net.map.txt=jchalard@google.com +per-file libandroid_net.map.txt=lorenzo@google.com +per-file libandroid_net.map.txt=satk@google.com + +per-file net.c=ek@google.com +per-file net.c=jchalard@google.com +per-file net.c=lorenzo@google.com +per-file net.c=satk@google.com diff --git a/packages/SettingsLib/res/drawable/ic_bt_hearing_aid.xml b/packages/SettingsLib/res/drawable/ic_bt_hearing_aid.xml new file mode 100644 index 000000000000..e14c99b61e2f --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_hearing_aid.xml @@ -0,0 +1,24 @@ +<!-- + Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M17,20c-0.29,0 -0.56,-0.06 -0.76,-0.15 -0.71,-0.37 -1.21,-0.88 -1.71,-2.38 -0.51,-1.56 -1.47,-2.29 -2.39,-3 -0.79,-0.61 -1.61,-1.24 -2.32,-2.53C9.29,10.98 9,9.93 9,9c0,-2.8 2.2,-5 5,-5s5,2.2 5,5h2c0,-3.93 -3.07,-7 -7,-7S7,5.07 7,9c0,1.26 0.38,2.65 1.07,3.9 0.91,1.65 1.98,2.48 2.85,3.15 0.81,0.62 1.39,1.07 1.71,2.05 0.6,1.82 1.37,2.84 2.73,3.55 0.51,0.23 1.07,0.35 1.64,0.35 2.21,0 4,-1.79 4,-4h-2c0,1.1 -0.9,2 -2,2zM7.64,2.64L6.22,1.22C4.23,3.21 3,5.96 3,9s1.23,5.79 3.22,7.78l1.41,-1.41C6.01,13.74 5,11.49 5,9s1.01,-4.74 2.64,-6.36zM11.5,9c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5 -2.5,1.12 -2.5,2.5z"/> +</vector> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 74a6c649b0b0..428f0b85b633 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -177,6 +177,11 @@ <!-- Bluetooth settings. Similar to bluetooth_profile_a2dp_high_quality, but used when the device supports high quality audio but we don't know which codec that will be used. --> <string name="bluetooth_profile_a2dp_high_quality_unknown_codec">HD audio</string> + <!-- Bluetooth settings. The user-visible string that is used whenever referring to the Hearing Aid profile. --> + <string name="bluetooth_profile_hearing_aid">Hearing Aid</string> + <!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. --> + <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aid</string> + <!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. --> <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string> <!-- Bluetooth settings. Connection options screen. The summary for the headset checkbox preference when headset is connected. --> @@ -214,6 +219,8 @@ for the HID checkbox preference that describes how checking it will set the HID profile as preferred. --> <string name="bluetooth_hid_profile_summary_use_for">Use for input</string> + <!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. --> + <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aid</string> <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] --> <string name="bluetooth_pairing_accept">Pair</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java new file mode 100644 index 000000000000..8f9e4635bb4b --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.bluetooth; + +import android.bluetooth.BluetoothHearingAid; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothCodecConfig; +import android.bluetooth.BluetoothCodecStatus; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothUuid; +import android.content.Context; +import android.os.ParcelUuid; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.R; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class HearingAidProfile implements LocalBluetoothProfile { + private static final String TAG = "HearingAidProfile"; + private static boolean V = true; + + private Context mContext; + + private BluetoothHearingAid mService; + private boolean mIsProfileReady; + + private final LocalBluetoothAdapter mLocalAdapter; + private final CachedBluetoothDeviceManager mDeviceManager; + + static final String NAME = "HearingAid"; + private final LocalBluetoothProfileManager mProfileManager; + + // Order of this profile in device profiles list + private static final int ORDINAL = 1; + + // These callbacks run on the main thread. + private final class HearingAidServiceListener + implements BluetoothProfile.ServiceListener { + + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (V) Log.d(TAG,"Bluetooth service connected"); + mService = (BluetoothHearingAid) proxy; + // We just bound to the service, so refresh the UI for any connected HearingAid devices. + List<BluetoothDevice> deviceList = mService.getConnectedDevices(); + while (!deviceList.isEmpty()) { + BluetoothDevice nextDevice = deviceList.remove(0); + CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); + // we may add a new device here, but generally this should not happen + if (device == null) { + Log.w(TAG, "HearingAidProfile found new device: " + nextDevice); + device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice); + } + device.onProfileStateChanged(HearingAidProfile.this, BluetoothProfile.STATE_CONNECTED); + device.refresh(); + } + mIsProfileReady=true; + } + + public void onServiceDisconnected(int profile) { + if (V) Log.d(TAG,"Bluetooth service disconnected"); + mIsProfileReady=false; + } + } + + public boolean isProfileReady() { + return mIsProfileReady; + } + + HearingAidProfile(Context context, LocalBluetoothAdapter adapter, + CachedBluetoothDeviceManager deviceManager, + LocalBluetoothProfileManager profileManager) { + mContext = context; + mLocalAdapter = adapter; + mDeviceManager = deviceManager; + mProfileManager = profileManager; + mLocalAdapter.getProfileProxy(context, new HearingAidServiceListener(), + BluetoothProfile.HEARING_AID); + } + + public boolean isConnectable() { + return true; + } + + public boolean isAutoConnectable() { + return true; + } + + public List<BluetoothDevice> getConnectedDevices() { + if (mService == null) return new ArrayList<BluetoothDevice>(0); + return mService.getDevicesMatchingConnectionStates( + new int[] {BluetoothProfile.STATE_CONNECTED, + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_DISCONNECTING}); + } + + public boolean connect(BluetoothDevice device) { + if (mService == null) return false; + return mService.connect(device); + } + + public boolean disconnect(BluetoothDevice device) { + if (mService == null) return false; + // Downgrade priority as user is disconnecting the hearing aid. + if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){ + mService.setPriority(device, BluetoothProfile.PRIORITY_ON); + } + return mService.disconnect(device); + } + + public int getConnectionStatus(BluetoothDevice device) { + if (mService == null) { + return BluetoothProfile.STATE_DISCONNECTED; + } + return mService.getConnectionState(device); + } + + public boolean isPreferred(BluetoothDevice device) { + if (mService == null) return false; + return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; + } + + public int getPreferred(BluetoothDevice device) { + if (mService == null) return BluetoothProfile.PRIORITY_OFF; + return mService.getPriority(device); + } + + public void setPreferred(BluetoothDevice device, boolean preferred) { + if (mService == null) return; + if (preferred) { + if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { + mService.setPriority(device, BluetoothProfile.PRIORITY_ON); + } + } else { + mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); + } + } + + public int getVolume() { + if (mService == null) { + return 0; + } + return mService.getVolume(); + } + + public void setVolume(int volume) { + if (mService == null) { + return; + } + mService.setVolume(volume); + } + + public long getHiSyncId(BluetoothDevice device) { + if (mService == null) { + return BluetoothHearingAid.HI_SYNC_ID_INVALID; + } + return mService.getHiSyncId(device); + } + + public int getDeviceSide(BluetoothDevice device) { + if (mService == null) { + return BluetoothHearingAid.SIDE_LEFT; + } + return mService.getDeviceSide(device); + } + + public int getDeviceMode(BluetoothDevice device) { + if (mService == null) { + return BluetoothHearingAid.MODE_MONAURAL; + } + return mService.getDeviceMode(device); + } + + public String toString() { + return NAME; + } + + public int getOrdinal() { + return ORDINAL; + } + + public int getNameResource(BluetoothDevice device) { + return R.string.bluetooth_profile_hearing_aid; + } + + public int getSummaryResourceForDevice(BluetoothDevice device) { + int state = getConnectionStatus(device); + switch (state) { + case BluetoothProfile.STATE_DISCONNECTED: + return R.string.bluetooth_hearing_aid_profile_summary_use_for; + + case BluetoothProfile.STATE_CONNECTED: + return R.string.bluetooth_hearing_aid_profile_summary_connected; + + default: + return Utils.getConnectionStateSummary(state); + } + } + + public int getDrawableResource(BluetoothClass btClass) { + return R.drawable.ic_bt_hearing_aid; + } + + protected void finalize() { + if (V) Log.d(TAG, "finalize()"); + if (mService != null) { + try { + BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEARING_AID, + mService); + mService = null; + }catch (Throwable t) { + Log.w(TAG, "Error cleaning up Hearing Aid proxy", t); + } + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 991d9221c796..34a099cb7ea0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -21,6 +21,7 @@ import android.bluetooth.BluetoothA2dpSink; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHeadsetClient; +import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothMapClient; @@ -91,6 +92,7 @@ public class LocalBluetoothProfileManager { private final PbapServerProfile mPbapProfile; private final boolean mUsePbapPce; private final boolean mUseMapClient; + private HearingAidProfile mHearingAidProfile; /** * Mapping from profile name, e.g. "HEADSET" to profile object. @@ -143,10 +145,14 @@ public class LocalBluetoothProfileManager { //Create PBAP server profile if(DEBUG) Log.d(TAG, "Adding local PBAP profile"); + mPbapProfile = new PbapServerProfile(context); addProfile(mPbapProfile, PbapServerProfile.NAME, BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED); + mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this); + addProfile(mHearingAidProfile, HearingAidProfile.NAME, + BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete"); } @@ -254,6 +260,18 @@ public class LocalBluetoothProfileManager { "Warning: PBAP Client profile was previously added but the UUID is now missing."); } + //Hearing Aid Client + if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) { + if (mHearingAidProfile == null) { + if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile"); + mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this); + addProfile(mHearingAidProfile, HearingAidProfile.NAME, + BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); + } + } else if (mHearingAidProfile != null) { + Log.w(TAG, "Warning: Hearing Aid profile was previously added but the UUID is now missing."); + } + mEventManager.registerProfileIntentReceiver(); // There is no local SDP record for HID and Settings app doesn't control PBAP Server. @@ -416,6 +434,10 @@ public class LocalBluetoothProfileManager { return mMapClientProfile; } + public HearingAidProfile getHearingAidProfile() { + return mHearingAidProfile; + } + /** * Fill in a list of LocalBluetoothProfile objects that are supported by * the local device and the remote device. @@ -515,6 +537,12 @@ public class LocalBluetoothProfileManager { removedProfiles.remove(mPbapClientProfile); } + if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid) && + mHearingAidProfile != null) { + profiles.add(mHearingAidProfile); + removedProfiles.remove(mHearingAidProfile); + } + if (DEBUG) { Log.d(TAG,"New Profiles" + profiles.toString()); } diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 87971cb41f96..9268c8fa2a01 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -108,7 +108,7 @@ <uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> <!-- Keyguard --> - <uses-permission android:name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" /> + <uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 6747be340d46..5e5eacb5c767 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -64,6 +64,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.NoSuchElementException; /** * Since phone process can be restarted, this class provides a centralized place @@ -90,6 +91,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { IBinder binder; + TelephonyRegistryDeathRecipient deathRecipient; + IPhoneStateListener callback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; @@ -251,6 +254,21 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } }; + private class TelephonyRegistryDeathRecipient implements IBinder.DeathRecipient { + + private final IBinder binder; + + TelephonyRegistryDeathRecipient(IBinder binder) { + this.binder = binder; + } + + @Override + public void binderDied() { + if (DBG) log("binderDied " + binder); + remove(binder); + } + } + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -378,23 +396,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - Record r; synchronized (mRecords) { // register - find_and_add: { - IBinder b = callback.asBinder(); - final int N = mRecords.size(); - for (int i = 0; i < N; i++) { - r = mRecords.get(i); - if (b == r.binder) { - break find_and_add; - } - } - r = new Record(); - r.binder = b; - mRecords.add(r); - if (DBG) log("listen oscl: add new record"); + IBinder b = callback.asBinder(); + Record r = add(b); + + if (r == null) { + return; } r.onSubscriptionsChangedListenerCallback = callback; @@ -496,20 +505,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { // register - Record r; - find_and_add: { - IBinder b = callback.asBinder(); - final int N = mRecords.size(); - for (int i = 0; i < N; i++) { - r = mRecords.get(i); - if (b == r.binder) { - break find_and_add; - } - } - r = new Record(); - r.binder = b; - mRecords.add(r); - if (DBG) log("listen: add new record"); + IBinder b = callback.asBinder(); + Record r = add(b); + + if (r == null) { + return; } r.callback = callback; @@ -697,16 +697,57 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : ""; } + private Record add(IBinder binder) { + Record r; + + synchronized (mRecords) { + final int N = mRecords.size(); + for (int i = 0; i < N; i++) { + r = mRecords.get(i); + if (binder == r.binder) { + // Already existed. + return r; + } + } + r = new Record(); + r.binder = binder; + r.deathRecipient = new TelephonyRegistryDeathRecipient(binder); + + try { + binder.linkToDeath(r.deathRecipient, 0); + } catch (RemoteException e) { + if (VDBG) log("LinkToDeath remote exception sending to r=" + r + " e=" + e); + // Binder already died. Return null. + return null; + } + + mRecords.add(r); + if (DBG) log("add new record"); + } + + return r; + } + private void remove(IBinder binder) { synchronized (mRecords) { final int recordCount = mRecords.size(); for (int i = 0; i < recordCount; i++) { - if (mRecords.get(i).binder == binder) { + Record r = mRecords.get(i); + if (r.binder == binder) { if (DBG) { - Record r = mRecords.get(i); - log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage - + "r.callback" + r.callback); + log("remove: binder=" + binder + " r.callingPackage " + r.callingPackage + + " r.callback " + r.callback); } + + if (r.deathRecipient != null) { + try { + binder.unlinkToDeath(r.deathRecipient, 0); + } catch (NoSuchElementException e) { + if (VDBG) log("UnlinkToDeath NoSuchElementException sending to r=" + + r + " e=" + e); + } + } + mRecords.remove(i); return; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c69af6c85399..0cce2d9ae56d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3891,10 +3891,10 @@ public class ActivityManagerService extends IActivityManager.Stub runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES; } - if (app.info.isAllowedToUseHiddenApi()) { - // This app is allowed to use undocumented and private APIs. Set - // up its runtime with the appropriate flag. - runtimeFlags |= Zygote.DISABLE_HIDDEN_API_CHECKS; + if (!app.info.isAllowedToUseHiddenApi()) { + // This app is not allowed to use undocumented and private APIs. + // Set up its runtime with the appropriate flag. + runtimeFlags |= Zygote.ENABLE_HIDDEN_API_CHECKS; } String invokeWith = null; @@ -17481,6 +17481,7 @@ public class ActivityManagerService extends IActivityManager.Stub final long myTotalPss = mi.getTotalPss(); final long myTotalSwapPss = mi.getTotalSwappedOutPss(); totalPss += myTotalPss; + totalSwapPss += myTotalSwapPss; nativeProcTotalPss += myTotalPss; MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")", diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 2cd128d0171e..91946821b8e0 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -58,9 +58,8 @@ public class Installer extends SystemService { public static final int DEXOPT_STORAGE_DE = 1 << 8; /** Indicates that dexopt is invoked from the background service. */ public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9; - /* Indicates that dexopt should not restrict access to private APIs. - * Must be kept in sync with com.android.internal.os.ZygoteInit. */ - public static final int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10; + /** Indicates that dexopt should restrict access to private APIs. */ + public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10; // NOTE: keep in sync with installd public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 1f219c14dbec..77fe8bc36ce5 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -55,7 +55,7 @@ import static com.android.server.pm.Installer.DEXOPT_FORCE; import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE; import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE; import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB; -import static com.android.server.pm.Installer.DEXOPT_DISABLE_HIDDEN_API_CHECKS; +import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; @@ -510,11 +510,9 @@ public class PackageDexOptimizer { boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter); boolean isPublic = !info.isForwardLocked() && !isProfileGuidedFilter; int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0; - // System apps are invoked with a runtime flag which exempts them from - // restrictions on hidden API usage. We dexopt with the same runtime flag - // otherwise offending methods would have to be re-verified at runtime - // and we want to avoid the performance overhead of that. - int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? DEXOPT_DISABLE_HIDDEN_API_CHECKS : 0; + // Some apps are executed with restrictions on hidden API usage. If this app is one + // of them, pass a flag to dexopt to enable the same restrictions during compilation. + int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS; int dexFlags = (isPublic ? DEXOPT_PUBLIC : 0) | (debuggable ? DEXOPT_DEBUGGABLE : 0) @@ -636,8 +634,8 @@ public class PackageDexOptimizer { if ((flags & DEXOPT_IDLE_BACKGROUND_JOB) == DEXOPT_IDLE_BACKGROUND_JOB) { flagsList.add("idle_background_job"); } - if ((flags & DEXOPT_DISABLE_HIDDEN_API_CHECKS) == DEXOPT_DISABLE_HIDDEN_API_CHECKS) { - flagsList.add("disable_hidden_api_checks"); + if ((flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) == DEXOPT_ENABLE_HIDDEN_API_CHECKS) { + flagsList.add("enable_hidden_api_checks"); } return String.join(",", flagsList); diff --git a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java new file mode 100644 index 000000000000..045081679d81 --- /dev/null +++ b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.updates; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.provider.Telephony; +import android.util.Log; + +public class CarrierIdInstallReceiver extends ConfigUpdateInstallReceiver { + + public CarrierIdInstallReceiver() { + super("/data/misc/carrierid", "carrier_list.pb", "metadata/", "version"); + } + + @Override + protected void postInstall(Context context, Intent intent) { + ContentResolver resolver = context.getContentResolver(); + resolver.update(Uri.withAppendedPath(Telephony.CarrierIdentification.All.CONTENT_URI, + "update_db"), new ContentValues(), null, null); + } +} diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 5fcff18aa5be..024bd303304f 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -29,7 +29,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -82,7 +81,7 @@ public abstract class Conference extends Conferenceable { private int mConnectionProperties; private String mDisconnectMessage; private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED; - private long mConnectElapsedTimeMillis = CONNECT_TIME_NOT_SPECIFIED; + private long mConnectionStartElapsedRealTime = CONNECT_TIME_NOT_SPECIFIED; private StatusHints mStatusHints; private Bundle mExtras; private Set<String> mPreviousExtraKeys; @@ -584,30 +583,36 @@ public abstract class Conference extends Conferenceable { } /** - * Sets the connection start time of the {@code Conference}. Should be specified in wall-clock - * time returned by {@link System#currentTimeMillis()}. + * Sets the connection start time of the {@code Conference}. This is used in the call log to + * indicate the date and time when the conference took place. + * <p> + * Should be specified in wall-clock time returned by {@link System#currentTimeMillis()}. * <p> * When setting the connection time, you should always set the connection elapsed time via - * {@link #setConnectionElapsedTime(long)}. + * {@link #setConnectionStartElapsedRealTime(long)} to ensure the duration is reflected. * - * @param connectionTimeMillis The connection time, in milliseconds. + * @param connectionTimeMillis The connection time, in milliseconds, as returned by + * {@link System#currentTimeMillis()}. */ public final void setConnectionTime(long connectionTimeMillis) { mConnectTimeMillis = connectionTimeMillis; } /** - * Sets the elapsed time since system boot when the {@link Conference} was connected. - * This is used to determine the duration of the {@link Conference}. + * Sets the start time of the {@link Conference} which is the basis for the determining the + * duration of the {@link Conference}. + * <p> + * You should use a value returned by {@link SystemClock#elapsedRealtime()} to ensure that time + * zone changes do not impact the conference duration. * <p> - * When setting the connection elapsed time, you should always set the connection time via + * When setting this, you should also set the connection time via * {@link #setConnectionTime(long)}. * - * @param connectionElapsedTime The connection time, as measured by + * @param connectionStartElapsedRealTime The connection time, as measured by * {@link SystemClock#elapsedRealtime()}. */ - public final void setConnectionElapsedTime(long connectionElapsedTime) { - mConnectElapsedTimeMillis = connectionElapsedTime; + public final void setConnectionStartElapsedRealTime(long connectionStartElapsedRealTime) { + mConnectionStartElapsedRealTime = connectionStartElapsedRealTime; } /** @@ -642,8 +647,8 @@ public abstract class Conference extends Conferenceable { * @return The elapsed time at which the {@link Conference} was connected. * @hide */ - public final long getConnectElapsedTime() { - return mConnectElapsedTimeMillis; + public final long getConnectionStartElapsedRealTime() { + return mConnectionStartElapsedRealTime; } /** diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index c0f6dfe90a57..69cc3dedf256 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -2298,7 +2298,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final void setConnectElapsedTimeMillis(long connectElapsedTimeMillis) { + public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) { mConnectElapsedTimeMillis = connectElapsedTimeMillis; } @@ -2737,7 +2737,20 @@ public abstract class Connection extends Conferenceable { /** * Notifies this Connection, which is in {@link #STATE_RINGING}, of * a request to accept. - * + * <p> + * For managed {@link ConnectionService}s, this will be called when the user answers a call via + * the default dialer's {@link InCallService}. + * <p> + * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the + * Telecom framework may request that the call is answered in the following circumstances: + * <ul> + * <li>The user chooses to answer an incoming call via a Bluetooth device.</li> + * <li>A car mode {@link InCallService} is in use which has declared + * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an + * {@link InCallService} will be able to see calls from self-managed + * {@link ConnectionService}s, and will be able to display an incoming call UI on their + * behalf.</li> + * </ul> * @param videoState The video state in which to answer the connection. */ public void onAnswer(int videoState) {} @@ -2745,6 +2758,20 @@ public abstract class Connection extends Conferenceable { /** * Notifies this Connection, which is in {@link #STATE_RINGING}, of * a request to accept. + * <p> + * For managed {@link ConnectionService}s, this will be called when the user answers a call via + * the default dialer's {@link InCallService}. + * <p> + * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the + * Telecom framework may request that the call is answered in the following circumstances: + * <ul> + * <li>The user chooses to answer an incoming call via a Bluetooth device.</li> + * <li>A car mode {@link InCallService} is in use which has declared + * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an + * {@link InCallService} will be able to see calls from self-managed + * {@link ConnectionService}s, and will be able to display an incoming call UI on their + * behalf.</li> + * </ul> */ public void onAnswer() { onAnswer(VideoProfile.STATE_AUDIO_ONLY); @@ -2759,6 +2786,20 @@ public abstract class Connection extends Conferenceable { /** * Notifies this Connection, which is in {@link #STATE_RINGING}, of * a request to reject. + * <p> + * For managed {@link ConnectionService}s, this will be called when the user rejects a call via + * the default dialer's {@link InCallService}. + * <p> + * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the + * Telecom framework may request that the call is rejected in the following circumstances: + * <ul> + * <li>The user chooses to reject an incoming call via a Bluetooth device.</li> + * <li>A car mode {@link InCallService} is in use which has declared + * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an + * {@link InCallService} will be able to see calls from self-managed + * {@link ConnectionService}s, and will be able to display an incoming call UI on their + * behalf.</li> + * </ul> */ public void onReject() {} @@ -2841,9 +2882,10 @@ public abstract class Connection extends Conferenceable { * should show its own incoming call user interface. * <p> * Where there are ongoing calls in other self-managed {@link ConnectionService}s, or in a - * regular {@link ConnectionService}, the Telecom framework will display its own incoming call - * user interface to allow the user to choose whether to answer the new incoming call and - * disconnect other ongoing calls, or to reject the new incoming call. + * regular {@link ConnectionService}, and it is not possible to hold these other calls, the + * Telecom framework will display its own incoming call user interface to allow the user to + * choose whether to answer the new incoming call and disconnect other ongoing calls, or to + * reject the new incoming call. * <p> * You should trigger the display of the incoming call user interface for your application by * showing a {@link Notification} with a full-screen {@link Intent} specified. diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 2ea7e65eeec7..46d6b4201497 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -21,7 +21,6 @@ import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -2007,7 +2006,7 @@ public abstract class ConnectionService extends Service { null : conference.getVideoProvider().getInterface(), conference.getVideoState(), conference.getConnectTimeMillis(), - conference.getConnectElapsedTime(), + conference.getConnectionStartElapsedRealTime(), conference.getStatusHints(), conference.getExtras()); diff --git a/telephony/java/android/telephony/OWNERS b/telephony/java/android/telephony/OWNERS new file mode 100644 index 000000000000..68dedce89272 --- /dev/null +++ b/telephony/java/android/telephony/OWNERS @@ -0,0 +1,14 @@ +set noparent + +amitmahajan@google.com +breadley@google.com +fionaxu@google.com +jackyu@google.com +hallliu@google.com +rgreenwalt@google.com +tgunn@google.com +jminjie@google.com +mpq@google.com +shuoq@google.com +refuhoo@google.com + diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index 38408fe3d0fd..77413d9c730d 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -34,6 +35,8 @@ import android.os.Parcelable; import android.util.DisplayMetrics; import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; /** * A Parcelable class for Subscription Information. @@ -332,12 +335,7 @@ public class SubscriptionInfo implements Parcelable { return this.mCountryIso; } - /** - * @return whether the subscription is an embedded one. - * @hide - * - * TODO(b/35851809): Make this public. - */ + /** @return whether the subscription is an embedded one. */ public boolean isEmbedded() { return this.mIsEmbedded; } @@ -351,9 +349,9 @@ public class SubscriptionInfo implements Parcelable { * @return whether the app is authorized to manage this subscription per its metadata. * @throws UnsupportedOperationException if this subscription is not embedded. * @hide - * - * TODO(b/35851809): Make this public. + * @deprecated - Do not use. */ + @Deprecated public boolean canManageSubscription(Context context) { return canManageSubscription(context, context.getPackageName()); } @@ -367,7 +365,9 @@ public class SubscriptionInfo implements Parcelable { * @return whether the app is authorized to manage this subscription per its metadata. * @throws UnsupportedOperationException if this subscription is not embedded. * @hide + * @deprecated - Do not use. */ + @Deprecated public boolean canManageSubscription(Context context, String packageName) { if (!isEmbedded()) { throw new UnsupportedOperationException("Not an embedded subscription"); @@ -395,14 +395,14 @@ public class SubscriptionInfo implements Parcelable { * @return the {@link UiccAccessRule}s dictating who is authorized to manage this subscription. * @throws UnsupportedOperationException if this subscription is not embedded. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ - public @Nullable UiccAccessRule[] getAccessRules() { + @SystemApi + public @Nullable List<UiccAccessRule> getAccessRules() { if (!isEmbedded()) { throw new UnsupportedOperationException("Not an embedded subscription"); } - return mAccessRules; + if (mAccessRules == null) return null; + return Arrays.asList(mAccessRules); } /** diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 1fae04b17d03..30e75b9bed91 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -23,6 +23,8 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; import android.net.INetworkPolicyManager; @@ -751,10 +753,13 @@ public class SubscriptionManager { * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} * then by {@link SubscriptionInfo#getSubscriptionId}. * </ul> - * @hide * - * TODO(b/35851809): Make this a SystemApi. + * <p> + * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required + * for #getAvailableSubscriptionInfoList to be invoked. + * @hide */ + @SystemApi public List<SubscriptionInfo> getAvailableSubscriptionInfoList() { List<SubscriptionInfo> result = null; @@ -792,9 +797,6 @@ public class SubscriptionManager { * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} * then by {@link SubscriptionInfo#getSubscriptionId}. * </ul> - * @hide - * - * TODO(b/35851809): Make this public. */ public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() { List<SubscriptionInfo> result = null; @@ -820,9 +822,8 @@ public class SubscriptionManager { * * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public void requestEmbeddedSubscriptionInfoListRefresh() { try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); @@ -1668,4 +1669,51 @@ public class SubscriptionManager { throw e.rethrowFromSystemServer(); } } + + /** + * Checks whether the app with the given context is authorized to manage the given subscription + * according to its metadata. Only supported for embedded subscriptions (if + * {@code SubscriptionInfo#isEmbedded} returns true). + * + * @param info The subscription to check. + * @return whether the app is authorized to manage this subscription per its metadata. + * @throws UnsupportedOperationException if this subscription is not embedded. + */ + public boolean canManageSubscription(SubscriptionInfo info) { + return canManageSubscription(info, mContext.getPackageName()); + } + + /** + * Checks whether the given app is authorized to manage the given subscription according to its + * metadata. Only supported for embedded subscriptions (if {@code SubscriptionInfo#isEmbedded} + * returns true). + * + * @param info The subscription to check. + * @param packageName Package name of the app to check. + * @return whether the app is authorized to manage this subscription per its metadata. + * @throws UnsupportedOperationException if this subscription is not embedded. + * @hide + */ + public boolean canManageSubscription(SubscriptionInfo info, String packageName) { + if (!info.isEmbedded()) { + throw new UnsupportedOperationException("Not an embedded subscription"); + } + if (info.getAccessRules() == null) { + return false; + } + PackageManager packageManager = mContext.getPackageManager(); + PackageInfo packageInfo; + try { + packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalArgumentException("Unknown package: " + packageName, e); + } + for (UiccAccessRule rule : info.getAccessRules()) { + if (rule.getCarrierPrivilegeStatus(packageInfo) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return true; + } + } + return false; + } } diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java index 8c4572474e6b..63263bd37206 100644 --- a/telephony/java/android/telephony/Telephony.java +++ b/telephony/java/android/telephony/Telephony.java @@ -33,6 +33,7 @@ import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SmsMessage; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Patterns; @@ -3345,73 +3346,118 @@ public final class Telephony { } /** - * Contains carrier identification information. - * @hide + * Contains carrier identification information for the current subscriptions. + * @see SubscriptionManager#getActiveSubscriptionIdList() */ public static final class CarrierIdentification implements BaseColumns { /** - * Numeric operator ID (as String). {@code MCC + MNC} - * <P>Type: TEXT </P> - */ - public static final String MCCMNC = "mccmnc"; - - /** - * Group id level 1 (as String). - * <P>Type: TEXT </P> - */ - public static final String GID1 = "gid1"; - - /** - * Group id level 2 (as String). - * <P>Type: TEXT </P> - */ - public static final String GID2 = "gid2"; - - /** - * Public Land Mobile Network name. - * <P>Type: TEXT </P> + * Not instantiable. + * @hide */ - public static final String PLMN = "plmn"; + private CarrierIdentification() {} /** - * Prefix xpattern of IMSI (International Mobile Subscriber Identity). - * <P>Type: TEXT </P> + * The {@code content://} style URI for this provider. */ - public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern"; + public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification"); /** - * Service Provider Name. - * <P>Type: TEXT </P> + * The authority string for the CarrierIdentification Provider + * @hide */ - public static final String SPN = "spn"; + public static final String AUTHORITY = "carrier_identification"; - /** - * Prefer APN name. - * <P>Type: TEXT </P> - */ - public static final String APN = "apn"; /** - * Prefix of Integrated Circuit Card Identifier. - * <P>Type: TEXT </P> + * Generates a content {@link Uri} used to receive updates on carrier identity change + * on the given subscriptionId + * <p> + * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the + * carrier identity {@link TelephonyManager#getAndroidCarrierIdForSubscription()} + * while your app is running. You can also use a {@link JobService} to ensure your app + * is notified of changes to the {@link Uri} even when it is not running. + * Note, however, that using a {@link JobService} does not guarantee timely delivery of + * updates to the {@link Uri}. + * + * @param subscriptionId the subscriptionId to receive updates on + * @return the Uri used to observe carrier identity changes */ - public static final String ICCID_PREFIX = "iccid_prefix"; + public static Uri getUriForSubscriptionId(int subscriptionId) { + return CONTENT_URI.buildUpon().appendEncodedPath( + String.valueOf(subscriptionId)).build(); + } /** - * User facing carrier name. + * A user facing carrier name. + * @see TelephonyManager#getAndroidCarrierNameForSubscription() * <P>Type: TEXT </P> */ public static final String NAME = "carrier_name"; /** * A unique carrier id + * @see TelephonyManager#getAndroidCarrierIdForSubscription() * <P>Type: INTEGER </P> */ public static final String CID = "carrier_id"; /** - * The {@code content://} URI for this table. + * Contains mappings between matching rules with carrier id for all carriers. + * @hide */ - public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification"); + public static final class All implements BaseColumns { + /** + * Numeric operator ID (as String). {@code MCC + MNC} + * <P>Type: TEXT </P> + */ + public static final String MCCMNC = "mccmnc"; + + /** + * Group id level 1 (as String). + * <P>Type: TEXT </P> + */ + public static final String GID1 = "gid1"; + + /** + * Group id level 2 (as String). + * <P>Type: TEXT </P> + */ + public static final String GID2 = "gid2"; + + /** + * Public Land Mobile Network name. + * <P>Type: TEXT </P> + */ + public static final String PLMN = "plmn"; + + /** + * Prefix xpattern of IMSI (International Mobile Subscriber Identity). + * <P>Type: TEXT </P> + */ + public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern"; + + /** + * Service Provider Name. + * <P>Type: TEXT </P> + */ + public static final String SPN = "spn"; + + /** + * Prefer APN name. + * <P>Type: TEXT </P> + */ + public static final String APN = "apn"; + + /** + * Prefix of Integrated Circuit Card Identifier. + * <P>Type: TEXT </P> + */ + public static final String ICCID_PREFIX = "iccid_prefix"; + + /** + * The {@code content://} URI for this table. + */ + public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification/all"); + } } } diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java index 39372019c20f..c3f8a1930409 100644 --- a/telephony/java/android/telephony/UiccAccessRule.java +++ b/telephony/java/android/telephony/UiccAccessRule.java @@ -16,6 +16,7 @@ package android.telephony; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.content.pm.PackageInfo; import android.content.pm.Signature; import android.os.Parcel; @@ -39,9 +40,8 @@ import java.util.Objects; * specification. * * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ +@SystemApi public final class UiccAccessRule implements Parcelable { private static final String TAG = "UiccAccessRule"; diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java index 0b3cbad0d2e2..0c17147ca3fa 100644 --- a/telephony/java/android/telephony/UiccSlotInfo.java +++ b/telephony/java/android/telephony/UiccSlotInfo.java @@ -55,10 +55,11 @@ public class UiccSlotInfo implements Parcelable { /** Card state restricted. */ public static final int CARD_STATE_INFO_RESTRICTED = 4; - public final boolean isActive; - public final boolean isEuicc; - public final String cardId; - public final @CardStateInfo int cardStateInfo; + private final boolean mIsActive; + private final boolean mIsEuicc; + private final String mCardId; + private final @CardStateInfo int mCardStateInfo; + private final int mLogicalSlotIdx; public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() { @Override @@ -73,18 +74,20 @@ public class UiccSlotInfo implements Parcelable { }; private UiccSlotInfo(Parcel in) { - isActive = in.readByte() != 0; - isEuicc = in.readByte() != 0; - cardId = in.readString(); - cardStateInfo = in.readInt(); + mIsActive = in.readByte() != 0; + mIsEuicc = in.readByte() != 0; + mCardId = in.readString(); + mCardStateInfo = in.readInt(); + mLogicalSlotIdx = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeByte((byte) (isActive ? 1 : 0)); - dest.writeByte((byte) (isEuicc ? 1 : 0)); - dest.writeString(cardId); - dest.writeInt(cardStateInfo); + dest.writeByte((byte) (mIsActive ? 1 : 0)); + dest.writeByte((byte) (mIsEuicc ? 1 : 0)); + dest.writeString(mCardId); + dest.writeInt(mCardStateInfo); + dest.writeInt(mLogicalSlotIdx); } @Override @@ -93,28 +96,33 @@ public class UiccSlotInfo implements Parcelable { } public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId, - @CardStateInfo int cardStateInfo) { - this.isActive = isActive; - this.isEuicc = isEuicc; - this.cardId = cardId; - this.cardStateInfo = cardStateInfo; + @CardStateInfo int cardStateInfo, int logicalSlotIdx) { + this.mIsActive = isActive; + this.mIsEuicc = isEuicc; + this.mCardId = cardId; + this.mCardStateInfo = cardStateInfo; + this.mLogicalSlotIdx = logicalSlotIdx; } public boolean getIsActive() { - return isActive; + return mIsActive; } public boolean getIsEuicc() { - return isEuicc; + return mIsEuicc; } public String getCardId() { - return cardId; + return mCardId; } @CardStateInfo public int getCardStateInfo() { - return cardStateInfo; + return mCardStateInfo; + } + + public int getLogicalSlotIdx() { + return mLogicalSlotIdx; } @Override @@ -127,32 +135,36 @@ public class UiccSlotInfo implements Parcelable { } UiccSlotInfo that = (UiccSlotInfo) obj; - return (isActive == that.isActive) - && (isEuicc == that.isEuicc) - && (cardId == that.cardId) - && (cardStateInfo == that.cardStateInfo); + return (mIsActive == that.mIsActive) + && (mIsEuicc == that.mIsEuicc) + && (mCardId == that.mCardId) + && (mCardStateInfo == that.mCardStateInfo) + && (mLogicalSlotIdx == that.mLogicalSlotIdx); } @Override public int hashCode() { int result = 1; - result = 31 * result + (isActive ? 1 : 0); - result = 31 * result + (isEuicc ? 1 : 0); - result = 31 * result + Objects.hashCode(cardId); - result = 31 * result + cardStateInfo; + result = 31 * result + (mIsActive ? 1 : 0); + result = 31 * result + (mIsEuicc ? 1 : 0); + result = 31 * result + Objects.hashCode(mCardId); + result = 31 * result + mCardStateInfo; + result = 31 * result + mLogicalSlotIdx; return result; } @Override public String toString() { - return "UiccSlotInfo (isActive=" - + isActive - + ", isEuicc=" - + isEuicc - + ", cardId=" - + cardId + return "UiccSlotInfo (mIsActive=" + + mIsActive + + ", mIsEuicc=" + + mIsEuicc + + ", mCardId=" + + mCardId + ", cardState=" - + cardStateInfo + + mCardStateInfo + + ", phoneId=" + + mLogicalSlotIdx + ")"; } } diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java index 01041c8b1360..88db22b82c5c 100644 --- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java +++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java @@ -16,18 +16,17 @@ package android.telephony.euicc; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.UiccAccessRule; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import com.android.internal.util.Preconditions; -/** - * Information about a subscription which is available for download. - * - * TODO(b/35851809): Make this public. - * @hide - */ +/** Information about a subscription which is available for download. */ public final class DownloadableSubscription implements Parcelable { public static final Creator<DownloadableSubscription> CREATOR = @@ -46,11 +45,12 @@ public final class DownloadableSubscription implements Parcelable { /** * Activation code. May be null for subscriptions which are not based on activation codes, e.g. * to download a default subscription assigned to this device. + * Should use getEncodedActivationCode() instead. * @hide - * - * TODO(b/35851809): Make this a SystemApi. + * @deprecated - Do not use. This will be private. Use getEncodedActivationCode() instead. */ @Nullable + @Deprecated public final String encodedActivationCode; @Nullable private String confirmationCode; @@ -58,8 +58,16 @@ public final class DownloadableSubscription implements Parcelable { // see getCarrierName and setCarrierName @Nullable private String carrierName; + // see getAccessRules and setAccessRules - private UiccAccessRule[] accessRules; + @Nullable + private List<UiccAccessRule> accessRules; + + /** Gets the activation code. */ + @Nullable + public String getEncodedActivationCode() { + return encodedActivationCode; + } /** @hide */ private DownloadableSubscription(String encodedActivationCode) { @@ -70,7 +78,59 @@ public final class DownloadableSubscription implements Parcelable { encodedActivationCode = in.readString(); confirmationCode = in.readString(); carrierName = in.readString(); - accessRules = in.createTypedArray(UiccAccessRule.CREATOR); + accessRules = new ArrayList<UiccAccessRule>(); + in.readTypedList(accessRules, UiccAccessRule.CREATOR); + } + + private DownloadableSubscription(String encodedActivationCode, String confirmationCode, + String carrierName, List<UiccAccessRule> accessRules) { + this.encodedActivationCode = encodedActivationCode; + this.confirmationCode = confirmationCode; + this.carrierName = carrierName; + this.accessRules = accessRules; + } + + /** @hide */ + @SystemApi + public static final class Builder { + @Nullable private String encodedActivationCode; + @Nullable private String confirmationCode; + @Nullable private String carrierName; + List<UiccAccessRule> accessRules; + + public Builder() {} + + public Builder(DownloadableSubscription baseSubscription) { + encodedActivationCode = baseSubscription.getEncodedActivationCode(); + confirmationCode = baseSubscription.getConfirmationCode(); + carrierName = baseSubscription.getCarrierName(); + accessRules = baseSubscription.getAccessRules(); + } + + public DownloadableSubscription build() { + return new DownloadableSubscription(encodedActivationCode, confirmationCode, + carrierName, accessRules); + } + + public Builder setEncodedActivationCode(String value) { + encodedActivationCode = value; + return this; + } + + public Builder setConfirmationCode(String value) { + confirmationCode = value; + return this; + } + + public Builder setCarrierName(String value) { + carrierName = value; + return this; + } + + public Builder setAccessRules(List<UiccAccessRule> value) { + accessRules = value; + return this; + } } /** @@ -87,7 +147,10 @@ public final class DownloadableSubscription implements Parcelable { /** * Sets the confirmation code. + * @hide + * @deprecated - Do not use. */ + @Deprecated public void setConfirmationCode(String confirmationCode) { this.confirmationCode = confirmationCode; } @@ -103,9 +166,9 @@ public final class DownloadableSubscription implements Parcelable { /** * Set the user-visible carrier name. * @hide - * - * TODO(b/35851809): Make this a SystemApi. + * @deprecated - Do not use. */ + @Deprecated public void setCarrierName(String carrierName) { this.carrierName = carrierName; } @@ -117,44 +180,51 @@ public final class DownloadableSubscription implements Parcelable { * those created with {@link #forActivationCode}). May be populated with * {@link EuiccManager#getDownloadableSubscriptionMetadata}. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi @Nullable public String getCarrierName() { return carrierName; } /** - * Returns the {@link UiccAccessRule}s dictating access to this subscription. + * Returns the {@link UiccAccessRule}s in list dictating access to this subscription. * * <p>Only present for downloadable subscriptions that were queried from a server (as opposed to * those created with {@link #forActivationCode}). May be populated with * {@link EuiccManager#getDownloadableSubscriptionMetadata}. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ - public UiccAccessRule[] getAccessRules() { + @SystemApi + public List<UiccAccessRule> getAccessRules() { return accessRules; } /** * Set the {@link UiccAccessRule}s dictating access to this subscription. * @hide - * - * TODO(b/35851809): Make this a SystemApi. + * @deprecated - Do not use. */ - public void setAccessRules(UiccAccessRule[] accessRules) { + @Deprecated + public void setAccessRules(List<UiccAccessRule> accessRules) { this.accessRules = accessRules; } + /** + * @hide + * @deprecated - Do not use. + */ + @Deprecated + public void setAccessRules(UiccAccessRule[] accessRules) { + this.accessRules = Arrays.asList(accessRules); + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(encodedActivationCode); dest.writeString(confirmationCode); dest.writeString(carrierName); - dest.writeTypedArray(accessRules, flags); + dest.writeTypedList(accessRules); } @Override diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java index a1a6a5a4d5bb..6be77250996e 100644 --- a/telephony/java/android/telephony/euicc/EuiccCardManager.java +++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java @@ -17,6 +17,7 @@ package android.telephony.euicc; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; @@ -49,14 +50,13 @@ import com.android.internal.telephony.euicc.ISwitchToProfileCallback; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.Executor; /** * EuiccCardManager is the application interface to an eSIM card. - * * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ +@SystemApi public class EuiccCardManager { private static final String TAG = "EuiccCardManager"; @@ -68,6 +68,7 @@ public class EuiccCardManager { CANCEL_REASON_TIMEOUT, CANCEL_REASON_PPR_NOT_ALLOWED }) + /** @hide */ public @interface CancelReason {} /** @@ -96,6 +97,7 @@ public class EuiccCardManager { RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS }) + /** @hide */ public @interface ResetOption {} /** Deletes all operational profiles. */ @@ -143,18 +145,20 @@ public class EuiccCardManager { } /** - * Gets all the profiles on eUicc. + * Requests all the profiles on eUicc. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code and all the profiles. */ - public void getAllProfiles(String cardId, ResultCallback<EuiccProfileInfo[]> callback) { + public void requestAllProfiles(String cardId, Executor executor, + ResultCallback<EuiccProfileInfo[]> callback) { try { getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(), cardId, new IGetAllProfilesCallback.Stub() { @Override public void onComplete(int resultCode, EuiccProfileInfo[] profiles) { - callback.onComplete(resultCode, profiles); + executor.execute(() -> callback.onComplete(resultCode, profiles)); } }); } catch (RemoteException e) { @@ -164,19 +168,21 @@ public class EuiccCardManager { } /** - * Gets the profile of the given iccid. + * Requests the profile of the given iccid. * * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code and profile. */ - public void getProfile(String cardId, String iccid, ResultCallback<EuiccProfileInfo> callback) { + public void requestProfile(String cardId, String iccid, Executor executor, + ResultCallback<EuiccProfileInfo> callback) { try { getIEuiccCardController().getProfile(mContext.getOpPackageName(), cardId, iccid, new IGetProfileCallback.Stub() { @Override public void onComplete(int resultCode, EuiccProfileInfo profile) { - callback.onComplete(resultCode, profile); + executor.execute(() -> callback.onComplete(resultCode, profile)); } }); } catch (RemoteException e) { @@ -191,16 +197,17 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. * @param refresh Whether sending the REFRESH command to modem. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code. */ - public void disableProfile(String cardId, String iccid, boolean refresh, + public void disableProfile(String cardId, String iccid, boolean refresh, Executor executor, ResultCallback<Void> callback) { try { getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid, refresh, new IDisableProfileCallback.Stub() { @Override public void onComplete(int resultCode) { - callback.onComplete(resultCode, null); + executor.execute(() -> callback.onComplete(resultCode, null)); } }); } catch (RemoteException e) { @@ -216,16 +223,17 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile to switch to. * @param refresh Whether sending the REFRESH command to modem. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code and the EuiccProfileInfo enabled. */ - public void switchToProfile(String cardId, String iccid, boolean refresh, + public void switchToProfile(String cardId, String iccid, boolean refresh, Executor executor, ResultCallback<EuiccProfileInfo> callback) { try { getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid, refresh, new ISwitchToProfileCallback.Stub() { @Override public void onComplete(int resultCode, EuiccProfileInfo profile) { - callback.onComplete(resultCode, profile); + executor.execute(() -> callback.onComplete(resultCode, profile)); } }); } catch (RemoteException e) { @@ -240,16 +248,17 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. * @param nickname The nickname of the profile. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code. */ - public void setNickname(String cardId, String iccid, String nickname, + public void setNickname(String cardId, String iccid, String nickname, Executor executor, ResultCallback<Void> callback) { try { getIEuiccCardController().setNickname(mContext.getOpPackageName(), cardId, iccid, nickname, new ISetNicknameCallback.Stub() { @Override public void onComplete(int resultCode) { - callback.onComplete(resultCode, null); + executor.execute(() -> callback.onComplete(resultCode, null)); } }); } catch (RemoteException e) { @@ -263,15 +272,17 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code. */ - public void deleteProfile(String cardId, String iccid, ResultCallback<Void> callback) { + public void deleteProfile(String cardId, String iccid, Executor executor, + ResultCallback<Void> callback) { try { getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), cardId, iccid, new IDeleteProfileCallback.Stub() { @Override public void onComplete(int resultCode) { - callback.onComplete(resultCode, null); + executor.execute(() -> callback.onComplete(resultCode, null)); } }); } catch (RemoteException e) { @@ -286,15 +297,17 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param options Bits of the options of resetting which parts of the eUICC memory. See * EuiccCard for details. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code. */ - public void resetMemory(String cardId, @ResetOption int options, ResultCallback<Void> callback) { + public void resetMemory(String cardId, @ResetOption int options, Executor executor, + ResultCallback<Void> callback) { try { getIEuiccCardController().resetMemory(mContext.getOpPackageName(), cardId, options, new IResetMemoryCallback.Stub() { @Override public void onComplete(int resultCode) { - callback.onComplete(resultCode, null); + executor.execute(() -> callback.onComplete(resultCode, null)); } }); } catch (RemoteException e) { @@ -304,18 +317,20 @@ public class EuiccCardManager { } /** - * Gets the default SM-DP+ address from eUICC. + * Requests the default SM-DP+ address from eUICC. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code and the default SM-DP+ address. */ - public void getDefaultSmdpAddress(String cardId, ResultCallback<String> callback) { + public void requestDefaultSmdpAddress(String cardId, Executor executor, + ResultCallback<String> callback) { try { getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(), cardId, new IGetDefaultSmdpAddressCallback.Stub() { @Override public void onComplete(int resultCode, String address) { - callback.onComplete(resultCode, address); + executor.execute(() -> callback.onComplete(resultCode, address)); } }); } catch (RemoteException e) { @@ -325,18 +340,20 @@ public class EuiccCardManager { } /** - * Gets the SM-DS address from eUICC. + * Requests the SM-DS address from eUICC. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code and the SM-DS address. */ - public void getSmdsAddress(String cardId, ResultCallback<String> callback) { + public void requestSmdsAddress(String cardId, Executor executor, + ResultCallback<String> callback) { try { getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(), cardId, new IGetSmdsAddressCallback.Stub() { @Override public void onComplete(int resultCode, String address) { - callback.onComplete(resultCode, address); + executor.execute(() -> callback.onComplete(resultCode, address)); } }); } catch (RemoteException e) { @@ -350,16 +367,18 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param defaultSmdpAddress The default SM-DP+ address to set. + * @param executor The executor through which the callback should be invode. * @param callback The callback to get the result code. */ - public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress, ResultCallback<Void> callback) { + public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress, Executor executor, + ResultCallback<Void> callback) { try { getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(), cardId, defaultSmdpAddress, new ISetDefaultSmdpAddressCallback.Stub() { @Override public void onComplete(int resultCode) { - callback.onComplete(resultCode, null); + executor.execute(() -> callback.onComplete(resultCode, null)); } }); } catch (RemoteException e) { @@ -369,18 +388,20 @@ public class EuiccCardManager { } /** - * Gets Rules Authorisation Table. + * Requests Rules Authorisation Table. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the rule authorisation table. */ - public void getRulesAuthTable(String cardId, ResultCallback<EuiccRulesAuthTable> callback) { + public void requestRulesAuthTable(String cardId, Executor executor, + ResultCallback<EuiccRulesAuthTable> callback) { try { getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(), cardId, new IGetRulesAuthTableCallback.Stub() { @Override public void onComplete(int resultCode, EuiccRulesAuthTable rat) { - callback.onComplete(resultCode, rat); + executor.execute(() -> callback.onComplete(resultCode, rat)); } }); } catch (RemoteException e) { @@ -390,18 +411,20 @@ public class EuiccCardManager { } /** - * Gets the eUICC challenge for new profile downloading. + * Requests the eUICC challenge for new profile downloading. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the challenge. */ - public void getEuiccChallenge(String cardId, ResultCallback<byte[]> callback) { + public void requestEuiccChallenge(String cardId, Executor executor, + ResultCallback<byte[]> callback) { try { getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(), cardId, new IGetEuiccChallengeCallback.Stub() { @Override public void onComplete(int resultCode, byte[] challenge) { - callback.onComplete(resultCode, challenge); + executor.execute(() -> callback.onComplete(resultCode, challenge)); } }); } catch (RemoteException e) { @@ -411,18 +434,20 @@ public class EuiccCardManager { } /** - * Gets the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading. + * Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the info1. */ - public void getEuiccInfo1(String cardId, ResultCallback<byte[]> callback) { + public void requestEuiccInfo1(String cardId, Executor executor, + ResultCallback<byte[]> callback) { try { getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(), cardId, new IGetEuiccInfo1Callback.Stub() { @Override public void onComplete(int resultCode, byte[] info) { - callback.onComplete(resultCode, info); + executor.execute(() -> callback.onComplete(resultCode, info)); } }); } catch (RemoteException e) { @@ -435,15 +460,17 @@ public class EuiccCardManager { * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading. * * @param cardId The Id of the eUICC. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the info2. */ - public void getEuiccInfo2(String cardId, ResultCallback<byte[]> callback) { + public void requestEuiccInfo2(String cardId, Executor executor, + ResultCallback<byte[]> callback) { try { getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(), cardId, new IGetEuiccInfo2Callback.Stub() { @Override public void onComplete(int resultCode, byte[] info) { - callback.onComplete(resultCode, info); + executor.execute(() -> callback.onComplete(resultCode, info)); } }); } catch (RemoteException e) { @@ -466,12 +493,13 @@ public class EuiccCardManager { * GSMA RSP v2.0+. * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by * SM-DP+ server. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and a byte array which represents a * {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+. */ public void authenticateServer(String cardId, String matchingId, byte[] serverSigned1, byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate, - ResultCallback<byte[]> callback) { + Executor executor, ResultCallback<byte[]> callback) { try { getIEuiccCardController().authenticateServer( mContext.getOpPackageName(), @@ -484,7 +512,7 @@ public class EuiccCardManager { new IAuthenticateServerCallback.Stub() { @Override public void onComplete(int resultCode, byte[] response) { - callback.onComplete(resultCode, response); + executor.execute(() -> callback.onComplete(resultCode, response)); } }); } catch (RemoteException e) { @@ -505,11 +533,13 @@ public class EuiccCardManager { * SM-DP+ server. * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned * by SM-DP+ server. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and a byte array which represents a * {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+ */ public void prepareDownload(String cardId, @Nullable byte[] hashCc, byte[] smdpSigned2, - byte[] smdpSignature2, byte[] smdpCertificate, ResultCallback<byte[]> callback) { + byte[] smdpSignature2, byte[] smdpCertificate, Executor executor, + ResultCallback<byte[]> callback) { try { getIEuiccCardController().prepareDownload( mContext.getOpPackageName(), @@ -521,7 +551,7 @@ public class EuiccCardManager { new IPrepareDownloadCallback.Stub() { @Override public void onComplete(int resultCode, byte[] response) { - callback.onComplete(resultCode, response); + executor.execute(() -> callback.onComplete(resultCode, response)); } }); } catch (RemoteException e) { @@ -535,11 +565,12 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and a byte array which represents a * {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+. */ public void loadBoundProfilePackage(String cardId, byte[] boundProfilePackage, - ResultCallback<byte[]> callback) { + Executor executor, ResultCallback<byte[]> callback) { try { getIEuiccCardController().loadBoundProfilePackage( mContext.getOpPackageName(), @@ -548,7 +579,7 @@ public class EuiccCardManager { new ILoadBoundProfilePackageCallback.Stub() { @Override public void onComplete(int resultCode, byte[] response) { - callback.onComplete(resultCode, response); + executor.execute(() -> callback.onComplete(resultCode, response)); } }); } catch (RemoteException e) { @@ -563,11 +594,12 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param transactionId the transaction ID returned by SM-DP+ server. * @param reason the cancel reason. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and an byte[] which represents a * {@code CancelSessionResponse} defined in GSMA RSP v2.0+. */ public void cancelSession(String cardId, byte[] transactionId, @CancelReason int reason, - ResultCallback<byte[]> callback) { + Executor executor, ResultCallback<byte[]> callback) { try { getIEuiccCardController().cancelSession( mContext.getOpPackageName(), @@ -577,7 +609,7 @@ public class EuiccCardManager { new ICancelSessionCallback.Stub() { @Override public void onComplete(int resultCode, byte[] response) { - callback.onComplete(resultCode, response); + executor.execute(() -> callback.onComplete(resultCode, response)); } }); } catch (RemoteException e) { @@ -591,16 +623,17 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param events bits of the event types ({@link EuiccNotification.Event}) to list. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the list of notifications. */ public void listNotifications(String cardId, @EuiccNotification.Event int events, - ResultCallback<EuiccNotification[]> callback) { + Executor executor, ResultCallback<EuiccNotification[]> callback) { try { getIEuiccCardController().listNotifications(mContext.getOpPackageName(), cardId, events, new IListNotificationsCallback.Stub() { @Override public void onComplete(int resultCode, EuiccNotification[] notifications) { - callback.onComplete(resultCode, notifications); + executor.execute(() -> callback.onComplete(resultCode, notifications)); } }); } catch (RemoteException e) { @@ -614,16 +647,17 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param events bits of the event types ({@link EuiccNotification.Event}) to list. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the list of notifications. */ public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events, - ResultCallback<EuiccNotification[]> callback) { + Executor executor, ResultCallback<EuiccNotification[]> callback) { try { getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), cardId, events, new IRetrieveNotificationListCallback.Stub() { @Override public void onComplete(int resultCode, EuiccNotification[] notifications) { - callback.onComplete(resultCode, notifications); + executor.execute(() -> callback.onComplete(resultCode, notifications)); } }); } catch (RemoteException e) { @@ -637,16 +671,17 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param seqNumber the sequence number of the notification. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code and the notification. */ - public void retrieveNotification(String cardId, int seqNumber, + public void retrieveNotification(String cardId, int seqNumber, Executor executor, ResultCallback<EuiccNotification> callback) { try { getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), cardId, seqNumber, new IRetrieveNotificationCallback.Stub() { @Override public void onComplete(int resultCode, EuiccNotification notification) { - callback.onComplete(resultCode, notification); + executor.execute(() -> callback.onComplete(resultCode, notification)); } }); } catch (RemoteException e) { @@ -660,9 +695,10 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param seqNumber the sequence number of the notification. + * @param executor The executor through which the callback should be invode. * @param callback the callback to get the result code. */ - public void removeNotificationFromList(String cardId, int seqNumber, + public void removeNotificationFromList(String cardId, int seqNumber, Executor executor, ResultCallback<Void> callback) { try { getIEuiccCardController().removeNotificationFromList( @@ -672,7 +708,7 @@ public class EuiccCardManager { new IRemoveNotificationFromListCallback.Stub() { @Override public void onComplete(int resultCode) { - callback.onComplete(resultCode, null); + executor.execute(() -> callback.onComplete(resultCode, null)); } }); } catch (RemoteException e) { diff --git a/telephony/java/android/telephony/euicc/EuiccInfo.java b/telephony/java/android/telephony/euicc/EuiccInfo.java index 5bfff08f8d45..a4adf0591a00 100644 --- a/telephony/java/android/telephony/euicc/EuiccInfo.java +++ b/telephony/java/android/telephony/euicc/EuiccInfo.java @@ -23,9 +23,6 @@ import android.os.Parcelable; * Information about an eUICC chip/device. * * @see EuiccManager#getEuiccInfo - * @hide - * - * TODO(b/35851809): Make this public. */ // WARNING: Do not add any privacy-sensitive fields to this class (such as an eUICC identifier)! // This API is accessible to all applications. Privacy-sensitive fields should be returned in their @@ -45,12 +42,17 @@ public final class EuiccInfo implements Parcelable { } }; + @Nullable + private final String osVersion; + /** - * Version of the operating system running on the eUICC. This field is hardware-specific and is - * not guaranteed to match any particular format. + * Gets the version of the operating system running on the eUICC. This field is + * hardware-specific and is not guaranteed to match any particular format. */ @Nullable - public final String osVersion; + public String getOsVersion() { + return osVersion; + } public EuiccInfo(@Nullable String osVersion) { this.osVersion = osVersion; diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 662056e90496..71ef5de92e7b 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -42,9 +42,6 @@ import java.lang.annotation.RetentionPolicy; * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}. * * <p>See {@link #isEnabled} before attempting to use these APIs. - * - * TODO(b/35851809): Make this public. - * @hide */ public class EuiccManager { @@ -56,6 +53,8 @@ public class EuiccManager { * * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if * {@link #isEnabled} is false. + * + * This is ued by non-LPA app to bring up LUI. */ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = @@ -69,8 +68,10 @@ public class EuiccManager { * * <p class="note">This is a protected intent that can only be sent * by the system. - * TODO(b/35851809): Make this a SystemApi. + * + * @hide */ + @SystemApi @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED"; @@ -78,12 +79,10 @@ public class EuiccManager { /** * Broadcast Action: The action sent to carrier app so it knows the carrier setup is not * completed. - * - * TODO(b/35851809): Make this a public API. */ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_NOTIFY_CARRIER_SETUP = - "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP"; + public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = + "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE"; /** * Intent action to provision an embedded subscription. @@ -95,8 +94,9 @@ public class EuiccManager { * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if * {@link #isEnabled} is false or if the device is already provisioned. * - * TODO(b/35851809): Make this a SystemApi. + * @hide */ + @SystemApi @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; @@ -143,9 +143,8 @@ public class EuiccManager { * Key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result * callbacks providing the downloadable subscription metadata. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION"; @@ -153,9 +152,8 @@ public class EuiccManager { * Key for an extra set on {@link #getDefaultDownloadableSubscriptionList} PendingIntent result * callbacks providing the list of available downloadable subscriptions. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS"; @@ -201,6 +199,7 @@ public class EuiccManager { * Euicc OTA update status which can be got by {@link #getOtaStatus} * @hide */ + @SystemApi @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"EUICC_OTA_"}, value = { EUICC_OTA_IN_PROGRESS, @@ -215,15 +214,37 @@ public class EuiccManager { /** * An OTA is in progress. During this time, the eUICC is not available and the user may lose * network access. + * @hide */ + @SystemApi public static final int EUICC_OTA_IN_PROGRESS = 1; - /** The OTA update failed. */ + + /** + * The OTA update failed. + * @hide + */ + @SystemApi public static final int EUICC_OTA_FAILED = 2; - /** The OTA update finished successfully. */ + + /** + * The OTA update finished successfully. + * @hide + */ + @SystemApi public static final int EUICC_OTA_SUCCEEDED = 3; - /** The OTA update not needed since current eUICC OS is latest. */ + + /** + * The OTA update not needed since current eUICC OS is latest. + * @hide + */ + @SystemApi public static final int EUICC_OTA_NOT_NEEDED = 4; - /** The OTA status is unavailable since eUICC service is unavailable. */ + + /** + * The OTA status is unavailable since eUICC service is unavailable. + * @hide + */ + @SystemApi public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; private final Context mContext; @@ -276,8 +297,10 @@ public class EuiccManager { * * @return the status of eUICC OTA. If {@link #isEnabled()} is false or the eUICC is not ready, * {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned. - * TODO(b/35851809): Make this a SystemApi. + * + * @hide */ + @SystemApi public int getOtaStatus() { if (!isEnabled()) { return EUICC_OTA_STATUS_UNAVAILABLE; @@ -292,7 +315,7 @@ public class EuiccManager { /** * Attempt to download the given {@link DownloadableSubscription}. * - * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, + * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, * or the calling app must be authorized to manage both the currently-active subscription and * the subscription to be downloaded according to the subscription metadata. Without the former, * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback @@ -354,14 +377,16 @@ public class EuiccManager { * * <p>To be called by the LUI upon completion of a resolvable error flow. * + * <p>Requires that the calling app has the + * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. + * * @param resolutionIntent The original intent used to start the LUI. * @param resolutionExtras Resolution-specific extras depending on the result of the resolution. * For example, this may indicate whether the user has consented or may include the input * they provided. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) { if (!isEnabled()) { PendingIntent callbackIntent = @@ -395,9 +420,8 @@ public class EuiccManager { * @param subscription the subscription which needs metadata filled in * @param callbackIntent a PendingIntent to launch when the operation completes. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public void getDownloadableSubscriptionMetadata( DownloadableSubscription subscription, PendingIntent callbackIntent) { if (!isEnabled()) { @@ -426,9 +450,8 @@ public class EuiccManager { * * @param callbackIntent a PendingIntent to launch when the operation completes. * @hide - * - * TODO(b/35851809): Make this a SystemApi. */ + @SystemApi public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) { if (!isEnabled()) { sendUnavailableError(callbackIntent); @@ -468,7 +491,7 @@ public class EuiccManager { * * <p>Requires that the calling app has carrier privileges according to the metadata of the * profile to be deleted, or the - * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. + * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. * * @param subscriptionId the ID of the subscription to delete. * @param callbackIntent a PendingIntent to launch when the operation completes. @@ -489,7 +512,7 @@ public class EuiccManager { /** * Switch to (enable) the given subscription. * - * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, + * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, * or the calling app must be authorized to manage both the currently-active subscription and * the subscription to be enabled according to the subscription metadata. Without the former, * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback @@ -599,11 +622,7 @@ public class EuiccManager { } } - /** - * @hide - */ - @TestApi - protected IEuiccController getIEuiccController() { + private static IEuiccController getIEuiccController() { return IEuiccController.Stub.asInterface(ServiceManager.getService("econtroller")); } } diff --git a/telephony/java/android/telephony/euicc/EuiccNotification.java b/telephony/java/android/telephony/euicc/EuiccNotification.java index ef3c1ce8cf3b..43a770748260 100644 --- a/telephony/java/android/telephony/euicc/EuiccNotification.java +++ b/telephony/java/android/telephony/euicc/EuiccNotification.java @@ -17,6 +17,7 @@ package android.telephony.euicc; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -31,10 +32,9 @@ import java.util.Objects; * disabling, or deleting). * * @hide - * - * TODO(b/35851809): Make this a @SystemApi. */ -public class EuiccNotification implements Parcelable { +@SystemApi +public final class EuiccNotification implements Parcelable { /** Event */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = { "EVENT_" }, value = { @@ -43,6 +43,7 @@ public class EuiccNotification implements Parcelable { EVENT_DISABLE, EVENT_DELETE }) + /** @hide */ public @interface Event {} /** A profile is downloaded and installed. */ @@ -57,7 +58,7 @@ public class EuiccNotification implements Parcelable { /** A profile is deleted. */ public static final int EVENT_DELETE = 1 << 3; - /** Value of the bits of all above events */ + /** Value of the bits of all the events including install, enable, disable and delete. */ @Event public static final int ALL_EVENTS = EVENT_INSTALL | EVENT_ENABLE | EVENT_DISABLE | EVENT_DELETE; diff --git a/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java index 7efe04364280..67ae983efeb0 100644 --- a/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java +++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java @@ -16,6 +16,7 @@ package android.telephony.euicc; import android.annotation.IntDef; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.service.carrier.CarrierIdentifier; @@ -27,20 +28,21 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; /** * This represents the RAT (Rules Authorisation Table) stored on eUICC. - * * @hide - * - * TODO(b/35851809): Make this a @SystemApi. */ +@SystemApi public final class EuiccRulesAuthTable implements Parcelable { /** Profile policy rule flags */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = { POLICY_RULE_FLAG_CONSENT_REQUIRED }) + /** @hide */ public @interface PolicyRuleFlag {} /** User consent is required to install the profile. */ @@ -89,12 +91,14 @@ public final class EuiccRulesAuthTable implements Parcelable { * @throws ArrayIndexOutOfBoundsException If the {@code mPosition} is larger than the size * this table. */ - public Builder add(int policyRules, CarrierIdentifier[] carrierId, int policyRuleFlags) { + public Builder add(int policyRules, List<CarrierIdentifier> carrierId, int policyRuleFlags) { if (mPosition >= mPolicyRules.length) { throw new ArrayIndexOutOfBoundsException(mPosition); } mPolicyRules[mPosition] = policyRules; - mCarrierIds[mPosition] = carrierId; + if (carrierId != null && carrierId.size() > 0) { + mCarrierIds[mPosition] = carrierId.toArray(new CarrierIdentifier[carrierId.size()]); + } mPolicyRuleFlags[mPosition] = policyRuleFlags; mPosition++; return this; diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java index f6c5532363e8..f186ee55d2c7 100644 --- a/tests/net/java/android/net/IpSecConfigTest.java +++ b/tests/net/java/android/net/IpSecConfigTest.java @@ -17,6 +17,7 @@ package android.net; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -48,18 +49,12 @@ public class IpSecConfigTest { assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId()); } - @Test - public void testParcelUnparcel() throws Exception { - assertParcelingIsLossless(new IpSecConfig()); - + private IpSecConfig getSampleConfig() { IpSecConfig c = new IpSecConfig(); c.setMode(IpSecTransform.MODE_TUNNEL); c.setSourceAddress("0.0.0.0"); c.setDestinationAddress("1.2.3.4"); - c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP); - c.setEncapSocketResourceId(7); - c.setEncapRemotePort(22); - c.setNattKeepaliveInterval(42); + c.setSpiResourceId(1984); c.setEncryption( new IpSecAlgorithm( IpSecAlgorithm.CRYPT_AES_CBC, @@ -68,7 +63,37 @@ public class IpSecConfigTest { new IpSecAlgorithm( IpSecAlgorithm.AUTH_HMAC_MD5, new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0})); - c.setSpiResourceId(1984); + c.setAuthenticatedEncryption( + new IpSecAlgorithm( + IpSecAlgorithm.AUTH_CRYPT_AES_GCM, + new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0, 1, 2, 3, 4 + }, + 128)); + c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP); + c.setEncapSocketResourceId(7); + c.setEncapRemotePort(22); + c.setNattKeepaliveInterval(42); + c.setMarkValue(12); + c.setMarkMask(23); + + return c; + } + + @Test + public void testCopyConstructor() { + IpSecConfig original = getSampleConfig(); + IpSecConfig copy = new IpSecConfig(original); + + assertTrue(IpSecConfig.equals(original, copy)); + assertFalse(original == copy); + } + + @Test + public void testParcelUnparcel() throws Exception { + assertParcelingIsLossless(new IpSecConfig()); + + IpSecConfig c = getSampleConfig(); assertParcelingIsLossless(c); } diff --git a/tests/net/java/android/net/IpSecTransformTest.java b/tests/net/java/android/net/IpSecTransformTest.java new file mode 100644 index 000000000000..b4342df58549 --- /dev/null +++ b/tests/net/java/android/net/IpSecTransformTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static org.junit.Assert.assertFalse; + +import android.support.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link IpSecTransform}. */ +@SmallTest +@RunWith(JUnit4.class) +public class IpSecTransformTest { + + @Test + public void testCreateTransformCopiesConfig() { + // Create a config with a few parameters to make sure it's not empty + IpSecConfig config = new IpSecConfig(); + config.setSourceAddress("0.0.0.0"); + config.setDestinationAddress("1.2.3.4"); + config.setSpiResourceId(1984); + + IpSecTransform preModification = new IpSecTransform(null, config); + + config.setSpiResourceId(1985); + IpSecTransform postModification = new IpSecTransform(null, config); + + assertFalse(IpSecTransform.equals(preModification, postModification)); + } + + @Test + public void testCreateTransformsWithSameConfigEqual() { + // Create a config with a few parameters to make sure it's not empty + IpSecConfig config = new IpSecConfig(); + config.setSourceAddress("0.0.0.0"); + config.setDestinationAddress("1.2.3.4"); + config.setSpiResourceId(1984); + + IpSecTransform config1 = new IpSecTransform(null, config); + IpSecTransform config2 = new IpSecTransform(null, config); + + assertFalse(IpSecTransform.equals(config1, config2)); + } +} diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt index d6a0a4516a6d..45027b51d3ef 100644 --- a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt +++ b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt @@ -27,6 +27,8 @@ class ParcelableDetector { impl.build() return impl.parcelables } + + const val PARCELABLE_CLASS = "android/os/Parcelable" } private class Impl(val ancestors: Map<String, Ancestors>) { @@ -35,7 +37,7 @@ class ParcelableDetector { fun build() { val classList = ancestors.keys - classList.filterTo(parcelables, this::isParcelable) + classList.filterTo(parcelables, { (it != PARCELABLE_CLASS) && isParcelable(it) }) parcelables.sort() } @@ -44,7 +46,7 @@ class ParcelableDetector { return false } - if (c == "android/os/Parcelable") { + if (c == PARCELABLE_CLASS) { return true } diff --git a/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt index c9bcbc9cadcf..f08173d5b2f1 100644 --- a/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt +++ b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt @@ -28,7 +28,7 @@ class ParcelableDetectorTest { val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap) - assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable")) + assertEquals(parcelables, listOf("android/test/Parcelable")) } @Test @@ -39,7 +39,7 @@ class ParcelableDetectorTest { val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap) - assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable")) + assertEquals(parcelables, listOf("android/test/Parcelable")) } @Test @@ -51,7 +51,7 @@ class ParcelableDetectorTest { val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap) - assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable", "android/test/SuperParcelable")) + assertEquals(parcelables, listOf("android/test/Parcelable", "android/test/SuperParcelable")) } @Test @@ -63,7 +63,7 @@ class ParcelableDetectorTest { val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap) - assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/IParcelable", "android/test/Parcelable")) + assertEquals(parcelables, listOf("android/test/IParcelable", "android/test/Parcelable")) } } |