diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-04-17 19:22:43 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-04-17 19:22:49 +0000 |
commit | 8e3b1a63f9cd76a71ecbfc8c6a0c68b4cbecab90 (patch) | |
tree | c65386d19eafacbab0b237cab86ca926ace21fe9 | |
parent | dbe270ce058afa3f61e5bf62c293ff37960d1617 (diff) | |
parent | cfa70fa0abe90d91bd7997ef23432e5631b40d2a (diff) |
Merge "EUICC API changes to support error resolution."
7 files changed, 138 insertions, 60 deletions
diff --git a/core/java/android/service/euicc/DownloadResult.java b/core/java/android/service/euicc/DownloadResult.java index 0aa55fbbc0ff..4e2af5343232 100644 --- a/core/java/android/service/euicc/DownloadResult.java +++ b/core/java/android/service/euicc/DownloadResult.java @@ -46,14 +46,14 @@ public final class DownloadResult implements Parcelable { @IntDef({ RESULT_OK, RESULT_GENERIC_ERROR, - RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, + RESULT_MUST_DEACTIVATE_SIM, }) @Retention(RetentionPolicy.SOURCE) public @interface ResultCode {} public static final int RESULT_OK = 0; public static final int RESULT_GENERIC_ERROR = 1; - public static final int RESULT_MUST_DEACTIVATE_REMOVABLE_SIM = 2; + public static final int RESULT_MUST_DEACTIVATE_SIM = 2; /** Result of the operation - one of the RESULT_* constants. */ public final @ResultCode int result; @@ -83,11 +83,10 @@ public final class DownloadResult implements Parcelable { } /** - * Return a result indicating that the removable SIM must be deactivated to perform the - * operation. + * Return a result indicating that an active SIM must be deactivated to perform the operation. */ - public static DownloadResult mustDeactivateRemovableSim() { - return new DownloadResult(RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, 0); + public static DownloadResult mustDeactivateSim() { + return new DownloadResult(RESULT_MUST_DEACTIVATE_SIM, 0); } /** diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index 6407507549b1..03aa967f9611 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.telephony.euicc.DownloadableSubscription; +import android.util.ArraySet; /** * Service interface linking the system with an eUICC local profile assistant (LPA) application. @@ -74,6 +75,33 @@ public abstract class EuiccService extends Service { public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; + // LUI resolution actions. These are called by the platform to resolve errors in situations that + // 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. */ + public static final String ACTION_RESOLVE_DEACTIVATE_SIM = + "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM"; + /** + * Alert the user about a download/switch being done for an app that doesn't currently have + * carrier privileges. + */ + public static final String ACTION_RESOLVE_NO_PRIVILEGES = + "android.service.euicc.action.RESOLVE_NO_PRIVILEGES"; + /** + * List of all valid resolution actions for validation purposes. + * @hide + */ + public static final ArraySet<String> RESOLUTION_ACTIONS; + static { + RESOLUTION_ACTIONS = new ArraySet<>(); + RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM); + RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES); + } + + /** Boolean extra for resolution actions indicating whether the user granted consent. */ + public static final String RESOLUTION_EXTRA_CONSENT = "consent"; + private final IEuiccService.Stub mStubWrapper; public EuiccService() { @@ -107,11 +135,15 @@ public abstract class EuiccService extends Service { * @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. * @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 GetDownloadableSubscriptionMetadataResult#mustDeactivateSim()} should be returned + * to allow the user to consent to this operation first. * @return The result of the operation. * @see android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata */ public abstract GetDownloadableSubscriptionMetadataResult getDownloadableSubscriptionMetadata( - int slotId, DownloadableSubscription subscription); + int slotId, DownloadableSubscription subscription, boolean forceDeactivateSim); /** * Download the given subscription. @@ -121,11 +153,16 @@ public abstract class EuiccService extends Service { * @param subscription The subscription to download. * @param switchAfterDownload If true, the subscription should be enabled upon successful * download. + * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the + * eUICC, perform this action automatically. Otherwise, + * {@link DownloadResult#mustDeactivateSim()} should be returned to allow the user to + * consent to this operation first. * @return the result of the download operation. * @see android.telephony.euicc.EuiccManager#downloadSubscription */ public abstract DownloadResult downloadSubscription(int slotId, - DownloadableSubscription subscription, boolean switchAfterDownload); + DownloadableSubscription subscription, boolean switchAfterDownload, + boolean forceDeactivateSim); /** * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}. @@ -133,9 +170,10 @@ public abstract class EuiccService extends Service { private class IEuiccServiceWrapper extends IEuiccService.Stub { @Override public void downloadSubscription(int slotId, DownloadableSubscription subscription, - boolean switchAfterDownload, IDownloadSubscriptionCallback callback) { + boolean switchAfterDownload, boolean forceDeactivateSim, + IDownloadSubscriptionCallback callback) { DownloadResult result = EuiccService.this.downloadSubscription( - slotId, subscription, switchAfterDownload); + slotId, subscription, switchAfterDownload, forceDeactivateSim); try { callback.onComplete(result); } catch (RemoteException e) { @@ -156,9 +194,11 @@ public abstract class EuiccService extends Service { @Override public void getDownloadableSubscriptionMetadata(int slotId, DownloadableSubscription subscription, + boolean forceDeactivateSim, IGetDownloadableSubscriptionMetadataCallback callback) { GetDownloadableSubscriptionMetadataResult result = - EuiccService.this.getDownloadableSubscriptionMetadata(slotId, subscription); + EuiccService.this.getDownloadableSubscriptionMetadata( + slotId, subscription, forceDeactivateSim); try { callback.onComplete(result); } catch (RemoteException e) { diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java index 04f49808b383..ca3c1597fa58 100644 --- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java +++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java @@ -49,13 +49,13 @@ public final class GetDownloadableSubscriptionMetadataResult implements Parcelab @IntDef({ RESULT_OK, RESULT_GENERIC_ERROR, - RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, + RESULT_MUST_DEACTIVATE_SIM, }) @Retention(RetentionPolicy.SOURCE) public @interface ResultCode {} public static final int RESULT_OK = 0; - public static final int RESULT_MUST_DEACTIVATE_REMOVABLE_SIM = 1; + public static final int RESULT_MUST_DEACTIVATE_SIM = 1; public static final int RESULT_GENERIC_ERROR = 2; /** Result of the operation - one of the RESULT_* constants. */ @@ -100,11 +100,10 @@ public final class GetDownloadableSubscriptionMetadataResult implements Parcelab } /** - * Return a result indicating that the removable SIM must be deactivated to perform the - * operation. + * Return a result indicating that an active SIM must be deactivated to perform the operation. */ - public static GetDownloadableSubscriptionMetadataResult mustDeactivateRemovableSim() { - return new GetDownloadableSubscriptionMetadataResult(RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, + public static GetDownloadableSubscriptionMetadataResult mustDeactivateSim() { + return new GetDownloadableSubscriptionMetadataResult(RESULT_MUST_DEACTIVATE_SIM, null /* subscription */, 0 /* detailedCode */); } diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl index 58fe262c8541..3658d9a357be 100644 --- a/core/java/android/service/euicc/IEuiccService.aidl +++ b/core/java/android/service/euicc/IEuiccService.aidl @@ -24,8 +24,9 @@ import android.telephony.euicc.DownloadableSubscription; /** @hide */ oneway interface IEuiccService { void downloadSubscription(int slotId, in DownloadableSubscription subscription, - boolean switchAfterDownload, in IDownloadSubscriptionCallback callback); + boolean switchAfterDownload, boolean forceDeactivateSim, + in IDownloadSubscriptionCallback callback); void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription, - in IGetDownloadableSubscriptionMetadataCallback callback); + boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback); void getEid(int slotId, in IGetEidCallback callback); }
\ No newline at end of file diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java index b12864cf3077..b5484e344a1c 100644 --- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java +++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java @@ -56,8 +56,6 @@ public final class DownloadableSubscription implements Parcelable { // see getCarrierName and setCarrierName @Nullable private String carrierName; - // see isConsentGranted and setConsentGranted - private boolean consentGranted; // see getAccessRules and setAccessRules private UiccAccessRule[] accessRules; @@ -69,7 +67,6 @@ public final class DownloadableSubscription implements Parcelable { private DownloadableSubscription(Parcel in) { encodedActivationCode = in.readString(); carrierName = in.readString(); - consentGranted = in.readInt() == 1; accessRules = in.createTypedArray(UiccAccessRule.CREATOR); } @@ -110,28 +107,6 @@ public final class DownloadableSubscription implements Parcelable { return carrierName; } - - /** - * Mark this download as being consented to by the user. - * @hide - */ - public void setConsentGranted() { - consentGranted = true; - } - - /** - * Returns whether the user has granted consent to download this subscription. - * - * <p>The {@link android.service.euicc.EuiccService} implementation should permit a subscription - * download if this is set, even if the calling app doesn't have permission to download it. - * @hide - * - * TODO(b/35851809): Make this a SystemApi. - */ - public boolean isConsentGranted() { - return consentGranted; - } - /** * Returns the {@link UiccAccessRule}s dictating access to this subscription. * @@ -156,22 +131,10 @@ public final class DownloadableSubscription implements Parcelable { this.accessRules = accessRules; } - /** - * Unset any untrusted fields. - * - * <p>Should be called by the platform whenever an instance is received from an untrusted - * source to reset any secure fields that may only be set by the platform. - * @hide - */ - public final void clearUntrustedFields() { - this.consentGranted = false; - } - @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(encodedActivationCode); dest.writeString(carrierName); - dest.writeInt(consentGranted ? 1 : 0); dest.writeTypedArray(accessRules, flags); } diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 10492c0bb6ff..8bc0be636ddb 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -22,7 +22,9 @@ import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.content.IntentSender; import android.content.pm.PackageManager; +import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; @@ -71,6 +73,13 @@ public class EuiccManager { "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; /** + * Intent action to handle a resolvable error. + * @hide + */ + public static final String ACTION_RESOLVE_ERROR = + "android.telephony.euicc.action.RESOLVE_ERROR"; + + /** * Result code for an operation indicating that the operation succeeded. */ public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; @@ -105,7 +114,7 @@ public class EuiccManager { "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE"; /** - * The key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result + * Key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result * callbacks providing the downloadable subscription metadata. * @hide * @@ -114,6 +123,30 @@ public class EuiccManager { public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION"; + /** + * Key for an extra set on {@link PendingIntent} result callbacks providing the resolution + * pending intent for {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}s. + * @hide + */ + public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT = + "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT"; + + /** + * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent + * containing the EuiccService action to launch for resolution. + * @hide + */ + public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION = + "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION"; + + /** + * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent + * providing the callback to execute after resolution is completed. + * @hide + */ + public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT = + "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT"; + private final Context mContext; private final IEuiccController mController; @@ -191,6 +224,8 @@ public class EuiccManager { * <p>If an operation returns {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}, this * method may be called to prompt the user to resolve the issue. * + * <p>This method may only be called once for a particular error. + * * @param activity the calling activity (which should be in the foreground). * @param requestCode an application-specific request code which will be provided to * {@link Activity#onActivityResult} upon completion. Note that the operation may still be @@ -200,11 +235,49 @@ public class EuiccManager { * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}. * @param callbackIntent a PendingIntent to launch when the operation completes. This is * trigered upon completion of the original operation that required user resolution. + * @throws android.content.IntentSender.SendIntentException if called more than once. */ public void startResolutionActivity(Activity activity, int requestCode, Intent resultIntent, - PendingIntent callbackIntent) { - // TODO(b/33075886): Implement this API. - throw new UnsupportedOperationException("Not implemented"); + PendingIntent callbackIntent) throws IntentSender.SendIntentException { + PendingIntent resolutionIntent = + resultIntent.getParcelableExtra(EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT); + if (resolutionIntent == null) { + throw new IllegalArgumentException("Invalid result intent"); + } + Intent fillInIntent = new Intent(); + fillInIntent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT, + callbackIntent); + activity.startIntentSenderForResult(resolutionIntent.getIntentSender(), requestCode, + fillInIntent, 0 /* flagsMask */, 0 /* flagsValues */, 0 /* extraFlags */); + } + + /** + * Continue an operation after the user resolves an error. + * + * <p>To be called by the LUI upon completion of a resolvable error flow. + * + * @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 + */ + @SystemApi + public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) { + if (!isEnabled()) { + PendingIntent callbackIntent = + resolutionIntent.getParcelableExtra( + EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT); + if (callbackIntent != null) { + sendUnavailableError(callbackIntent); + } + return; + } + try { + mController.continueOperation(resolutionIntent, resolutionExtras); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl index de198c1a7675..5f03dd97d785 100644 --- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl +++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl @@ -17,10 +17,13 @@ package com.android.internal.telephony.euicc; import android.app.PendingIntent; +import android.content.Intent; +import android.os.Bundle; import android.telephony.euicc.DownloadableSubscription; /** @hide */ interface IEuiccController { + oneway void continueOperation(in Intent resolutionIntent, in Bundle resolutionExtras); oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription, in PendingIntent callbackIntent); String getEid(); |