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

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

Merge "Start OTA in EuiccCardController" am: b78cce7b

am: 187aa2d0

Change-Id: I0ff352334528e332f7481f3a53d5204280ae5bbd
parents 8094d507 187aa2d0
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -140,12 +140,6 @@ public class PhoneFactory {
                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
                Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
                Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);


                if (context.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_TELEPHONY_EUICC)) {
                    sEuiccController = EuiccController.init(context);
                    sEuiccCardController = EuiccCardController.init(context);
                }

                /* In case of multi SIM mode two instances of Phone, RIL are created,
                /* In case of multi SIM mode two instances of Phone, RIL are created,
                   where as in single SIM mode only instance. isMultiSimEnabled() function checks
                   where as in single SIM mode only instance. isMultiSimEnabled() function checks
                   whether it is single SIM or multi SIM mode */
                   whether it is single SIM or multi SIM mode */
@@ -184,6 +178,12 @@ public class PhoneFactory {
                // call getInstance()
                // call getInstance()
                sUiccController = UiccController.make(context, sCommandsInterfaces);
                sUiccController = UiccController.make(context, sCommandsInterfaces);


                if (context.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_TELEPHONY_EUICC)) {
                    sEuiccController = EuiccController.init(context);
                    sEuiccCardController = EuiccCardController.init(context);
                }

                for (int i = 0; i < numPhones; i++) {
                for (int i = 0; i < numPhones; i++) {
                    Phone phone = null;
                    Phone phone = null;
                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
+76 −3
Original line number Original line Diff line number Diff line
@@ -18,19 +18,27 @@ package com.android.internal.telephony.euicc;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ComponentInfo;
import android.content.pm.ComponentInfo;
import android.os.Binder;
import android.os.Binder;
import android.os.Handler;
import android.os.Handler;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.service.euicc.EuiccProfileInfo;
import android.service.euicc.EuiccProfileInfo;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccNotification;
import android.telephony.euicc.EuiccNotification;
import android.telephony.euicc.EuiccRulesAuthTable;
import android.telephony.euicc.EuiccRulesAuthTable;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccSlot;
import com.android.internal.telephony.uicc.UiccSlot;
import com.android.internal.telephony.uicc.euicc.EuiccCard;
import com.android.internal.telephony.uicc.euicc.EuiccCard;
@@ -43,16 +51,31 @@ import java.io.PrintWriter;
/** Backing implementation of {@link EuiccCardManager}. */
/** Backing implementation of {@link EuiccCardManager}. */
public class EuiccCardController extends IEuiccCardController.Stub {
public class EuiccCardController extends IEuiccCardController.Stub {
    private static final String TAG = "EuiccCardController";
    private static final String TAG = "EuiccCardController";
    private static final String KEY_LAST_BOOT_COUNT = "last_boot_count";


    private final Context mContext;
    private final Context mContext;
    private AppOpsManager mAppOps;
    private AppOpsManager mAppOps;
    private String mCallingPackage;
    private String mCallingPackage;
    private ComponentInfo mBestComponent;
    private ComponentInfo mBestComponent;

    private Handler mEuiccMainThreadHandler;
    private Handler mEuiccMainThreadHandler;
    private SimSlotStatusChangedBroadcastReceiver mSimSlotStatusChangeReceiver;
    private EuiccController mEuiccController;
    private UiccController mUiccController;


    private static EuiccCardController sInstance;
    private static EuiccCardController sInstance;


    private class SimSlotStatusChangedBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED.equals(intent.getAction())) {
                if (isEmbeddedSlotActivated()) {
                    mEuiccController.startOtaUpdatingIfNecessary();
                }
                mContext.unregisterReceiver(mSimSlotStatusChangeReceiver);
            }
        }
    }

    /** Initialize the instance. Should only be called once. */
    /** Initialize the instance. Should only be called once. */
    public static EuiccCardController init(Context context) {
    public static EuiccCardController init(Context context) {
        synchronized (EuiccCardController.class) {
        synchronized (EuiccCardController.class) {
@@ -78,12 +101,62 @@ public class EuiccCardController extends IEuiccCardController.Stub {
    }
    }


    private EuiccCardController(Context context) {
    private EuiccCardController(Context context) {
        this(context, new Handler(), EuiccController.get(), UiccController.getInstance());
        ServiceManager.addService("euicc_card_controller", this);
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    public EuiccCardController(
            Context context,
            Handler handler,
            EuiccController euiccController,
            UiccController uiccController) {
        mContext = context;
        mContext = context;
        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);


        mEuiccMainThreadHandler = new Handler();
        mEuiccMainThreadHandler = handler;
        mUiccController = uiccController;
        mEuiccController = euiccController;


        ServiceManager.addService("euicc_card_controller", this);
        if (isBootUp(mContext)) {
            mSimSlotStatusChangeReceiver = new SimSlotStatusChangedBroadcastReceiver();
            mContext.registerReceiver(
                    mSimSlotStatusChangeReceiver,
                    new IntentFilter(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        }
    }

    /**
     * Check whether the restored boot count is the same as current one. If not, update the restored
     * one.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    public static boolean isBootUp(Context context) {
        int bootCount = Settings.Global.getInt(
                context.getContentResolver(), Settings.Global.BOOT_COUNT, -1);
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        int lastBootCount = sp.getInt(KEY_LAST_BOOT_COUNT, -1);
        if (bootCount == -1 || lastBootCount == -1 || bootCount != lastBootCount) {
            sp.edit().putInt(KEY_LAST_BOOT_COUNT, bootCount).apply();
            return true;
        }
        return false;
    }

    /** Whether embedded slot is activated or not. */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    public boolean isEmbeddedSlotActivated() {
        UiccSlot[] slots = mUiccController.getUiccSlots();
        if (slots == null) {
            return false;
        }
        for (int i = 0; i < slots.length; ++i) {
            UiccSlot slotInfo = slots[i];
            if (slotInfo.isEuicc() && slotInfo.isActive()) {
                return true;
            }
        }
        return false;
    }
    }


    private void checkCallingPackage(String callingPackage) {
    private void checkCallingPackage(String callingPackage) {
+204 −0
Original line number Original line Diff line number Diff line
/*
 * 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 com.android.internal.telephony.euicc;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;

import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;

import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccSlot;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
public class EuiccCardControllerTest extends TelephonyTest {
    private static final String KEY_LAST_BOOT_COUNT = "last_boot_count";

    private int mBootCount;
    private int mLastBootCount;
    private EuiccCardController mEuiccCardController;
    private SharedPreferences mSp;
    @Mock
    private UiccSlot mInactivatedEsimSlot;
    @Mock
    private UiccSlot mActivatedEsimSlot;
    @Mock
    private UiccSlot mActivatedRemovableSlot;
    @Mock
    private EuiccController mEuiccController;
    @Mock
    private UiccController mUiccController;
    private boolean mOtaStarted;
    private CountDownLatch mOtaLatch;


    @Before
    public void setUp() throws Exception {
        super.setUp("EuiccCardControllerTest");
        MockitoAnnotations.initMocks(this);
        mSp = PreferenceManager.getDefaultSharedPreferences(mContext);

        mLastBootCount = mSp.getInt(KEY_LAST_BOOT_COUNT, -1);
        mBootCount = Settings.Global.getInt(
                mContext.getContentResolver(), Settings.Global.BOOT_COUNT, -1);
        mOtaStarted = false;
        mOtaLatch = new CountDownLatch(1);

        when(mEuiccController.getOtaStatus()).thenReturn(EuiccManager.EUICC_OTA_SUCCEEDED);
        doAnswer(new Answer<Void>() {
                @Override
                public Void answer(InvocationOnMock invocation) throws Throwable {
                    mOtaStarted = true;
                    mOtaLatch.countDown();
                    return null;
                }
        }).when(mEuiccController).startOtaUpdatingIfNecessary();
        when(mTelephonyManager.switchSlots(any())).thenReturn(true);
        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
        when(mActivatedEsimSlot.isEuicc()).thenReturn(true);
        when(mActivatedEsimSlot.isActive()).thenReturn(true);
        when(mInactivatedEsimSlot.isEuicc()).thenReturn(true);
        when(mInactivatedEsimSlot.isActive()).thenReturn(false);
        when(mActivatedRemovableSlot.isEuicc()).thenReturn(false);
        when(mActivatedRemovableSlot.isActive()).thenReturn(true);
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
        if (mBootCount == -1) {
            Settings.Global.resetToDefaults(mContext.getContentResolver(), KEY_LAST_BOOT_COUNT);
        } else {
            Settings.Global.putInt(mContext.getContentResolver(),
                    Settings.Global.BOOT_COUNT, mBootCount);
        }
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
        sp.edit().putInt(KEY_LAST_BOOT_COUNT, mLastBootCount).apply();
    }

    @Test
    public void testIsBootUp() {
        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
        assertTrue(EuiccCardController.isBootUp(mContext));

        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
        Settings.Global.resetToDefaults(mContext.getContentResolver(), KEY_LAST_BOOT_COUNT);
        assertTrue(EuiccCardController.isBootUp(mContext));

        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 1);
        assertFalse(EuiccCardController.isBootUp(mContext));

        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 2).apply();
        assertTrue(EuiccCardController.isBootUp(mContext));
        assertEquals(mSp.getInt(KEY_LAST_BOOT_COUNT, -1), 1);
    }

    @Test
    public void testIsEmbeddedSlotActivated() {
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot});
        assertFalse(mEuiccCardController.isEmbeddedSlotActivated());

        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mActivatedEsimSlot});
        assertTrue(mEuiccCardController.isEmbeddedSlotActivated());

        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mInactivatedEsimSlot});
        assertFalse(mEuiccCardController.isEmbeddedSlotActivated());

        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {
                        mActivatedEsimSlot, mInactivatedEsimSlot, mActivatedRemovableSlot});
        assertTrue(mEuiccCardController.isEmbeddedSlotActivated());

        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {
                        mInactivatedEsimSlot, mActivatedEsimSlot, mActivatedRemovableSlot});
        assertTrue(mEuiccCardController.isEmbeddedSlotActivated());
    }

    @Test
    public void testStartOtaUpdatingIfNecessary_onEmbeddedSlot() {
        // isBootUp = true
        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});

        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        try {
            mOtaLatch.await(5000, TimeUnit.MILLISECONDS);
            assertTrue(mOtaStarted);
        } catch (InterruptedException ignore) { }
    }

    @Test
    public void testStartOtaUpdatingIfNecessary_notBootUp() {
        // isBootUp = false
        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 1);
        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);

        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        assertFalse(mOtaStarted);
    }

    @Test
    public void testStartOtaUpdatingIfNecessary_onRemovableSlot() {
        // isBootUp = true
        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot, mInactivatedEsimSlot});

        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        assertFalse(mOtaStarted);
    }
}