content: /*
   * 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.telephony.euicc;
  
  import android.annotation.CallbackExecutor;
  import android.annotation.IntDef;
  import android.annotation.Nullable;
  import android.annotation.SystemApi;
  import android.content.Context;
  import android.os.RemoteException;
  import android.os.ServiceManager;
  import android.service.euicc.EuiccProfileInfo;
  import android.util.Log;
  
  import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
  import com.android.internal.telephony.euicc.ICancelSessionCallback;
  import com.android.internal.telephony.euicc.IDeleteProfileCallback;
  import com.android.internal.telephony.euicc.IDisableProfileCallback;
  import com.android.internal.telephony.euicc.IEuiccCardController;
  import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
  import com.android.internal.telephony.euicc.IGetDefaultSmdpAddressCallback;
  import com.android.internal.telephony.euicc.IGetEuiccChallengeCallback;
  import com.android.internal.telephony.euicc.IGetEuiccInfo1Callback;
  import com.android.internal.telephony.euicc.IGetEuiccInfo2Callback;
  import com.android.internal.telephony.euicc.IGetProfileCallback;
  import com.android.internal.telephony.euicc.IGetRulesAuthTableCallback;
  import com.android.internal.telephony.euicc.IGetSmdsAddressCallback;
  import com.android.internal.telephony.euicc.IListNotificationsCallback;
  import com.android.internal.telephony.euicc.ILoadBoundProfilePackageCallback;
  import com.android.internal.telephony.euicc.IPrepareDownloadCallback;
  import com.android.internal.telephony.euicc.IRemoveNotificationFromListCallback;
  import com.android.internal.telephony.euicc.IResetMemoryCallback;
  import com.android.internal.telephony.euicc.IRetrieveNotificationCallback;
  import com.android.internal.telephony.euicc.IRetrieveNotificationListCallback;
  import com.android.internal.telephony.euicc.ISetDefaultSmdpAddressCallback;
  import com.android.internal.telephony.euicc.ISetNicknameCallback;
  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
   */
  @SystemApi
  public class EuiccCardManager {
      private static final String TAG = "EuiccCardManager";
  
      /** Reason for canceling a profile download session */
      @Retention(RetentionPolicy.SOURCE)
      @IntDef(prefix = { "CANCEL_REASON_" }, value = {
              CANCEL_REASON_END_USER_REJECTED,
              CANCEL_REASON_POSTPONED,
              CANCEL_REASON_TIMEOUT,
              CANCEL_REASON_PPR_NOT_ALLOWED
      })
      /** @hide */
      public @interface CancelReason {}
  
      /**
       * The end user has rejected the download. The profile will be put into the error state and
       * cannot be downloaded again without the operator's change.
       */
      public static final int CANCEL_REASON_END_USER_REJECTED = 0;
  
      /** The download has been postponed and can be restarted later. */
      public static final int CANCEL_REASON_POSTPONED = 1;
  
      /** The download has been timed out and can be restarted later. */
      public static final int CANCEL_REASON_TIMEOUT = 2;
  
      /**
       * The profile to be downloaded cannot be installed due to its policy rule is not allowed by
       * the RAT (Rules Authorisation Table) on the eUICC or by other installed profiles. The
       * download can be restarted later.
       */
      public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3;
  
      /** Options for resetting eUICC memory */
      @Retention(RetentionPolicy.SOURCE)
      @IntDef(flag = true, prefix = { "RESET_OPTION_" }, value = {
              RESET_OPTION_DELETE_OPERATIONAL_PROFILES,
              RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES,
              RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS
      })
      /** @hide */
      public @interface ResetOption {}
  
      /** Deletes all operational profiles. */
      public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1;
  
      /** Deletes all field-loaded testing profiles. */
      public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 1 << 1;
  
      /** Resets the default SM-DP+ address. */
      public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 1 << 2;
  
      /** Result code of execution with no error. */
      public static final int RESULT_OK = 0;
  
      /** Result code of an unknown error. */
      public static final int RESULT_UNKNOWN_ERROR = -1;
  
      /** Result code when the eUICC card with the given card Id is not found. */
      public static final int RESULT_EUICC_NOT_FOUND = -2;
  
      /** Result code indicating the caller is not the active LPA. */
      public static final int RESULT_CALLER_NOT_ALLOWED = -3;
  
      /**
       * Callback to receive the result of an eUICC card API.
       *
       * @param <T> Type of the result.
       */
      public interface ResultCallback<T> {
          /**
           * This method will be called when an eUICC card API call is completed.
           *
           * @param resultCode This can be {@link #RESULT_OK} or other positive values returned by the
           *     eUICC.
           * @param result The result object. It can be null if the {@code resultCode} is not
           *     {@link #RESULT_OK}.
           */
          void onComplete(int resultCode, T result);
      }
  
      private final Context mContext;
  
      /** @hide */
      public EuiccCardManager(Context context) {
          mContext = context;
      }
  
      private IEuiccCardController getIEuiccCardController() {
          return IEuiccCardController.Stub.asInterface(
                  ServiceManager.getService("euicc_card_controller"));
      }
  
      /**
       * Requests all the profiles on eUicc.
       *
       * @param cardId The Id of the eUICC.
       * @param executor The executor through which the callback should be invoked.
       * @param callback The callback to get the result code and all the profiles.
       */
      public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<EuiccProfileInfo[]> callback) {
          try {
              getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(), cardId,
                      new IGetAllProfilesCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
                              executor.execute(() -> callback.onComplete(resultCode, profiles));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getAllProfiles", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * 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 invoked.
       * @param callback The callback to get the result code and profile.
       */
      public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
              ResultCallback<EuiccProfileInfo> callback) {
          try {
              getIEuiccCardController().getProfile(mContext.getOpPackageName(), cardId, iccid,
                      new IGetProfileCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccProfileInfo profile) {
                              executor.execute(() -> callback.onComplete(resultCode, profile));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getProfile", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Disables the profile of the given iccid.
       *
       * @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 invoked.
       * @param callback The callback to get the result code.
       */
      public void disableProfile(String cardId, String iccid, boolean refresh,
              @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
          try {
              getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
                      refresh, new IDisableProfileCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode) {
                              executor.execute(() -> callback.onComplete(resultCode, null));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling disableProfile", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Switches from the current profile to another profile. The current profile will be disabled
       * and the specified profile will be enabled.
       *
       * @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 invoked.
       * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
       */
      public void switchToProfile(String cardId, String iccid, boolean refresh,
              @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) {
          try {
              getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
                      refresh, new ISwitchToProfileCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccProfileInfo profile) {
                              executor.execute(() -> callback.onComplete(resultCode, profile));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling switchToProfile", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Sets the nickname of the profile of the given iccid.
       *
       * @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 invoked.
       * @param callback The callback to get the result code.
       */
      public void setNickname(String cardId, String iccid, String nickname,
              @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
          try {
              getIEuiccCardController().setNickname(mContext.getOpPackageName(), cardId, iccid,
                      nickname, new ISetNicknameCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode) {
                              executor.execute(() -> callback.onComplete(resultCode, null));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling setNickname", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Deletes the profile of the given iccid from eUICC.
       *
       * @param cardId The Id of the eUICC.
       * @param iccid The iccid of the profile.
       * @param executor The executor through which the callback should be invoked.
       * @param callback The callback to get the result code.
       */
      public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
              ResultCallback<Void> callback) {
          try {
              getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), cardId, iccid,
                      new IDeleteProfileCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode) {
                              executor.execute(() -> callback.onComplete(resultCode, null));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling deleteProfile", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Resets the eUICC memory.
       *
       * @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 invoked.
       * @param callback The callback to get the result code.
       */
      public void resetMemory(String cardId, @ResetOption int options,
              @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
          try {
              getIEuiccCardController().resetMemory(mContext.getOpPackageName(), cardId, options,
                      new IResetMemoryCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode) {
                              executor.execute(() -> callback.onComplete(resultCode, null));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling resetMemory", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * 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 invoked.
       * @param callback The callback to get the result code and the default SM-DP+ address.
       */
      public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<String> callback) {
          try {
              getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
                      new IGetDefaultSmdpAddressCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, String address) {
                              executor.execute(() -> callback.onComplete(resultCode, address));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getDefaultSmdpAddress", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Requests the SM-DS address from eUICC.
       *
       * @param cardId The Id of the eUICC.
       * @param executor The executor through which the callback should be invoked.
       * @param callback The callback to get the result code and the SM-DS address.
       */
      public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<String> callback) {
          try {
              getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(), cardId,
                      new IGetSmdsAddressCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, String address) {
                              executor.execute(() -> callback.onComplete(resultCode, address));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getSmdsAddress", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Sets the default SM-DP+ address of eUICC.
       *
       * @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 invoked.
       * @param callback The callback to get the result code.
       */
      public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
              @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
          try {
              getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
                      defaultSmdpAddress,
                      new ISetDefaultSmdpAddressCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode) {
                              executor.execute(() -> callback.onComplete(resultCode, null));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling setDefaultSmdpAddress", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Requests Rules Authorisation Table.
       *
       * @param cardId The Id of the eUICC.
       * @param executor The executor through which the callback should be invoked.
       * @param callback the callback to get the result code and the rule authorisation table.
       */
      public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<EuiccRulesAuthTable> callback) {
          try {
              getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(), cardId,
                      new IGetRulesAuthTableCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccRulesAuthTable rat) {
                              executor.execute(() -> callback.onComplete(resultCode, rat));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getRulesAuthTable", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * 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 invoked.
       * @param callback the callback to get the result code and the challenge.
       */
      public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(), cardId,
                      new IGetEuiccChallengeCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] challenge) {
                              executor.execute(() -> callback.onComplete(resultCode, challenge));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getEuiccChallenge", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * 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 invoked.
       * @param callback the callback to get the result code and the info1.
       */
      public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(), cardId,
                      new IGetEuiccInfo1Callback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] info) {
                              executor.execute(() -> callback.onComplete(resultCode, info));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getEuiccInfo1", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * 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 invoked.
       * @param callback the callback to get the result code and the info2.
       */
      public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
              ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(), cardId,
                      new IGetEuiccInfo2Callback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] info) {
                              executor.execute(() -> callback.onComplete(resultCode, info));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling getEuiccInfo2", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Authenticates the SM-DP+ server by the eUICC.
       *
       * @param cardId The Id of the eUICC.
       * @param matchingId the activation code token defined in GSMA RSP v2.0+ or empty when it is not
       *     required.
       * @param serverSigned1 ASN.1 data in byte array signed and returned by the SM-DP+ server.
       * @param serverSignature1 ASN.1 data in byte array indicating a SM-DP+ signature which is
       *     returned by SM-DP+ server.
       * @param euiccCiPkIdToBeUsed ASN.1 data in byte array indicating CI Public Key Identifier to be
       *     used by the eUICC for signature which is returned by SM-DP+ server. This is defined in
       *     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 invoked.
       * @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,
              @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().authenticateServer(
                      mContext.getOpPackageName(),
                      cardId,
                      matchingId,
                      serverSigned1,
                      serverSignature1,
                      euiccCiPkIdToBeUsed,
                      serverCertificate,
                      new IAuthenticateServerCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] response) {
                              executor.execute(() -> callback.onComplete(resultCode, response));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling authenticateServer", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Prepares the profile download request sent to SM-DP+.
       *
       * @param cardId The Id of the eUICC.
       * @param hashCc the hash of confirmation code. It can be null if there is no confirmation code
       *     required.
       * @param smdpSigned2 ASN.1 data in byte array indicating the data to be signed by the SM-DP+
       *     returned by SM-DP+ server.
       * @param smdpSignature2 ASN.1 data in byte array indicating the SM-DP+ signature returned by
       *     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 invoked.
       * @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, @CallbackExecutor Executor executor,
              ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().prepareDownload(
                      mContext.getOpPackageName(),
                      cardId,
                      hashCc,
                      smdpSigned2,
                      smdpSignature2,
                      smdpCertificate,
                      new IPrepareDownloadCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] response) {
                              executor.execute(() -> callback.onComplete(resultCode, response));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling prepareDownload", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Loads a downloaded bound profile package onto the eUICC.
       *
       * @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 invoked.
       * @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,
              @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().loadBoundProfilePackage(
                      mContext.getOpPackageName(),
                      cardId,
                      boundProfilePackage,
                      new ILoadBoundProfilePackageCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] response) {
                              executor.execute(() -> callback.onComplete(resultCode, response));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling loadBoundProfilePackage", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Cancels the current profile download session.
       *
       * @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 invoked.
       * @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,
              @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
          try {
              getIEuiccCardController().cancelSession(
                      mContext.getOpPackageName(),
                      cardId,
                      transactionId,
                      reason,
                      new ICancelSessionCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, byte[] response) {
                              executor.execute(() -> callback.onComplete(resultCode, response));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling cancelSession", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Lists all notifications of the given {@code events}.
       *
       * @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 invoked.
       * @param callback the callback to get the result code and the list of notifications.
       */
      public void listNotifications(String cardId, @EuiccNotification.Event int events,
              @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback) {
          try {
              getIEuiccCardController().listNotifications(mContext.getOpPackageName(), cardId, events,
                      new IListNotificationsCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccNotification[] notifications) {
                              executor.execute(() -> callback.onComplete(resultCode, notifications));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling listNotifications", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Retrieves contents of all notification of the given {@code events}.
       *
       * @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 invoked.
       * @param callback the callback to get the result code and the list of notifications.
       */
      public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
              @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback) {
          try {
              getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), cardId,
                      events, new IRetrieveNotificationListCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccNotification[] notifications) {
                              executor.execute(() -> callback.onComplete(resultCode, notifications));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling retrieveNotificationList", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Retrieves the content of a notification of the given {@code seqNumber}.
       *
       * @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 invoked.
       * @param callback the callback to get the result code and the notification.
       */
      public void retrieveNotification(String cardId, int seqNumber,
              @CallbackExecutor Executor executor, ResultCallback<EuiccNotification> callback) {
          try {
              getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), cardId,
                      seqNumber, new IRetrieveNotificationCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode, EuiccNotification notification) {
                              executor.execute(() -> callback.onComplete(resultCode, notification));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling retrieveNotification", e);
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Removes a notification from eUICC.
       *
       * @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 invoked.
       * @param callback the callback to get the result code.
       */
      public void removeNotificationFromList(String cardId, int seqNumber,
              @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
          try {
              getIEuiccCardController().removeNotificationFromList(
                      mContext.getOpPackageName(),
                      cardId,
                      seqNumber,
                      new IRemoveNotificationFromListCallback.Stub() {
                          @Override
                          public void onComplete(int resultCode) {
                              executor.execute(() -> callback.onComplete(resultCode, null));
                          }
                      });
          } catch (RemoteException e) {
              Log.e(TAG, "Error calling removeNotificationFromList", e);
              throw e.rethrowFromSystemServer();
          }
      }
  }
  