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

Commit 8a86293b authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add API EuiccController#startOtaUpdatingIfNecessary"

parents 60d720f2 0a2c99b1
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.content.pm.ServiceInfo;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.service.euicc.EuiccService;
import android.service.euicc.GetDefaultDownloadableSubscriptionListResult;
import android.service.euicc.GetDownloadableSubscriptionMetadataResult;
@@ -47,12 +48,14 @@ import android.service.euicc.IGetEidCallback;
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
import android.service.euicc.IGetOtaStatusCallback;
import android.service.euicc.IOtaStatusChangedCallback;
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;
import android.telephony.euicc.EuiccManager.OtaStatus;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -135,6 +138,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
    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 final int CMD_START_OTA_IF_NECESSARY = 112;

    private static boolean isEuiccCommand(int what) {
        return what >= CMD_GET_EID;
@@ -195,6 +199,14 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        void onGetOtaStatusComplete(@OtaStatus int status);
    }

    /** Callback class for {@link #startOtaIfNecessary}. */
    @VisibleForTesting(visibility = PACKAGE)
    public interface OtaStatusChangedCallback extends BaseEuiccCommandCallback {
        /**
         * Called when OTA status is changed to {@link EuiccM}. */
        void onOtaStatusChanged(int status);
    }

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

    /** Asynchronously perform OTA update. */
    @VisibleForTesting(visibility = PACKAGE)
    public void startOtaIfNecessary(OtaStatusChangedCallback callback) {
        sendMessage(CMD_START_OTA_IF_NECESSARY, callback);
    }

    /** Asynchronously fetch metadata for the given downloadable subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription,
@@ -839,6 +857,28 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
                                    });
                            break;
                        }
                        case CMD_START_OTA_IF_NECESSARY: {
                            mEuiccService.startOtaIfNecessary(slotId,
                                    new IOtaStatusChangedCallback.Stub() {
                                        @Override
                                        public void onOtaStatusChanged(int status)
                                                throws RemoteException {
                                            if (status == EuiccManager.EUICC_OTA_IN_PROGRESS) {
                                                sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
                                                    ((OtaStatusChangedCallback) callback)
                                                            .onOtaStatusChanged(status);
                                                });
                                            } else {
                                                sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
                                                    ((OtaStatusChangedCallback) callback)
                                                            .onOtaStatusChanged(status);
                                                    onCommandEnd(callback);
                                                });
                                            }
                                        }
                                    });
                            break;
                        }
                        default: {
                            Log.wtf(TAG, "Unimplemented eUICC command: " + message.what);
                            callback.onEuiccServiceUnavailable();
@@ -882,6 +922,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
            case CMD_ERASE_SUBSCRIPTIONS:
            case CMD_RETAIN_SUBSCRIPTIONS:
            case CMD_GET_OTA_STATUS:
            case CMD_START_OTA_IF_NECESSARY:
                return (BaseEuiccCommandCallback) message.obj;
            case CMD_GET_DOWNLOADABLE_SUBSCRIPTION_METADATA:
                return ((GetMetadataRequest) message.obj).mCallback;
+32 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.telephony.euicc;
import static android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE;

import android.Manifest;
import android.Manifest.permission;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -46,6 +47,7 @@ import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -191,6 +193,26 @@ public class EuiccController extends IEuiccController.Stub {
        }
    }


    /**
     * Start eUICC OTA update if current eUICC OS is not the latest one. When OTA is started or
     * finished, the broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} will be sent.
     *
     * This function will only be called from phone process and isn't exposed to the other apps.
     */
    public void startOtaUpdatingIfNecessary() {
        mConnector.startOtaIfNecessary(
                new OtaStatusChangedCallback() {
                    @Override
                    public void onOtaStatusChanged(int status) {
                        sendOtaStatusChangedBroadcast();
                    }

                    @Override
                    public void onEuiccServiceUnavailable() {}
                });
    }

    @Override
    public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription,
            String callingPackage, PendingIntent callbackIntent) {
@@ -943,6 +965,16 @@ public class EuiccController extends IEuiccController.Stub {
        }
    }

    /**
     * Send broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} for OTA status
     * changed.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    public void sendOtaStatusChangedBroadcast() {
        Intent intent = new Intent(EuiccManager.ACTION_OTA_STATUS_CHANGED);
        mContext.sendBroadcast(intent, permission.WRITE_EMBEDDED_SUBSCRIPTIONS);
    }

    @Nullable
    private SubscriptionInfo getSubscriptionForSubscriptionId(int subscriptionId) {
        List<SubscriptionInfo> subs = mSubscriptionManager.getAvailableSubscriptionInfoList();
+54 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.telephony.euicc.EuiccManager;

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

import org.junit.After;
import org.junit.Before;
@@ -125,8 +126,12 @@ public class EuiccControllerTest extends TelephonyTest {
        // Whether refreshSubscriptionsAndSendResult was called.
        private boolean mCalledRefreshSubscriptionsAndSendResult;

        // Number of OTA status changed.
        private int mNumOtaStatusChanged;

        TestEuiccController(Context context, EuiccConnector connector) {
            super(context, connector);
            mNumOtaStatusChanged = 0;
        }

        @Override
@@ -151,6 +156,11 @@ public class EuiccControllerTest extends TelephonyTest {
            mCalledRefreshSubscriptionsAndSendResult = true;
            sendResult(callbackIntent, resultCode, extrasIntent);
        }

        @Override
        public void sendOtaStatusChangedBroadcast() {
            ++mNumOtaStatusChanged;
        }
    }

    @Before
@@ -226,6 +236,32 @@ public class EuiccControllerTest extends TelephonyTest {
                callGetOtaStatus(false /* success */, 1 /* status */));
    }

    @Test
    public void testStartOtaUpdatingIfNecessary_serviceNotAvailable() {
        setHasWriteEmbeddedPermission(true /* hasPermission */);
        callStartOtaUpdatingIfNecessary(
                false /* serviceAvailable */, EuiccManager.EUICC_OTA_IN_PROGRESS);
        assertEquals(mController.mNumOtaStatusChanged, 0);
    }

    @Test
    public void testStartOtaUpdatingIfNecessary_otaStatusChanged() {
        setHasWriteEmbeddedPermission(true /* hasPermission */);
        callStartOtaUpdatingIfNecessary(
                true /* serviceAvailable */, EuiccManager.EUICC_OTA_IN_PROGRESS);
        callStartOtaUpdatingIfNecessary(
                true /* serviceAvailable */, EuiccManager.EUICC_OTA_FAILED);
        callStartOtaUpdatingIfNecessary(
                true /* serviceAvailable */, EuiccManager.EUICC_OTA_SUCCEEDED);
        callStartOtaUpdatingIfNecessary(
                true /* serviceAvailable */, EuiccManager.EUICC_OTA_NOT_NEEDED);
        callStartOtaUpdatingIfNecessary(
                true /* serviceAvailable */, EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE);

        assertEquals(mController.mNumOtaStatusChanged, 5);
    }


    @Test
    public void testGetEuiccInfo_success() {
        assertEquals(OS_VERSION, callGetEuiccInfo(true /* success */, EUICC_INFO).osVersion);
@@ -845,6 +881,24 @@ public class EuiccControllerTest extends TelephonyTest {
        return mController.getOtaStatus();
    }

    private void callStartOtaUpdatingIfNecessary(
            final boolean serviceAvailable, int status) {
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Exception {
                OtaStatusChangedCallback cb = invocation.getArgument(0);
                if (!serviceAvailable) {
                    cb.onEuiccServiceUnavailable();
                } else {
                    cb.onOtaStatusChanged(status);
                }
                return null;
            }
        }).when(mMockConnector).startOtaIfNecessary(Mockito.<OtaStatusChangedCallback>any());

        mController.startOtaUpdatingIfNecessary();
    }

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