Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00729997 authored by Qingxi Li's avatar Qingxi Li Committed by android-build-merger
Browse files

Merge "Add API to get eUICC's OTA status"

am: e01e32e1

Change-Id: I3ca7a5741cfb7241b92fa7369d6320f99bafd7e8
parents 8bc89a1f e01e32e1
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -46,12 +46,14 @@ import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback;
import android.service.euicc.IGetEidCallback;
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
import android.service.euicc.IGetOtaStatusCallback;
import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
import android.telephony.SubscriptionManager;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager.OtaStatus;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -132,6 +134,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
    private static final int CMD_UPDATE_SUBSCRIPTION_NICKNAME = 108;
    private static final int CMD_ERASE_SUBSCRIPTIONS = 109;
    private static final int CMD_RETAIN_SUBSCRIPTIONS = 110;
    private static final int CMD_GET_OTA_STATUS = 111;

    private static boolean isEuiccCommand(int what) {
        return what >= CMD_GET_EID;
@@ -185,6 +188,13 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        void onGetEidComplete(String eid);
    }

    /** Callback class for {@link #getOtaStatus}. */
    @VisibleForTesting(visibility = PACKAGE)
    public interface GetOtaStatusCommandCallback extends BaseEuiccCommandCallback {
        /** Called when the getting OTA status lookup has completed. */
        void onGetOtaStatusComplete(@OtaStatus int status);
    }

    static class GetMetadataRequest {
        DownloadableSubscription mSubscription;
        boolean mForceDeactivateSim;
@@ -373,6 +383,12 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        sendMessage(CMD_GET_EID, callback);
    }

    /** Asynchronously get OTA status. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getOtaStatus(GetOtaStatusCommandCallback callback) {
        sendMessage(CMD_GET_OTA_STATUS, callback);
    }

    /** Asynchronously fetch metadata for the given downloadable subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription,
@@ -809,6 +825,20 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
                                    });
                            break;
                        }
                        case CMD_GET_OTA_STATUS: {
                            mEuiccService.getOtaStatus(slotId,
                                    new IGetOtaStatusCallback.Stub() {
                                        @Override
                                        public void onSuccess(@OtaStatus int status) {
                                            sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
                                                ((GetOtaStatusCommandCallback) callback)
                                                        .onGetOtaStatusComplete(status);
                                                onCommandEnd(callback);
                                            });
                                        }
                                    });
                            break;
                        }
                        default: {
                            Log.wtf(TAG, "Unimplemented eUICC command: " + message.what);
                            callback.onEuiccServiceUnavailable();
@@ -851,6 +881,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
            case CMD_GET_EUICC_INFO:
            case CMD_ERASE_SUBSCRIPTIONS:
            case CMD_RETAIN_SUBSCRIPTIONS:
            case CMD_GET_OTA_STATUS:
                return (BaseEuiccCommandCallback) message.obj;
            case CMD_GET_DOWNLOADABLE_SUBSCRIPTION_METADATA:
                return ((GetMetadataRequest) message.obj).mCallback;
+41 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.internal.telephony.euicc;

import static android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE;

import android.Manifest;
import android.annotation.Nullable;
import android.app.AppOpsManager;
@@ -38,6 +40,7 @@ import android.telephony.UiccAccessRule;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager;
import android.telephony.euicc.EuiccManager.OtaStatus;
import android.text.TextUtils;
import android.util.Log;

@@ -169,6 +172,25 @@ public class EuiccController extends IEuiccController.Stub {
        }
    }

    /**
     * Return the current status of OTA update.
     *
     * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load,
     * that IPC should generally be fast.
     */
    @Override
    public @OtaStatus int getOtaStatus() {
        if (!callerCanWriteEmbeddedSubscriptions()) {
            throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get OTA status");
        }
        long token = Binder.clearCallingIdentity();
        try {
            return blockingGetOtaStatusFromEuiccService();
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription,
            String callingPackage, PendingIntent callbackIntent) {
@@ -953,6 +975,25 @@ public class EuiccController extends IEuiccController.Stub {
        return awaitResult(latch, eidRef);
    }

    private @OtaStatus int blockingGetOtaStatusFromEuiccService() {
        CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<Integer> statusRef =
                new AtomicReference<>(EUICC_OTA_STATUS_UNAVAILABLE);
        mConnector.getOtaStatus(new EuiccConnector.GetOtaStatusCommandCallback() {
            @Override
            public void onGetOtaStatusComplete(@OtaStatus int status) {
                statusRef.set(status);
                latch.countDown();
            }

            @Override
            public void onEuiccServiceUnavailable() {
                latch.countDown();
            }
        });
        return awaitResult(latch, statusRef);
    }

    @Nullable
    private EuiccInfo blockingGetEuiccInfoFromEuiccService() {
        CountDownLatch latch = new CountDownLatch(1);
+39 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.internal.telephony.euicc;

import static android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -56,6 +58,7 @@ import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager;

import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;

import org.junit.After;
import org.junit.Before;
@@ -203,6 +206,26 @@ public class EuiccControllerTest extends TelephonyTest {
        assertNull(callGetEid(true /* success */, null /* eid */));
    }

    @Test(expected = SecurityException.class)
    public void testGetOtaStatus_noPrivileges() {
        setHasWriteEmbeddedPermission(false /* hasPermission */);
        callGetOtaStatus(true /* success */, 1 /* status */);
    }

    @Test
    public void testGetOtaStatus_withWriteEmbeddedPermission() {
        setHasWriteEmbeddedPermission(true /* hasPermission */);
        assertEquals(1, callGetOtaStatus(true /* success */, 1 /* status */));
    }

    @Test
    public void testGetOtaStatus_failure() {
        setHasWriteEmbeddedPermission(true /* hasPermission */);
        assertEquals(
                EUICC_OTA_STATUS_UNAVAILABLE,
                callGetOtaStatus(false /* success */, 1 /* status */));
    }

    @Test
    public void testGetEuiccInfo_success() {
        assertEquals(OS_VERSION, callGetEuiccInfo(true /* success */, EUICC_INFO).osVersion);
@@ -806,6 +829,22 @@ public class EuiccControllerTest extends TelephonyTest {
        return mController.getEid();
    }

    private int callGetOtaStatus(final boolean success, final int status) {
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Exception {
                GetOtaStatusCommandCallback cb = invocation.getArgument(0);
                if (success) {
                    cb.onGetOtaStatusComplete(status);
                } else {
                    cb.onEuiccServiceUnavailable();
                }
                return null;
            }
        }).when(mMockConnector).getOtaStatus(Mockito.<GetOtaStatusCommandCallback>any());
        return mController.getOtaStatus();
    }

    private EuiccInfo callGetEuiccInfo(final boolean success, final @Nullable EuiccInfo euiccInfo) {
        doAnswer(new Answer<Void>() {
            @Override