Merge "Add portIndex for switch subscription API" am: d9e8a4f5ff am: effba65e40

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2037585

Change-Id: I28b2a088ec14a8f734b5fafcddd110c09185408a
This commit is contained in:
Chen Xu
2022-03-23 23:35:35 +00:00
committed by Automerger Merge Worker
7 changed files with 168 additions and 10 deletions

View File

@@ -42283,7 +42283,8 @@ package android.telephony.euicc {
method public boolean isEnabled();
method public boolean isSimPortAvailable(int);
method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
method @Deprecated @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccManager.ResultListener);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);
field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
field public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
@@ -42329,6 +42330,10 @@ package android.telephony.euicc {
field public static final int OPERATION_SYSTEM = 1; // 0x1
}
public static interface EuiccManager.ResultListener {
method public void onComplete(int, @Nullable android.content.Intent);
}
}
package android.telephony.gsm {

View File

@@ -9641,7 +9641,8 @@ package android.service.euicc {
method @android.telephony.euicc.EuiccManager.OtaStatus public abstract int onGetOtaStatus(int);
method public abstract int onRetainSubscriptionsForFactoryReset(int);
method public abstract void onStartOtaIfNecessary(int, android.service.euicc.EuiccService.OtaStatusChangedCallback);
method public abstract int onSwitchToSubscription(int, @Nullable String, boolean);
method @Deprecated public abstract int onSwitchToSubscription(int, @Nullable String, boolean);
method public int onSwitchToSubscriptionWithPort(int, int, @Nullable String, boolean);
method public abstract int onUpdateSubscriptionNickname(int, String, String);
field public static final String ACTION_BIND_CARRIER_PROVISIONING_SERVICE = "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE";
field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
@@ -9663,6 +9664,7 @@ package android.service.euicc {
field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
field public static final String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT";
field public static final String EXTRA_RESOLUTION_PORT_INDEX = "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
field public static final 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

View File

@@ -255,6 +255,12 @@ public abstract class EuiccService extends Service {
public static final String EXTRA_RESOLUTION_CARD_ID =
"android.service.euicc.extra.RESOLUTION_CARD_ID";
/**
* Intent extra set for resolution requests containing an int indicating the current port index.
*/
public static final String EXTRA_RESOLUTION_PORT_INDEX =
"android.service.euicc.extra.RESOLUTION_PORT_INDEX";
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "RESULT_" }, value = {
@@ -579,9 +585,32 @@ public abstract class EuiccService extends Service {
* @return the result of the switch 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#switchToSubscription
*
* @deprecated prefer {@link #onSwitchToSubscriptionWithPort(int, int, String, boolean)}
*/
public abstract @Result int onSwitchToSubscription(int slotId, @Nullable String iccid,
boolean forceDeactivateSim);
@Deprecated public abstract @Result int onSwitchToSubscription(int slotId,
@Nullable String iccid, boolean forceDeactivateSim);
/**
* Switch to the given subscription.
*
* @param slotId ID of the SIM slot to use for the operation.
* @param portIndex which port on the eUICC to use
* @param iccid the ICCID of the subscription to enable. May be null, in which case the current
* profile should be deactivated and no profile should be activated to replace it - this is
* equivalent to a physical SIM being ejected.
* @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 switch 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#switchToSubscription
*/
public @Result int onSwitchToSubscriptionWithPort(int slotId, int portIndex,
@Nullable String iccid, boolean forceDeactivateSim) {
// stub implementation, LPA needs to implement this
throw new UnsupportedOperationException("LPA must override onSwitchToSubscriptionWithPort");
}
/**
* Update the nickname of the given subscription.
@@ -821,16 +850,15 @@ public abstract class EuiccService extends Service {
}
});
}
@Override
public void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
ISwitchToSubscriptionCallback callback) {
public void switchToSubscription(int slotId, int portIndex, String iccid,
boolean forceDeactivateSim, ISwitchToSubscriptionCallback callback) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
int result =
EuiccService.this.onSwitchToSubscription(
slotId, iccid, forceDeactivateSim);
EuiccService.this.onSwitchToSubscriptionWithPort(
slotId, portIndex, iccid, forceDeactivateSim);
try {
callback.onComplete(result);
} catch (RemoteException e) {

View File

@@ -48,7 +48,7 @@ oneway interface IEuiccService {
in IGetDefaultDownloadableSubscriptionListCallback callback);
void getEuiccInfo(int slotId, in IGetEuiccInfoCallback callback);
void deleteSubscription(int slotId, String iccid, in IDeleteSubscriptionCallback callback);
void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
void switchToSubscription(int slotId, int portIndex, String iccid, boolean forceDeactivateSim,
in ISwitchToSubscriptionCallback callback);
void updateSubscriptionNickname(int slotId, String iccid, String nickname,
in IUpdateSubscriptionNicknameCallback callback);

View File

@@ -16,6 +16,7 @@
package android.telephony.euicc;
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -28,6 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyFrameworkInitializer;
@@ -35,11 +37,13 @@ import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccCardManager.ResetOption;
import com.android.internal.telephony.euicc.IEuiccController;
import com.android.internal.telephony.euicc.IResultCallback;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/**
@@ -214,6 +218,20 @@ public class EuiccManager {
public static final String ACTION_START_EUICC_ACTIVATION =
"android.telephony.euicc.action.START_EUICC_ACTIVATION";
/**
* Result codes passed to the ResultListener by
* {@link #switchToSubscription(int, int, Executor, ResultListener)}
*
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"EMBEDDED_SUBSCRIPTION_RESULT_"}, value = {
EMBEDDED_SUBSCRIPTION_RESULT_OK,
EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
})
public @interface ResultCode{}
/**
* Result code for an operation indicating that the operation succeeded.
*/
@@ -1125,7 +1143,12 @@ public class EuiccManager {
* permission, or the calling app must be authorized to manage the active subscription on
* the target eUICC.
* @param callbackIntent a PendingIntent to launch when the operation completes.
*
* @deprecated From T, callers should use
* {@link #switchToSubscription(int, int, Executor, ResultListener)} instead to specify a port
* index on the card to switch to.
*/
@Deprecated
@RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
if (!isEnabled()) {
@@ -1140,6 +1163,71 @@ public class EuiccManager {
}
}
/**
* Switch to (enable) the given subscription.
*
* <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
* or the calling app must be authorized to manage both the currently-active subscription and
* the subscription to be enabled according to the subscription metadata. Without the former,
* an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
* intent to prompt the user to accept the download.
*
* <p>On a multi-active SIM device, requires the
* {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
* only if the targeted eUICC does not currently have an active subscription or the calling app
* is authorized to manage the active subscription on the target eUICC, and the calling app is
* authorized to manage any active subscription on any SIM. Without it, an
* {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
* intent to prompt the user to accept the download. The caller should also be authorized to
* manage the subscription to be enabled.
*
* @param subscriptionId the ID of the subscription to enable. May be
* {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
* current profile without activating another profile to replace it. If it's a disable
* operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
* permission, or the calling app must be authorized to manage the active subscription on
* the target eUICC.
* @param portIndex the index of the port to target for the enabled subscription
* @param executor an Executor on which to run the callback
* @param callback a {@link ResultListener} which will run when the operation completes
*/
@RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void switchToSubscription(int subscriptionId, int portIndex,
@NonNull @CallbackExecutor Executor executor,
@NonNull ResultListener callback) {
if (!isEnabled()) {
sendUnavailableErrorToCallback(executor, callback);
return;
}
try {
IResultCallback internalCallback = new IResultCallback.Stub() {
@Override
public void onComplete(int result, Intent resultIntent) {
executor.execute(() -> Binder.withCleanCallingIdentity(
() -> callback.onComplete(result, resultIntent)));
}
};
getIEuiccController().switchToSubscriptionWithPort(mCardId, portIndex,
subscriptionId, mContext.getOpPackageName(), internalCallback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Callback to receive the result of an EuiccManager API.
*/
public interface ResultListener {
/**
* Called on completion of some operation.
* @param resultCode representing success or specific failure of the operation
* (See {@link ResultCode})
* @param resultIntent an intent used to start a resolution activity when an error
* occurs that can be resolved by the user
*/
void onComplete(@ResultCode int resultCode, @Nullable Intent resultIntent);
}
/**
* Update the nickname for the given subscription.
*
@@ -1411,6 +1499,13 @@ public class EuiccManager {
}
}
private static void sendUnavailableErrorToCallback(@NonNull Executor executor,
ResultListener callback) {
Integer result = EMBEDDED_SUBSCRIPTION_RESULT_ERROR;
executor.execute(() ->
Binder.withCleanCallingIdentity(() -> callback.onComplete(result, null)));
}
private static IEuiccController getIEuiccController() {
return IEuiccController.Stub.asInterface(
TelephonyFrameworkInitializer

View File

@@ -21,6 +21,9 @@ import android.content.Intent;
import android.os.Bundle;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import com.android.internal.telephony.euicc.IResultCallback;
import java.util.List;
/** @hide */
@@ -42,6 +45,8 @@ interface IEuiccController {
in PendingIntent callbackIntent);
oneway void switchToSubscription(int cardId, int subscriptionId, String callingPackage,
in PendingIntent callbackIntent);
oneway void switchToSubscriptionWithPort(int cardId, int portIndex, int subscriptionId,
String callingPackage, in IResultCallback callback);
oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
String callingPackage, in PendingIntent callbackIntent);
oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony.euicc;
import android.content.Intent;
/** @hide */
oneway interface IResultCallback {
void onComplete(int resultCode, in Intent resultIntent);
}