diff --git a/Android.mk b/Android.mk index 28abb89690798..a4d1107286b3d 100644 --- a/Android.mk +++ b/Android.mk @@ -287,6 +287,7 @@ LOCAL_SRC_FILES += \ core/java/android/service/euicc/IEuiccService.aidl \ core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl \ core/java/android/service/euicc/IGetEidCallback.aidl \ + core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl \ core/java/android/service/gatekeeper/IGateKeeperService.aidl \ core/java/android/service/notification/INotificationListener.aidl \ core/java/android/service/notification/IStatusBarNotificationHolder.aidl \ @@ -754,6 +755,7 @@ aidl_files := \ frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \ frameworks/base/core/java/android/service/euicc/DownloadResult.aidl \ frameworks/base/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl \ + frameworks/base/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl \ frameworks/base/core/java/android/service/notification/Adjustment.aidl \ frameworks/base/core/java/android/service/notification/Condition.aidl \ frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \ diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java new file mode 100644 index 0000000000000..ba6c9a2d1b572 --- /dev/null +++ b/core/java/android/service/euicc/EuiccProfileInfo.java @@ -0,0 +1,84 @@ +/* + * 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.service.euicc; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.UiccAccessRule; +import android.text.TextUtils; + +/** + * Information about an embedded profile (subscription) on an eUICC. + * + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ +public final class EuiccProfileInfo implements Parcelable { + + /** The iccid of the subscription. */ + public final String iccid; + + /** + * Optional access rules defining which apps can manage this subscription. If unset, only the + * platform can manage it. + */ + public final @Nullable UiccAccessRule[] accessRules; + + /** An optional nickname for the subscription. */ + public final @Nullable String nickname; + + public static final Creator CREATOR = new Creator() { + @Override + public EuiccProfileInfo createFromParcel(Parcel in) { + return new EuiccProfileInfo(in); + } + + @Override + public EuiccProfileInfo[] newArray(int size) { + return new EuiccProfileInfo[size]; + } + }; + + public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules, + @Nullable String nickname) { + if (!TextUtils.isDigitsOnly(iccid)) { + throw new IllegalArgumentException("iccid contains invalid characters: " + iccid); + } + this.iccid = iccid; + this.accessRules = accessRules; + this.nickname = nickname; + } + + private EuiccProfileInfo(Parcel in) { + iccid = in.readString(); + accessRules = in.createTypedArray(UiccAccessRule.CREATOR); + nickname = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(iccid); + dest.writeTypedArray(accessRules, flags); + dest.writeString(nickname); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index 03aa967f9611b..917cf7e588877 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -164,6 +164,17 @@ public abstract class EuiccService extends Service { DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim); + /** + * Return a list of all @link EuiccProfileInfo}s. + * + * @param slotId ID of the SIM slot to use when starting the download. This is currently not + * populated but is here to future-proof the APIs. + * @return The result of the operation. + * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList + * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList + */ + public abstract GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId); + /** * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}. */ @@ -205,5 +216,16 @@ public abstract class EuiccService extends Service { // Can't communicate with the phone process; ignore. } } + + @Override + public void getEuiccProfileInfoList(int slotId, IGetEuiccProfileInfoListCallback callback) { + GetEuiccProfileInfoListResult result = + EuiccService.this.onGetEuiccProfileInfoList(slotId); + try { + callback.onComplete(result); + } catch (RemoteException e) { + // Can't communicate with the phone process; ignore. + } + } } } diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl new file mode 100644 index 0000000000000..6003b79462da1 --- /dev/null +++ b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl @@ -0,0 +1,19 @@ +/* + * 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.service.euicc; + +parcelable GetEuiccProfileInfoListResult; diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java new file mode 100644 index 0000000000000..5ac10fef3c233 --- /dev/null +++ b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java @@ -0,0 +1,128 @@ +/* + * 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.service.euicc; + +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Result of a {@link EuiccService#onGetEuiccProfileInfoList} operation. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ +public final class GetEuiccProfileInfoListResult implements Parcelable { + + public static final Creator CREATOR = + new Creator() { + @Override + public GetEuiccProfileInfoListResult createFromParcel(Parcel in) { + return new GetEuiccProfileInfoListResult(in); + } + + @Override + public GetEuiccProfileInfoListResult[] newArray(int size) { + return new GetEuiccProfileInfoListResult[size]; + } + }; + + /** @hide */ + @IntDef({ + RESULT_OK, + RESULT_GENERIC_ERROR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ResultCode {} + + public static final int RESULT_OK = 0; + public static final int RESULT_GENERIC_ERROR = 1; + + /** Result of the operation - one of the RESULT_* constants. */ + public final @ResultCode int result; + + /** Implementation-defined detailed error code in case of a failure not covered here. */ + public final int detailedCode; + + /** The profile list (only upon success). */ + @Nullable + public final EuiccProfileInfo[] profiles; + + /** Whether the eUICC is removable. */ + public final boolean isRemovable; + + private GetEuiccProfileInfoListResult(int result, int detailedCode, EuiccProfileInfo[] profiles, + boolean isRemovable) { + this.result = result; + this.detailedCode = detailedCode; + this.profiles = profiles; + this.isRemovable = isRemovable; + } + + private GetEuiccProfileInfoListResult(Parcel in) { + this.result = in.readInt(); + this.detailedCode = in.readInt(); + this.profiles = in.createTypedArray(EuiccProfileInfo.CREATOR); + this.isRemovable = in.readBoolean(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(result); + dest.writeInt(detailedCode); + dest.writeTypedArray(profiles, flags); + dest.writeBoolean(isRemovable); + } + + /** + * Return a result indicating that the listing was successful. + * + * @param profiles the list of profiles + * @param isRemovable whether the eUICC in this slot is removable. If true, the profiles + * returned here will only be considered accessible as long as this eUICC is present. + * Otherwise, they will remain accessible until the next time a response with isRemovable + * set to false is returned. + */ + public static GetEuiccProfileInfoListResult success( + EuiccProfileInfo[] profiles, boolean isRemovable) { + return new GetEuiccProfileInfoListResult( + RESULT_OK, 0 /* detailedCode */, profiles, isRemovable); + } + + /** + * Return a result indicating that an error occurred for which no other more specific error + * code has been defined. + * + * @param detailedCode an implementation-defined detailed error code for debugging purposes. + * @param isRemovable whether the eUICC in this slot is removable. If true, only removable + * profiles will be made inaccessible. Otherwise, all embedded profiles will be + * considered inaccessible. + */ + public static GetEuiccProfileInfoListResult genericError( + int detailedCode, boolean isRemovable) { + return new GetEuiccProfileInfoListResult( + RESULT_GENERIC_ERROR, detailedCode, null /* profiles */, isRemovable); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl index 3658d9a357beb..502fc844977ed 100644 --- a/core/java/android/service/euicc/IEuiccService.aidl +++ b/core/java/android/service/euicc/IEuiccService.aidl @@ -19,6 +19,7 @@ package android.service.euicc; import android.service.euicc.IDownloadSubscriptionCallback; import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback; import android.service.euicc.IGetEidCallback; +import android.service.euicc.IGetEuiccProfileInfoListCallback; import android.telephony.euicc.DownloadableSubscription; /** @hide */ @@ -29,4 +30,5 @@ oneway interface IEuiccService { void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription, boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback); void getEid(int slotId, in IGetEidCallback callback); + void getEuiccProfileInfoList(int slotId, in IGetEuiccProfileInfoListCallback callback); } \ No newline at end of file diff --git a/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl b/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl new file mode 100644 index 0000000000000..761ec1f01324c --- /dev/null +++ b/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl @@ -0,0 +1,24 @@ +/* + * 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.service.euicc; + +import android.service.euicc.GetEuiccProfileInfoListResult; + +/** @hide */ +oneway interface IGetEuiccProfileInfoListCallback { + void onComplete(in GetEuiccProfileInfoListResult result); +} \ No newline at end of file diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index cf2d27e287090..4e1c15fa12516 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -16,7 +16,10 @@ package android.telephony; +import android.annotation.Nullable; import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -30,6 +33,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.DisplayMetrics; +import java.util.Arrays; + /** * A Parcelable class for Subscription Information. */ @@ -109,12 +114,35 @@ public class SubscriptionInfo implements Parcelable { */ private String mCountryIso; + /** + * Whether the subscription is an embedded one. + */ + private boolean mIsEmbedded; + + /** + * The access rules for this subscription, if it is embedded and defines any. + */ + @Nullable + private UiccAccessRule[] mAccessRules; + /** * @hide */ public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, int mcc, int mnc, String countryIso) { + this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, + roaming, icon, mcc, mnc, countryIso, false /* isEmbedded */, + null /* accessRules */); + } + + /** + * @hide + */ + public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, + CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, + Bitmap icon, int mcc, int mnc, String countryIso, boolean isEmbedded, + @Nullable UiccAccessRule[] accessRules) { this.mId = id; this.mIccId = iccId; this.mSimSlotIndex = simSlotIndex; @@ -128,6 +156,8 @@ public class SubscriptionInfo implements Parcelable { this.mMcc = mcc; this.mMnc = mnc; this.mCountryIso = countryIso; + this.mIsEmbedded = isEmbedded; + this.mAccessRules = accessRules; } /** @@ -284,6 +314,79 @@ public class SubscriptionInfo implements Parcelable { return this.mCountryIso; } + /** + * @return whether the subscription is an embedded one. + * @hide + * + * TODO(b/35851809): Make this public. + */ + public boolean isEmbedded() { + return this.mIsEmbedded; + } + + /** + * Checks whether the app with the given context is authorized to manage this subscription + * according to its metadata. Only supported for embedded subscriptions (if {@link #isEmbedded} + * returns true). + * + * @param context Context of the application to check. + * @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. + */ + public boolean canManageSubscription(Context context) { + return canManageSubscription(context, context.getPackageName()); + } + + /** + * Checks whether the given app is authorized to manage this subscription according to its + * metadata. Only supported for embedded subscriptions (if {@link #isEmbedded} returns true). + * + * @param context Any context. + * @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(Context context, String packageName) { + if (!isEmbedded()) { + throw new UnsupportedOperationException("Not an embedded subscription"); + } + if (mAccessRules == null) { + return false; + } + PackageManager packageManager = context.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 : mAccessRules) { + if (rule.getCarrierPrivilegeStatus(packageInfo) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return true; + } + } + return false; + } + + /** + * @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() { + if (!isEmbedded()) { + throw new UnsupportedOperationException("Not an embedded subscription"); + } + return mAccessRules; + } + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public SubscriptionInfo createFromParcel(Parcel source) { @@ -300,9 +403,12 @@ public class SubscriptionInfo implements Parcelable { int mnc = source.readInt(); String countryIso = source.readString(); Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source); + boolean isEmbedded = source.readBoolean(); + UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR); return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName, - nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso); + nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, + isEmbedded, accessRules); } @Override @@ -326,6 +432,8 @@ public class SubscriptionInfo implements Parcelable { dest.writeInt(mMnc); dest.writeString(mCountryIso); mIconBitmap.writeToParcel(dest, flags); + dest.writeBoolean(mIsEmbedded); + dest.writeTypedArray(mAccessRules, flags); } @Override @@ -355,6 +463,7 @@ public class SubscriptionInfo implements Parcelable { + " displayName=" + mDisplayName + " carrierName=" + mCarrierName + " nameSource=" + mNameSource + " iconTint=" + mIconTint + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc - + " mnc " + mMnc + "}"; + + " mnc " + mMnc + " isEmbedded " + mIsEmbedded + + " accessRules " + Arrays.toString(mAccessRules) + "}"; } } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 7f616ad6fb080..77525ff500401 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -24,17 +24,17 @@ import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.net.Uri; -import android.telephony.Rlog; import android.os.Handler; import android.os.Message; -import android.os.ServiceManager; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.DisplayMetrics; -import com.android.internal.telephony.ISub; import com.android.internal.telephony.IOnSubscriptionsChangedListener; +import com.android.internal.telephony.ISub; import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.PhoneConstants; + import java.util.ArrayList; import java.util.List; @@ -45,7 +45,8 @@ import java.util.List; * You do not instantiate this class directly; instead, you retrieve * a reference to an instance through {@link #from}. *

- * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE. + * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE unless otherwise + * specified. */ public class SubscriptionManager { private static final String LOG_TAG = "SubscriptionManager"; @@ -259,6 +260,32 @@ public class SubscriptionManager { */ public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status"; + /** + * TelephonyProvider column name for whether a subscription is embedded (that is, present on an + * eSIM). + *

Type: INTEGER (int), 1 for embedded or 0 for non-embedded. + * @hide + */ + public static final String IS_EMBEDDED = "is_embedded"; + + /** + * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from + * {@link UiccAccessRule#encodeRules}. Only present if {@link #IS_EMBEDDED} is 1. + *

TYPE: BLOB + * @hide + */ + public static final String ACCESS_RULES = "access_rules"; + + /** + * TelephonyProvider column name identifying whether an embedded subscription is on a removable + * card. Such subscriptions are marked inaccessible as soon as the current card is removed. + * Otherwise, they will remain accessible unless explicitly deleted. Only present if + * {@link #IS_EMBEDDED} is 1. + *

TYPE: INTEGER (int), 1 for removable or 0 for non-removable. + * @hide + */ + public static final String IS_REMOVABLE = "is_removable"; + /** * TelephonyProvider column name for extreme threat in CB settings * @hide @@ -632,6 +659,112 @@ public class SubscriptionManager { return result; } + /** + * Gets the SubscriptionInfo(s) of all available subscriptions, if any. + * + *

Available subscriptions include active ones (those with a non-negative + * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded + * subscriptions. + * + *

The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by + * {@link SubscriptionInfo#getSubscriptionId}. + * + * @return Sorted list of the current {@link SubscriptionInfo} records available on the + * device. + *

    + *
  • + * If null is returned the current state is unknown but if a + * {@link OnSubscriptionsChangedListener} has been registered + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. + *
  • + * If the list is empty then there are no {@link SubscriptionInfo} records currently available. + *
  • + * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} + * then by {@link SubscriptionInfo#getSubscriptionId}. + *
+ * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + public List getAvailableSubscriptionInfoList() { + List result = null; + + try { + ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); + if (iSub != null) { + result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName()); + } + } catch (RemoteException ex) { + // ignore it + } + return result; + } + + /** + * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if + * any. + * + *

Only those subscriptions for which the calling app has carrier privileges per the + * subscription metadata, if any, will be included in the returned list. + * + *

The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by + * {@link SubscriptionInfo#getSubscriptionId}. + * + * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the + * device which are accessible to the caller. + *

    + *
  • + * If null is returned the current state is unknown but if a + * {@link OnSubscriptionsChangedListener} has been registered + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. + *
  • + * If the list is empty then there are no {@link SubscriptionInfo} records currently available. + *
  • + * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} + * then by {@link SubscriptionInfo#getSubscriptionId}. + *
+ * @hide + * + * TODO(b/35851809): Make this public. + */ + public List getAccessibleSubscriptionInfoList() { + List result = null; + + try { + ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); + if (iSub != null) { + result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName()); + } + } catch (RemoteException ex) { + // ignore it + } + return result; + } + + /** + * Request a refresh of the platform cache of profile information. + * + *

Should be called by the EuiccService implementation whenever this information changes due + * to an operation done outside the scope of a request initiated by the platform to the + * EuiccService. There is no need to refresh for downloads, deletes, or other operations that + * were made through the EuiccService. + * + *

Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + public void requestEmbeddedSubscriptionInfoListRefresh() { + try { + ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); + if (iSub != null) { + iSub.requestEmbeddedSubscriptionInfoListRefresh(); + } + } catch (RemoteException ex) { + // ignore it + } + } + /** * @return the count of all subscriptions in the database, this includes * all subscriptions that have been seen. diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java index 1ac4c5cf7d801..e42a758350083 100644 --- a/telephony/java/android/telephony/UiccAccessRule.java +++ b/telephony/java/android/telephony/UiccAccessRule.java @@ -16,7 +16,6 @@ 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; @@ -63,7 +62,11 @@ public final class UiccAccessRule implements Parcelable { * Encode these access rules as a byte array which can be parsed with {@link #decodeRules}. * @hide */ - public static byte[] encodeRules(UiccAccessRule[] accessRules) { + @Nullable + public static byte[] encodeRules(@Nullable UiccAccessRule[] accessRules) { + if (accessRules == null) { + return null; + } try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(baos); @@ -72,7 +75,12 @@ public final class UiccAccessRule implements Parcelable { for (UiccAccessRule accessRule : accessRules) { output.writeInt(accessRule.mCertificateHash.length); output.write(accessRule.mCertificateHash); - output.writeUTF(accessRule.mPackageName); + if (accessRule.mPackageName != null) { + output.writeBoolean(true); + output.writeUTF(accessRule.mPackageName); + } else { + output.writeBoolean(false); + } output.writeLong(accessRule.mAccessType); } output.close(); @@ -87,7 +95,11 @@ public final class UiccAccessRule implements Parcelable { * Decodes a byte array generated with {@link #encodeRules}. * @hide */ - public static UiccAccessRule[] decodeRules(byte[] encodedRules) { + @Nullable + public static UiccAccessRule[] decodeRules(@Nullable byte[] encodedRules) { + if (encodedRules == null) { + return null; + } ByteArrayInputStream bais = new ByteArrayInputStream(encodedRules); try (DataInputStream input = new DataInputStream(bais)) { input.readInt(); // version; currently ignored @@ -97,7 +109,7 @@ public final class UiccAccessRule implements Parcelable { int certificateHashLength = input.readInt(); byte[] certificateHash = new byte[certificateHashLength]; input.readFully(certificateHash); - String packageName = input.readUTF(); + String packageName = input.readBoolean() ? input.readUTF() : null; long accessType = input.readLong(); accessRules[i] = new UiccAccessRule(certificateHash, packageName, accessType); } diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 71f2c6b80927c..644ad49734dc4 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -93,6 +93,21 @@ interface ISub { */ int getActiveSubInfoCountMax(); + /** + * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList + */ + List getAvailableSubscriptionInfoList(String callingPackage); + + /** + * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList + */ + List getAccessibleSubscriptionInfoList(String callingPackage); + + /** + * @see android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh + */ + oneway void requestEmbeddedSubscriptionInfoListRefresh(); + /** * Add a new SubscriptionInfo to subinfo database if needed * @param iccId the IccId of the SIM card