Merge "Support profile policy rule as a resolvable error."
am: 997a88853b

Change-Id: I3de60be5f94e60399e7a7339014d9dc79c258293
diff --git a/api/system-current.txt b/api/system-current.txt
index 52a6985..1eba1c9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4435,6 +4435,16 @@
 
 package android.service.euicc {
 
+  public final class DownloadSubscriptionResult implements android.os.Parcelable {
+    ctor public DownloadSubscriptionResult(int, int, int);
+    method public int describeContents();
+    method public int getCardId();
+    method public int getResolvableErrors();
+    method public int getResult();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.euicc.DownloadSubscriptionResult> CREATOR;
+  }
+
   public final class EuiccProfileInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.service.carrier.CarrierIdentifier getCarrierIdentifier();
@@ -4488,7 +4498,8 @@
     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 android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, android.telephony.euicc.DownloadableSubscription, boolean, boolean, android.os.Bundle);
+    method public deprecated 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);
@@ -4502,19 +4513,25 @@
     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 deprecated 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 ACTION_RESOLVE_RESOLVABLE_ERRORS = "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
     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_ALLOW_POLICY_RULES = "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES";
     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 java.lang.String EXTRA_RESOLVABLE_ERRORS = "android.service.euicc.extra.RESOLVABLE_ERRORS";
+    field public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1; // 0x1
+    field public static final int RESOLVABLE_ERROR_POLICY_RULES = 2; // 0x2
     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 deprecated int RESULT_NEED_CONFIRMATION_CODE = -2; // 0xfffffffe
     field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_RESOLVABLE_ERRORS = -2; // 0xfffffffe
   }
 
   public static abstract class EuiccService.OtaStatusChangedCallback {
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 6025766..e717c1e 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1499,7 +1499,6 @@
 Landroid/service/dreams/IDreamManager;->isDreaming()Z
 Landroid/service/dreams/IDreamManager;->setDreamComponents([Landroid/content/ComponentName;)V
 Landroid/service/euicc/IDeleteSubscriptionCallback;->onComplete(I)V
-Landroid/service/euicc/IDownloadSubscriptionCallback;->onComplete(I)V
 Landroid/service/euicc/IEraseSubscriptionsCallback;->onComplete(I)V
 Landroid/service/euicc/IEuiccService$Stub;-><init>()V
 Landroid/service/euicc/IGetDefaultDownloadableSubscriptionListCallback;->onComplete(Landroid/service/euicc/GetDefaultDownloadableSubscriptionListResult;)V
diff --git a/core/java/android/service/euicc/DownloadSubscriptionResult.aidl b/core/java/android/service/euicc/DownloadSubscriptionResult.aidl
new file mode 100644
index 0000000..b625fd6
--- /dev/null
+++ b/core/java/android/service/euicc/DownloadSubscriptionResult.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.euicc;
+
+parcelable DownloadSubscriptionResult;
diff --git a/core/java/android/service/euicc/DownloadSubscriptionResult.java b/core/java/android/service/euicc/DownloadSubscriptionResult.java
new file mode 100644
index 0000000..b410e35
--- /dev/null
+++ b/core/java/android/service/euicc/DownloadSubscriptionResult.java
@@ -0,0 +1,99 @@
+/*
+ * 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 android.service.euicc;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.euicc.EuiccService.ResolvableError;
+import android.service.euicc.EuiccService.Result;
+
+/**
+ * Result of a {@link EuiccService#onDownloadSubscription} operation.
+ * @hide
+ */
+@SystemApi
+public final class DownloadSubscriptionResult implements Parcelable {
+
+    public static final Creator<DownloadSubscriptionResult> CREATOR =
+            new Creator<DownloadSubscriptionResult>() {
+        @Override
+        public DownloadSubscriptionResult createFromParcel(Parcel in) {
+            return new DownloadSubscriptionResult(in);
+        }
+
+        @Override
+        public DownloadSubscriptionResult[] newArray(int size) {
+            return new DownloadSubscriptionResult[size];
+        }
+    };
+
+    private final @Result int mResult;
+    private final @ResolvableError int mResolvableErrors;
+    private final int mCardId;
+
+    public DownloadSubscriptionResult(@Result int result, @ResolvableError int resolvableErrors,
+            int cardId) {
+        this.mResult = result;
+        this.mResolvableErrors = resolvableErrors;
+        this.mCardId = cardId;
+    }
+
+    /** Gets the result of the operation. */
+    public @Result int getResult() {
+        return mResult;
+    }
+
+    /**
+     * Gets the bit map of resolvable errors.
+     *
+     * <p>The value is passed from EuiccService. The values can be
+     *
+     * <ul>
+     * <li>{@link EuiccService#RESOLVABLE_ERROR_CONFIRMATION_CODE}
+     * <li>{@link EuiccService#RESOLVABLE_ERROR_POLICY_RULES}
+     * </ul>
+     */
+    public @ResolvableError int getResolvableErrors() {
+        return mResolvableErrors;
+    }
+
+    /**
+     * Gets the card Id. This is used when resolving resolvable errors. The value is passed from
+     * EuiccService.
+     */
+    public int getCardId() {
+        return mCardId;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mResult);
+        dest.writeInt(mResolvableErrors);
+        dest.writeInt(mCardId);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    private DownloadSubscriptionResult(Parcel in) {
+        this.mResult = in.readInt();
+        this.mResolvableErrors = in.readInt();
+        this.mCardId = in.readInt();
+    }
+}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index b87faef..b84e556 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -16,17 +16,24 @@
 package android.service.euicc;
 
 import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.telephony.TelephonyManager;
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccInfo;
 import android.telephony.euicc.EuiccManager.OtaStatus;
 import android.util.ArraySet;
+import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -73,6 +80,8 @@
  */
 @SystemApi
 public abstract class EuiccService extends Service {
+    private static final String TAG = "EuiccService";
+
     /** Action which must be included in this service's intent filter. */
     public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
 
@@ -108,30 +117,91 @@
     public static final String ACTION_RESOLVE_NO_PRIVILEGES =
             "android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
 
-    /** Ask the user to input carrier confirmation code. */
+    /**
+     * Ask the user to input carrier confirmation code.
+     *
+     * @deprecated From Q, the resolvable errors happened in the download step are presented as
+     * bit map in {@link #EXTRA_RESOLVABLE_ERRORS}. The corresponding action would be
+     * {@link #ACTION_RESOLVE_RESOLVABLE_ERRORS}.
+     */
+    @Deprecated
     public static final String ACTION_RESOLVE_CONFIRMATION_CODE =
             "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
 
+    /** Ask the user to resolve all the resolvable errors. */
+    public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS =
+            "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "RESOLVABLE_ERROR_" }, value = {
+            RESOLVABLE_ERROR_CONFIRMATION_CODE,
+            RESOLVABLE_ERROR_POLICY_RULES,
+    })
+    public @interface ResolvableError {}
+
+    /**
+     * Possible value for the bit map of resolvable errors indicating the download process needs
+     * the user to input confirmation code.
+     */
+    public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1 << 0;
+    /**
+     * Possible value for the bit map of resolvable errors indicating the download process needs
+     * the user's consent to allow profile policy rules.
+     */
+    public static final int RESOLVABLE_ERROR_POLICY_RULES = 1 << 1;
+
     /**
      * 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.
+     * ACTION_RESOLVE_NO_PRIVILEGES and ACTION_RESOLVE_RESOLVABLE_ERRORS.
      */
     public static final String EXTRA_RESOLUTION_CALLING_PACKAGE =
             "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
 
     /**
+     * Intent extra set for resolution requests containing the list of resolvable errors to be
+     * resolved. Each resolvable error is an integer. Its possible values include:
+     * <UL>
+     * <LI>{@link #RESOLVABLE_ERROR_CONFIRMATION_CODE}
+     * <LI>{@link #RESOLVABLE_ERROR_POLICY_RULES}
+     * </UL>
+     */
+    public static final String EXTRA_RESOLVABLE_ERRORS =
+            "android.service.euicc.extra.RESOLVABLE_ERRORS";
+
+    /**
      * Intent extra set for resolution requests containing a boolean indicating whether to ask the
      * user to retry another confirmation code.
      */
     public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED =
             "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "RESULT_" }, value = {
+            RESULT_OK,
+            RESULT_MUST_DEACTIVATE_SIM,
+            RESULT_RESOLVABLE_ERRORS,
+            RESULT_NEED_CONFIRMATION_CODE,
+            RESULT_FIRST_USER,
+    })
+    public @interface Result {}
+
     /** Result code for a successful operation. */
     public static final int RESULT_OK = 0;
     /** Result code indicating that an active SIM must be deactivated to perform the operation. */
     public static final int RESULT_MUST_DEACTIVATE_SIM = -1;
-    /** Result code indicating that the user must input a carrier confirmation code. */
+    /** Result code indicating that the user must resolve resolvable errors. */
+    public static final int RESULT_RESOLVABLE_ERRORS = -2;
+    /**
+     * Result code indicating that the user must input a carrier confirmation code.
+     *
+     * @deprecated From Q, the resolvable errors happened in the download step are presented as
+     * bit map in {@link #EXTRA_RESOLVABLE_ERRORS}. The corresponding result would be
+     * {@link #RESULT_RESOLVABLE_ERRORS}.
+     */
+    @Deprecated
     public static final int RESULT_NEED_CONFIRMATION_CODE = -2;
     // New predefined codes should have negative values.
 
@@ -147,7 +217,7 @@
         RESOLUTION_ACTIONS = new ArraySet<>();
         RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
         RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
-        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE);
+        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS);
     }
 
     /**
@@ -162,6 +232,12 @@
      */
     public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE =
             "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
+    /**
+     * String extra for resolution actions indicating whether the user allows policy rules.
+     * This is used and set by the implementation and used in {@code EuiccOperation}.
+     */
+    public static final String EXTRA_RESOLUTION_ALLOW_POLICY_RULES =
+            "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES";
 
     private final IEuiccService.Stub mStubWrapper;
 
@@ -229,8 +305,7 @@
     /**
      * Return the EID of the eUICC.
      *
-     * @param slotId ID of the SIM slot being queried. This is currently not populated but is here
-     *     to future-proof the APIs.
+     * @param slotId ID of the SIM slot being queried.
      * @return the EID.
      * @see android.telephony.euicc.EuiccManager#getEid
      */
@@ -240,8 +315,7 @@
     /**
      * Return the status of OTA update.
      *
-     * @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 status of Euicc OTA update.
      * @see android.telephony.euicc.EuiccManager#getOtaStatus
      */
@@ -250,8 +324,7 @@
     /**
      * Perform OTA if current OS is not the latest one.
      *
-     * @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 statusChangedCallback Function called when OTA status changed.
      */
     public abstract void onStartOtaIfNecessary(
@@ -274,8 +347,7 @@
     /**
      * Return metadata for subscriptions which are available for download for this 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.
      * @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)}
      *     should be returned to allow the user to consent to this operation first.
@@ -295,13 +367,44 @@
      * @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}
      *     should be returned to allow the user to consent to this operation first.
+     * @param resolvedBundle The bundle containing information on resolved errors. It can contain
+     *     a string of confirmation code for the key {@link #EXTRA_RESOLUTION_CONFIRMATION_CODE},
+     *     and a boolean for key {@link #EXTRA_RESOLUTION_ALLOW_POLICY_RULES} indicating whether
+     *     the user allows profile policy rules or not.
+     * @return a DownloadSubscriptionResult instance including a result code, a resolvable errors
+     *     bit map, and original the card Id. The result code may be one of the predefined
+     *     {@code RESULT_} constants or any implementation-specific code starting with
+     *     {@link #RESULT_FIRST_USER}. The resolvable error bit map can be either 0 or values
+     *     defined in {@code RESOLVABLE_ERROR_}.
+     * @see android.telephony.euicc.EuiccManager#downloadSubscription
+     */
+    public abstract DownloadSubscriptionResult onDownloadSubscription(int slotId,
+            @NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
+            boolean forceDeactivateSim, @Nullable Bundle resolvedBundle);
+
+    /**
+     * Download the given subscription.
+     *
+     * @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.
+     * @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}
+     *     should be returned to allow the user to consent to this operation first.
      * @return the result of the download operation. May be one of the predefined {@code RESULT_}
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      * @see android.telephony.euicc.EuiccManager#downloadSubscription
+     *
+     * @deprecated From Q, please use the above
+     * {@link #onDownloadSubscription(int, DownloadableSubscription, boolean, boolean, Bundle)}.
      */
-    public abstract int onDownloadSubscription(int slotId,
-            DownloadableSubscription subscription, boolean switchAfterDownload,
-            boolean forceDeactivateSim);
+    @Deprecated public @Result int onDownloadSubscription(int slotId,
+            @NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
+            boolean forceDeactivateSim) {
+        throw new UnsupportedOperationException("onDownloadSubscription(int, "
+            + "DownloadableSubscription, boolean, boolean) is deprecated.");
+    }
 
     /**
      * Return a list of all @link EuiccProfileInfo}s.
@@ -311,7 +414,7 @@
      * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
      * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
      */
-    public abstract GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId);
+    public abstract @NonNull GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId);
 
     /**
      * Return info about the eUICC chip/device.
@@ -320,7 +423,7 @@
      * @return the {@link EuiccInfo} for the eUICC chip/device.
      * @see android.telephony.euicc.EuiccManager#getEuiccInfo
      */
-    public abstract EuiccInfo onGetEuiccInfo(int slotId);
+    public abstract @NonNull EuiccInfo onGetEuiccInfo(int slotId);
 
     /**
      * Delete the given subscription.
@@ -334,7 +437,7 @@
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      * @see android.telephony.euicc.EuiccManager#deleteSubscription
      */
-    public abstract int onDeleteSubscription(int slotId, String iccid);
+    public abstract @Result int onDeleteSubscription(int slotId, String iccid);
 
     /**
      * Switch to the given subscription.
@@ -350,7 +453,7 @@
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      * @see android.telephony.euicc.EuiccManager#switchToSubscription
      */
-    public abstract int onSwitchToSubscription(int slotId, @Nullable String iccid,
+    public abstract @Result int onSwitchToSubscription(int slotId, @Nullable String iccid,
             boolean forceDeactivateSim);
 
     /**
@@ -372,8 +475,7 @@
      * <p>This is intended to be used for device resets. As such, the reset should be performed even
      * if an active SIM must be deactivated in order to access the eUICC.
      *
-     * @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 erase operation. May be one of the predefined {@code RESULT_}
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      * @see android.telephony.euicc.EuiccManager#eraseSubscriptions
@@ -388,8 +490,7 @@
      * should persist some bit that will remain accessible after the factory reset to bypass this
      * flow when this method is called.
      *
-     * @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. May be one of the predefined {@code RESULT_} constants
      *     or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      */
@@ -401,13 +502,26 @@
     private class IEuiccServiceWrapper extends IEuiccService.Stub {
         @Override
         public void downloadSubscription(int slotId, DownloadableSubscription subscription,
-                boolean switchAfterDownload, boolean forceDeactivateSim,
+                boolean switchAfterDownload, boolean forceDeactivateSim, Bundle resolvedBundle,
                 IDownloadSubscriptionCallback callback) {
             mExecutor.execute(new Runnable() {
                 @Override
                 public void run() {
-                    int result = EuiccService.this.onDownloadSubscription(
-                            slotId, subscription, switchAfterDownload, forceDeactivateSim);
+                    DownloadSubscriptionResult result;
+                    try {
+                        result =
+                            EuiccService.this.onDownloadSubscription(
+                                slotId, subscription, switchAfterDownload, forceDeactivateSim,
+                                resolvedBundle);
+                    } catch (AbstractMethodError e) {
+                        Log.w(TAG, "The new onDownloadSubscription(int, "
+                                + "DownloadableSubscription, boolean, boolean, Bundle) is not "
+                                + "implemented. Fall back to the old one.", e);
+                        int resultCode = EuiccService.this.onDownloadSubscription(
+                                slotId, subscription, switchAfterDownload, forceDeactivateSim);
+                        result = new DownloadSubscriptionResult(resultCode,
+                            0 /* resolvableErrors */, TelephonyManager.INVALID_CARD_ID);
+                    }
                     try {
                         callback.onComplete(result);
                     } catch (RemoteException e) {
diff --git a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
index 6893c85..50ecbeb 100644
--- a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
+++ b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
@@ -16,7 +16,9 @@
 
 package android.service.euicc;
 
+import android.service.euicc.DownloadSubscriptionResult;
+
 /** @hide */
 oneway interface IDownloadSubscriptionCallback {
-    void onComplete(int result);
+    void onComplete(in DownloadSubscriptionResult result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index 45be527..c2cdf09 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -30,11 +30,12 @@
 import android.service.euicc.ISwitchToSubscriptionCallback;
 import android.service.euicc.IUpdateSubscriptionNicknameCallback;
 import android.telephony.euicc.DownloadableSubscription;
+import android.os.Bundle;
 
 /** @hide */
 oneway interface IEuiccService {
     void downloadSubscription(int slotId, in DownloadableSubscription subscription,
-            boolean switchAfterDownload, boolean forceDeactivateSim,
+            boolean switchAfterDownload, boolean forceDeactivateSim, in Bundle resolvedBundle,
             in IDownloadSubscriptionCallback callback);
     void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription,
             boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index b732d4d..219e8d2 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -335,7 +335,7 @@
         }
         try {
             getIEuiccController().downloadSubscription(subscription, switchAfterDownload,
-                    mContext.getOpPackageName(), callbackIntent);
+                    mContext.getOpPackageName(), null /* resolvedBundle */, callbackIntent);
         } 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 0a0ad90..870a689 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -32,7 +32,7 @@
     String getEid();
     int getOtaStatus();
     oneway void downloadSubscription(in DownloadableSubscription subscription,
-        boolean switchAfterDownload, String callingPackage, in PendingIntent callbackIntent);
+        boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle, in PendingIntent callbackIntent);
     EuiccInfo getEuiccInfo();
     oneway void deleteSubscription(int subscriptionId, String callingPackage,
         in PendingIntent callbackIntent);