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

Commit c1115357 authored by Xiangyu/Malcolm Chen's avatar Xiangyu/Malcolm Chen Committed by Gerrit Code Review
Browse files

Merge "Never attempt to disable grouped CBRS until all SIM states are final."

parents 0a00be5d 772030d1
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ public class MultiSimSettingController extends Handler {

    private final Context mContext;
    private final SubscriptionController mSubController;
    private boolean mIsAllSubscriptionsLoaded;
    private List<SubscriptionInfo> mPrimarySubList;

    /** The singleton instance. */
@@ -117,7 +116,8 @@ public class MultiSimSettingController extends Handler {
    }

    /**
     * Notify that, for the first time after boot, SIMs are all loaded
     * Notify that, for the first time after boot, SIMs are initialized.
     * Should only be triggered once.
     */
    public void notifyAllSubscriptionLoaded() {
        obtainMessage(EVENT_ALL_SUBSCRIPTIONS_LOADED).sendToTarget();
@@ -207,12 +207,12 @@ public class MultiSimSettingController extends Handler {
    }

    /**
     * Mark mIsAllSubscriptionsLoaded and update defaults and mobile data enabling.
     * Upon initialization, update defaults and mobile data enabling.
     * Should only be triggered once.
     */
    @VisibleForTesting
    public void onAllSubscriptionsLoaded() {
        if (DBG) log("onAllSubscriptionsLoaded");
        mIsAllSubscriptionsLoaded = true;
        updateDefaults();
        disableDataForNonDefaultNonOpportunisticSubscriptions();
    }
@@ -225,7 +225,7 @@ public class MultiSimSettingController extends Handler {
    @VisibleForTesting
    public void onSubscriptionsChanged() {
        if (DBG) log("onSubscriptionsChanged");
        if (!mIsAllSubscriptionsLoaded) return;
        if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return;
        updateDefaults();
        disableDataForNonDefaultNonOpportunisticSubscriptions();
    }
@@ -310,7 +310,7 @@ public class MultiSimSettingController extends Handler {
    public void updateDefaults() {
        if (DBG) log("updateDefaults");

        if (!mIsAllSubscriptionsLoaded) return;
        if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return;

        List<SubscriptionInfo> activeSubInfos = mSubController
                .getActiveSubscriptionInfoList(mContext.getOpPackageName());
@@ -399,6 +399,8 @@ public class MultiSimSettingController extends Handler {
    }

    private void disableDataForNonDefaultNonOpportunisticSubscriptions() {
        if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return;

        int defaultDataSub = mSubController.getDefaultDataSubId();
        // Only disable data for non-default subscription if default sub is active.
        if (!mSubController.isActiveSubId(defaultDataSub)) {
+17 −42
Original line number Diff line number Diff line
@@ -211,27 +211,17 @@ public class SubscriptionController extends ISub.Stub {
        if (DBG) logdl("[SubscriptionController] init by Context");
    }

    /**
     * Should only be triggered once.
     */
    public void notifySubInfoReady() {
        // broadcast default subId.
        sendDefaultChangedBroadcast(SubscriptionManager.getDefaultSubscriptionId());
    }

    @UnsupportedAppUsage
    private boolean isSubInfoReady() {
        if (VDBG) {
            // make sure sSlotIndexToSubIds is consistent with cached subinfo list
            int count = 0;
            for (Integer i : sSlotIndexToSubIds.keySet()) {
                count += sSlotIndexToSubIds.get(i).size();
            }
            if (count != mCacheActiveSubInfoList.size()) {
                logdl("mismatch between map and list. list size = " + mCacheActiveSubInfoList.size()
                        + ", map size = " + count);
                for (Integer i : sSlotIndexToSubIds.keySet()) {
                    logdl("From the Map, subs in map at slot index: " + i + " are: "
                            + sSlotIndexToSubIds.get(i));
                }
                for (SubscriptionInfo info : mCacheActiveSubInfoList) {
                    logdl("From the Cached list, subinfo is: " + info);
                }
            }
        }
        return sSlotIndexToSubIds.size() > 0;
        return SubscriptionInfoUpdater.isSubInfoInitialized();
    }

    /**
@@ -703,14 +693,6 @@ public class SubscriptionController extends ISub.Stub {
     */
    @VisibleForTesting  // For mockito to mock this method
    public void refreshCachedActiveSubscriptionInfoList() {
        if (!isSubInfoReady()) {
            if (DBG_CACHE) {
                logdl("[refreshCachedActiveSubscriptionInfoList] "
                        + "Sub Controller not ready ");
            }
            return;
        }

        boolean opptSubListChanged;

        synchronized (mSubInfoListLock) {
@@ -1365,8 +1347,7 @@ public class SubscriptionController extends ISub.Stub {
        if (DBG) logdl("[clearSubInfoRecord]+ iccId:" + " slotIndex:" + slotIndex);

        // update simInfo db with invalid slot index
        List<SubscriptionInfo> oldSubInfo = getSubInfoUsingSlotIndexPrivileged(slotIndex,
                false);
        List<SubscriptionInfo> oldSubInfo = getSubInfoUsingSlotIndexPrivileged(slotIndex);
        ContentResolver resolver = mContext.getContentResolver();
        ContentValues value = new ContentValues(1);
        value.put(SubscriptionManager.SIM_SLOT_INDEX,
@@ -2327,8 +2308,7 @@ public class SubscriptionController extends ISub.Stub {

    /** Must be public for access from instrumentation tests. */
    @VisibleForTesting
    public List<SubscriptionInfo> getSubInfoUsingSlotIndexPrivileged(int slotIndex,
            boolean needCheck) {
    public List<SubscriptionInfo> getSubInfoUsingSlotIndexPrivileged(int slotIndex) {
        if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]+ slotIndex:" + slotIndex);
        if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) {
            slotIndex = getSlotIndex(getDefaultSubId());
@@ -2338,11 +2318,6 @@ public class SubscriptionController extends ISub.Stub {
            return null;
        }

        if (needCheck && !isSubInfoReady()) {
            if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]- not ready");
            return null;
        }

        Cursor cursor = mContext.getContentResolver().query(SubscriptionManager.CONTENT_URI,
                null, SubscriptionManager.SIM_SLOT_INDEX + "=?",
                new String[]{String.valueOf(slotIndex)}, null);
@@ -3467,11 +3442,6 @@ public class SubscriptionController extends ISub.Stub {
    // They are doing similar things except operating on different cache.
    private List<SubscriptionInfo> getSubscriptionInfoListFromCacheHelper(
            String callingPackage, List<SubscriptionInfo> cacheSubList) {
        if (!isSubInfoReady()) {
            if (DBG) logd("[getSubscriptionInfoList] Sub Controller not ready");
            return null;
        }

        boolean canReadAllPhoneState;
        try {
            canReadAllPhoneState = TelephonyPermissions.checkReadPhoneState(mContext,
@@ -3580,7 +3550,11 @@ public class SubscriptionController extends ISub.Stub {
            for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
                if (shouldDisableSubGroup(info.getGroupUuid())) {
                    info.setGroupDisabled(true);
                    if (isActiveSubId(info.getSubscriptionId())) {
                    // TODO: move it to ONS.
                    if (isActiveSubId(info.getSubscriptionId()) && isSubInfoReady()) {
                        logd("[refreshCachedOpportunisticSubscriptionInfoList] "
                                + "Deactivating grouped opportunistic subscription "
                                + info.getSubscriptionId());
                        deactivateSubscription(info);
                    }
                }
@@ -3616,6 +3590,7 @@ public class SubscriptionController extends ISub.Stub {
    private void deactivateSubscription(SubscriptionInfo info) {
        // TODO: b/120439488 deactivate pSIM.
        if (info.isEmbedded()) {
            logd("[deactivateSubscription] eSIM profile " + info.getSubscriptionId());
            EuiccManager euiccManager = (EuiccManager)
                    mContext.getSystemService(Context.EUICC_SERVICE);
            euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+23 −9
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ public class SubscriptionInfoUpdater extends Handler {
    private static String mIccId[] = new String[PROJECT_SIM_NUM];
    private static int[] sSimCardState = new int[PROJECT_SIM_NUM];
    private static int[] sSimApplicationState = new int[PROJECT_SIM_NUM];
    private static boolean sIsSubInfoInitialized = false;
    private SubscriptionManager mSubscriptionManager = null;
    private EuiccManager mEuiccManager;
    @UnsupportedAppUsage
@@ -420,7 +421,7 @@ public class SubscriptionInfoUpdater extends Handler {

        updateSubscriptionInfoByIccId(slotId);
        List<SubscriptionInfo> subscriptionInfos = SubscriptionController.getInstance()
                .getSubInfoUsingSlotIndexPrivileged(slotId, false);
                .getSubInfoUsingSlotIndexPrivileged(slotId);
        if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
            loge("empty subinfo for slotId: " + slotId + "could not update ContentResolver");
        } else {
@@ -587,7 +588,7 @@ public class SubscriptionInfoUpdater extends Handler {
        }

        List<SubscriptionInfo> subInfos = SubscriptionController.getInstance()
                .getSubInfoUsingSlotIndexPrivileged(slotIndex, false);
                .getSubInfoUsingSlotIndexPrivileged(slotIndex);
        if (subInfos != null) {
            boolean changed = false;
            for (int i = 0; i < subInfos.size(); i++) {
@@ -629,17 +630,30 @@ public class SubscriptionInfoUpdater extends Handler {
                                uiccSlot.getUiccCard().getCardId()))
                        .forEach(cardId -> updateEmbeddedSubscriptions(cardId));
            }
            // update default subId
            MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
            // broadcast default subId
            SubscriptionController.getInstance().sendDefaultChangedBroadcast(
                    SubscriptionManager.getDefaultSubscriptionId());
            setSubInfoInitialized();
        }

        SubscriptionController.getInstance().notifySubscriptionInfoChanged();
        logd("updateSubscriptionInfoByIccId:- SubscriptionInfo update complete");
    }

    private static void setSubInfoInitialized() {
        // Should only be triggered once.
        if (!sIsSubInfoInitialized) {
            if (DBG) logd("SubInfo Initialized");
            sIsSubInfoInitialized = true;
            SubscriptionController.getInstance().notifySubInfoReady();
            MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
        }
    }

    /**
     * Whether subscriptions of all SIMs are initialized.
     */
    public static boolean isSubInfoInitialized() {
        return sIsSubInfoInitialized;
    }

    /**
     * Update the cached list of embedded subscription for the eUICC with the given card ID
     * {@code cardId}.
@@ -1013,11 +1027,11 @@ public class SubscriptionInfoUpdater extends Handler {
    }

    @UnsupportedAppUsage
    private void logd(String message) {
    private static void logd(String message) {
        Rlog.d(LOG_TAG, message);
    }

    private void loge(String message) {
    private static void loge(String message) {
        Rlog.e(LOG_TAG, message);
    }

+27 −9
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
@@ -56,6 +55,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.telephony.euicc.EuiccController;
import com.android.internal.telephony.uicc.IccFileHandler;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccSlot;

import org.junit.After;
import org.junit.Before;
@@ -98,6 +98,8 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
    private IntentBroadcaster mIntentBroadcaster;
    @Mock
    private IPackageManager mPackageManager;
    @Mock
    private UiccSlot mUiccSlot;

    /*Custom ContentProvider */
    private class FakeSubscriptionContentProvider extends MockContentProvider {
@@ -130,10 +132,13 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        replaceInstance(SubscriptionInfoUpdater.class, "PROJECT_SIM_NUM", null, 1);
        replaceInstance(SubscriptionInfoUpdater.class, "sSimCardState", null, new int[1]);
        replaceInstance(SubscriptionInfoUpdater.class, "sSimApplicationState", null, new int[1]);
        replaceInstance(SubscriptionInfoUpdater.class, "sIsSubInfoInitialized", null, false);

        replaceInstance(EuiccController.class, "sInstance", null, mEuiccController);
        replaceInstance(IntentBroadcaster.class, "sIntentBroadcaster", null, mIntentBroadcaster);

        doReturn(true).when(mUiccSlot).isActive();
        doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
        doReturn(1).when(mTelephonyManager).getSimCount();
        doReturn(1).when(mTelephonyManager).getPhoneCount();

@@ -162,6 +167,8 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        mSubscriptionInfoUpdaterHandlerThread = new SubscriptionInfoUpdaterHandlerThread(TAG);
        mSubscriptionInfoUpdaterHandlerThread.start();
        waitUntilReady();

        assertFalse(mUpdater.isSubInfoInitialized());
    }

    @After
@@ -174,13 +181,14 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
    @SmallTest
    public void testSimAbsent() throws Exception {
        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
        doReturn(new int[]{FAKE_SUB_ID_1}).when(mSubscriptionController)
                .getActiveSubIdList(/*visibleOnly*/false);
        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1, false);

        waitForMs(100);
        assertTrue(mUpdater.isSubInfoInitialized());
        verify(mSubscriptionController, times(1)).clearSubInfoRecord(eq(FAKE_SUB_ID_1));

        CarrierConfigManager mConfigManager = (CarrierConfigManager)
@@ -194,13 +202,14 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
    @SmallTest
    public void testSimAbsentAndInactive() throws Exception {
        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
        doReturn(new int[]{FAKE_SUB_ID_1}).when(mSubscriptionController)
                .getActiveSubIdList(/*visibleOnly*/false);
        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1, true);

        waitForMs(100);
        assertTrue(mUpdater.isSubInfoInitialized());
        verify(mSubscriptionController, times(1)).clearSubInfoRecord(eq(FAKE_SUB_ID_1));

        // Verify that in the special absent and inactive case, we update subscriptions without
@@ -220,6 +229,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
                IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null, FAKE_SUB_ID_1, false);

        waitForMs(100);
        assertFalse(mUpdater.isSubInfoInitialized());
        verify(mSubscriptionContent, times(0)).put(anyString(), any());
        CarrierConfigManager mConfigManager = (CarrierConfigManager)
                mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -236,6 +246,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
                IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR, null, FAKE_SUB_ID_1, false);

        waitForMs(100);
        assertTrue(mUpdater.isSubInfoInitialized());
        verify(mSubscriptionContent, times(0)).put(anyString(), any());
        CarrierConfigManager mConfigManager = (CarrierConfigManager)
                mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -252,6 +263,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
                IccCardConstants.INTENT_VALUE_ICC_IMSI, null, 2, false);

        waitForMs(100);
        assertFalse(mUpdater.isSubInfoInitialized());
        verify(mSubscriptionContent, times(0)).put(anyString(), any());
        CarrierConfigManager mConfigManager = (CarrierConfigManager)
                mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -266,7 +278,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
    public void testSimLoaded() throws Exception {
        doReturn(FAKE_SUB_ID_1).when(mSubInfo).getSubscriptionId();
        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
        doReturn("89012604200000000000").when(mIccRecord).getFullIccId();
        doReturn(FAKE_MCC_MNC_1).when(mTelephonyManager).getSimOperatorNumeric(FAKE_SUB_ID_1);

@@ -274,6 +286,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
                IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1, false);

        waitForMs(100);
        assertTrue(mUpdater.isSubInfoInitialized());

        // verify SIM_STATE_CHANGED broadcast. It should be broadcast twice, once for
        // READ_PHONE_STATE and once for READ_PRIVILEGED_PHONE_STATE
@@ -334,11 +347,12 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        doReturn("").when(mTelephonyManager).getSimOperatorNumeric(FAKE_SUB_ID_1);
        doReturn(FAKE_SUB_ID_1).when(mSubInfo).getSubscriptionId();
        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1, false);

        waitForMs(300);
        assertTrue(mUpdater.isSubInfoInitialized());
        SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext);
        verify(mTelephonyManager).getSimOperatorNumeric(FAKE_SUB_ID_1);
        verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(
@@ -360,12 +374,13 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        doReturn("98106240020000000000").when(mIccRecord).getFullIccId();

        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_LOCKED, "TESTING", FAKE_SUB_ID_1, false);

        waitForMs(100);

        assertTrue(mUpdater.isSubInfoInitialized());
        SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext);
        verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(
                eq("98106240020000000000"), eq(FAKE_SUB_ID_1));
@@ -408,7 +423,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {

        // Mock sending a sim loaded for SIM 1
        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1, false);

@@ -417,10 +432,11 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(anyString(), anyInt());
        verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged();
        verify(mSubscriptionController, times(1)).setMccMnc(anyString(), anyInt());
        assertFalse(mUpdater.isSubInfoInitialized());

        // Mock sending a sim loaded for SIM 2
        doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_2), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_2));
        doReturn(FAKE_SUB_ID_2).when(mSubInfo).getSubscriptionId();
        doReturn("89012604200000000001").when(mIccRecord).getFullIccId();

@@ -436,6 +452,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        verify(mSubscriptionController, times(1)).setMccMnc(eq(FAKE_MCC_MNC_1), eq(FAKE_SUB_ID_1));
        verify(mSubscriptionController, times(1)).setMccMnc(eq(FAKE_MCC_MNC_2), eq(FAKE_SUB_ID_2));
        verify(mSubscriptionController, times(2)).notifySubscriptionInfoChanged();
        assertTrue(mUpdater.isSubInfoInitialized());
    }

    @Test
@@ -451,6 +468,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {

        waitForMs(100);

        assertTrue(mUpdater.isSubInfoInitialized());
        SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext);
        verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(
                anyString(), eq(FAKE_SUB_ID_1));
@@ -582,7 +600,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
    @SmallTest
    public void testHexIccIdSuffix() throws Exception {
        doReturn(null).when(mSubscriptionController)
                .getSubInfoUsingSlotIndexPrivileged(anyInt(), anyBoolean());
                .getSubInfoUsingSlotIndexPrivileged(anyInt());
        verify(mSubscriptionController, times(0)).clearSubInfo();
        doReturn("890126042000000000Ff").when(mIccRecord).getFullIccId();

+1 −0
Original line number Diff line number Diff line
@@ -563,6 +563,7 @@ public abstract class TelephonyTest {
                mCellularNetworkValidator);
        replaceInstance(MultiSimSettingController.class, "sInstance", null,
                mMultiSimSettingController);
        replaceInstance(SubscriptionInfoUpdater.class, "sIsSubInfoInitialized", null, true);

        assertNotNull("Failed to set up SubscriptionController singleton",
                SubscriptionController.getInstance());