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

Commit 2a15ee94 authored by Brad Ebinger's avatar Brad Ebinger Committed by android-build-merger
Browse files

Merge "ImsResolver will wait for CarrierConfig changes to update" am: 059a3de7 am: 844443c1

am: d17267fc

Change-Id: I574d6b6447ad31e94c84cfe39634d630c55b14b5
parents 138b6d59 d17267fc
Loading
Loading
Loading
Loading
+79 −20
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
@@ -217,7 +218,19 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                    SubscriptionManager.INVALID_SIM_SLOT_INDEX);

            if (slotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
                Log.i(TAG, "Received SIM change for invalid slot id.");
                Log.i(TAG, "Received CCC for invalid slot id.");
                return;
            }

            int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
            int slotSimState = mTelephonyManagerProxy.getSimState(mContext, slotId);
            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
                    && slotSimState != TelephonyManager.SIM_STATE_ABSENT) {
                // We only care about carrier config updates that happen when a slot is known to be
                // absent or populated and the carrier config has been loaded.
                Log.i(TAG, "Received CCC for slot " + slotId + " and sim state "
                        + slotSimState + ", ignoring.");
                return;
            }

@@ -254,6 +267,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        int getSlotIndex(int subId);
    }

    /**
     * Testing interface used to stub out TelephonyManager dependencies.
     */
    @VisibleForTesting
    public interface TelephonyManagerProxy {
        /**
         * @return the SIM state for the slot ID specified.
         */
        int getSimState(Context context, int slotId);
    }

    private TelephonyManagerProxy mTelephonyManagerProxy = new TelephonyManagerProxy() {
        @Override
        public int getSimState(Context context, int slotId) {
            TelephonyManager tm = context.getSystemService(TelephonyManager.class);
            if (tm == null) {
                return TelephonyManager.SIM_STATE_UNKNOWN;
            }
            return tm.getSimState(slotId);
        }
    };

    private SubscriptionManagerProxy mSubscriptionManagerProxy = new SubscriptionManagerProxy() {
        @Override
        public int getSubId(int slotId) {
@@ -496,6 +531,11 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        }
    }

    @VisibleForTesting
    public void setTelephonyManagerProxy(TelephonyManagerProxy proxy) {
        mTelephonyManagerProxy = proxy;
    }

    @VisibleForTesting
    public void setSubscriptionManagerProxy(SubscriptionManagerProxy proxy) {
        mSubscriptionManagerProxy = proxy;
@@ -520,13 +560,32 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
     * Needs to be called after the constructor to kick off the process of binding to ImsServices.
     */
    public void initialize() {
        Log.i(TAG, "Initializing cache and binding.");
        Log.i(TAG, "Initializing cache.");
        mFeatureQueryManager = mDynamicQueryManagerFactory.create(mContext, mDynamicQueryListener);
        // Populates the CarrierConfig override package names for each slot
        mHandler.obtainMessage(HANDLER_CONFIG_CHANGED,
                SubscriptionManager.INVALID_SIM_SLOT_INDEX).sendToTarget();
        // Starts first bind to the system.
        mHandler.obtainMessage(HANDLER_ADD_PACKAGE, null).sendToTarget();

        // This will get all services with the correct intent filter from PackageManager
        List<ImsServiceInfo> infos = getImsServiceInfo(null);
        for (ImsServiceInfo info : infos) {
            if (!mInstalledServicesCache.containsKey(info.name)) {
                mInstalledServicesCache.put(info.name, info);
            }
        }
        // Update the package names of the carrier ImsServices if they do not exist already and
        // possibly bind if carrier configs exist. Otherwise wait for CarrierConfigChanged
        // indication.
        for (int i = 0; i < mNumSlots; i++) {
            int subId = mSubscriptionManagerProxy.getSubId(i);
            PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
            if (config != null && mCarrierServices[i] == null) {
                String newPackageName = config.getString(
                        CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
                if (!TextUtils.isEmpty(newPackageName)) {
                    updateBoundCarrierServices(i, newPackageName);
                    Log.i(TAG, "Initializing, found package " + newPackageName + " on slot "
                            + i);
                }
            }
        }
    }

    /**
@@ -860,7 +919,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                    Log.d(TAG, "Updating Features - New Features: " + features);
                    controller.changeImsServiceFeatures(features);
                } else {
                    Log.i(TAG, "updateImsServiceFeatures: unbound with active features, rebinding");
                    Log.i(TAG, "updateImsServiceFeatures: unbound with active features, binding");
                    bindImsServiceWithFeatures(newInfo, features);
                }
                // If the carrier service features have changed, the device features will also
@@ -1068,6 +1127,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                // ImsService is retrieved from the cache. If the cache hasn't been populated yet,
                // the calls to unbind/bind will fail (intended during initial start up).
                unbindImsService(getImsServiceInfoFromCache(oldPackageName));
            }
            ImsServiceInfo newInfo = getImsServiceInfoFromCache(newPackageName);
            // if there is no carrier ImsService, newInfo is null. This we still want to update
            // bindings for device ImsService to pick up the missing features.
@@ -1082,7 +1142,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
            }
        }
    }
    }

    /**
     * Schedules a query for dynamic ImsService features.
+3 −0
Original line number Diff line number Diff line
@@ -397,6 +397,9 @@ public class ImsServiceController {
            HashSet<ImsFeatureConfiguration.FeatureSlotPair> newImsFeatures)
            throws RemoteException {
        synchronized (mLock) {
            if (mImsFeatures.equals(newImsFeatures)) {
                return;
            }
            Log.i(LOG_TAG, "Features changed (" + mImsFeatures + "->" + newImsFeatures + ") for "
                    + "ImsService: " + mComponentName);
            HashSet<ImsFeatureConfiguration.FeatureSlotPair> oldImsFeatures =
+59 −35
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
@@ -88,6 +89,8 @@ public class ImsResolverTest extends ImsTestBase {
    @Mock
    ImsResolver.SubscriptionManagerProxy mTestSubscriptionManagerProxy;
    @Mock
    ImsResolver.TelephonyManagerProxy mTestTelephonyManagerProxy;
    @Mock
    CarrierConfigManager mMockCarrierConfigManager;
    @Mock
    ImsResolver.ImsDynamicQueryManagerFactory mMockQueryManagerFactory;
@@ -129,7 +132,7 @@ public class ImsResolverTest extends ImsTestBase {
        setupController();

        // Complete package manager lookup and cache.
        startBind();
        startBindCarrierConfigAlreadySet();

        ImsResolver.ImsServiceInfo testCachedService =
                mTestImsResolver.getImsServiceInfoFromCache(
@@ -155,7 +158,7 @@ public class ImsResolverTest extends ImsTestBase {
        setupController();

        // Complete package manager lookup and cache.
        startBind();
        startBindCarrierConfigAlreadySet();

        ImsResolver.ImsServiceInfo testCachedService =
                mTestImsResolver.getImsServiceInfoFromCache(
@@ -185,7 +188,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController controller = setupController();

        // Start bind to carrier service
        startBind();
        startBindCarrierConfigAlreadySet();
        // setup features response
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);

@@ -210,7 +213,7 @@ public class ImsResolverTest extends ImsTestBase {
        setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
        ImsServiceController controller = setupController();

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);

        verify(controller).bind(features);
@@ -234,7 +237,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController controller = setupController();

        // Bind without emergency calling
        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
        verify(controller).bind(features);
        verify(controller, never()).unbind();
@@ -266,7 +269,7 @@ public class ImsResolverTest extends ImsTestBase {
        // Set the CarrierConfig string to null so that ImsResolver will not bind to the available
        // Services
        setConfigCarrierString(0, null);
        startBind();
        startBindCarrierConfigAlreadySet();

        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
        verify(mMockQueryManager, never()).startQuery(any(), any());
@@ -293,7 +296,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController controller = setupController();


        startBind();
        startBindNoCarrierConfig(1);
        // Wait to make sure that there are no dynamic queries that are being completed.
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);

@@ -333,7 +336,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);

        // Verify that all features that have been defined for the carrier override are bound
@@ -344,6 +347,7 @@ public class ImsResolverTest extends ImsTestBase {
        // device controller (including emergency voice for slot 0)
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
                convertToHashSet(deviceFeatures, 0);
        deviceFeatureSet.removeAll(carrierFeatures);
        verify(deviceController).bind(deviceFeatureSet);
        verify(deviceController, never()).unbind();
        assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -394,7 +398,7 @@ public class ImsResolverTest extends ImsTestBase {
        setupPackageQuery(info);
        ImsServiceController controller = setupController();
        // Bind using default features
        startBind();
        startBindNoCarrierConfig(2);
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
                convertToHashSet(features, 0);
        featureSet.addAll(convertToHashSet(features, 1));
@@ -442,7 +446,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);

        // Verify that all features that have been defined for the carrier override are bound
@@ -455,9 +459,7 @@ public class ImsResolverTest extends ImsTestBase {
                convertToHashSet(deviceFeatures, 1);
        deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
        deviceFeatureSet.removeAll(carrierFeatures);
        // we will first have bound to device and then the features will change once the dynamic
        // returns. So, instead of checking the bind parameters, we will check the change parameters
        verify(deviceController).changeImsServiceFeatures(deviceFeatureSet);
        verify(deviceController).bind(deviceFeatureSet);
        verify(deviceController, never()).unbind();
        assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());

@@ -508,7 +510,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
        // Verify that all features that have been defined for the carrier override are bound
        verify(carrierController).bind(carrierFeatures);
@@ -520,9 +522,7 @@ public class ImsResolverTest extends ImsTestBase {
                convertToHashSet(deviceFeatures, 1);
        deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
        deviceFeatureSet.removeAll(carrierFeatures);
        // device ImsService will bind with all of its defined features first and then when the
        // carrier query comes back, it will change. So, checking change instead of bind here.
        verify(deviceController).changeImsServiceFeatures(deviceFeatureSet);
        verify(deviceController).bind(deviceFeatureSet);
        verify(deviceController, never()).unbind();
        assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());

@@ -566,7 +566,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
        // Verify that all features that have been defined for the carrier override are bound
        verify(carrierController).bind(carrierFeatures);
@@ -578,9 +578,7 @@ public class ImsResolverTest extends ImsTestBase {
                convertToHashSet(deviceFeatures, 1);
        deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
        deviceFeatureSet.removeAll(carrierFeatures);
        // we will first have bound to device and then the features will change once the dynamic
        // returns. So, instead of checking the bind parameters, we will check the change parameters
        verify(deviceController).changeImsServiceFeatures(deviceFeatureSet);
        verify(deviceController).bind(deviceFeatureSet);
        verify(deviceController, never()).unbind();
        assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());

@@ -624,7 +622,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();

        HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
        // Carrier service doesn't support the voice feature.
@@ -670,7 +668,7 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);

        // Tell the package manager that carrier app is uninstalled
@@ -714,14 +712,11 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);

        setConfigCarrierString(0, null);
        Intent carrierConfigIntent = new Intent();
        carrierConfigIntent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
        mTestCarrierConfigReceiver.onReceive(null, carrierConfigIntent);
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
        sendCarrierConfigChanged(0, 0);

        // Verify that the carrier controller is unbound
        verify(carrierController).unbind();
@@ -768,14 +763,11 @@ public class ImsResolverTest extends ImsTestBase {
        ImsServiceController carrierController2 = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController1, carrierController2);

        startBind();
        startBindCarrierConfigAlreadySet();
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures1, 1);

        setConfigCarrierString(0, TEST_CARRIER_2_DEFAULT_NAME.getPackageName());
        Intent carrierConfigIntent = new Intent();
        carrierConfigIntent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
        mTestCarrierConfigReceiver.onReceive(null, carrierConfigIntent);
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
        sendCarrierConfigChanged(0, 0);
        setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, carrierFeatures2, 1);

        // Verify that carrier 1 is unbound
@@ -816,7 +808,7 @@ public class ImsResolverTest extends ImsTestBase {
        setImsServiceControllerFactory(deviceController, carrierController);

        // Bind with device ImsService
        startBind();
        startBindCarrierConfigAlreadySet();

        // Boot complete happens and the Carrier ImsService is now available.
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
@@ -849,6 +841,8 @@ public class ImsResolverTest extends ImsTestBase {
                    mCarrierConfigs[i]);
            when(mTestSubscriptionManagerProxy.getSlotIndex(eq(i))).thenReturn(i);
            when(mTestSubscriptionManagerProxy.getSubId(eq(i))).thenReturn(i);
            when(mTestTelephonyManagerProxy.getSimState(any(Context.class), eq(i))).thenReturn(
                    TelephonyManager.SIM_STATE_READY);
        }

        mTestImsResolver = new ImsResolver(mMockContext, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
@@ -865,6 +859,7 @@ public class ImsResolverTest extends ImsTestBase {
        mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(0);
        mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(1);
        mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
        mTestImsResolver.setTelephonyManagerProxy(mTestTelephonyManagerProxy);
        when(mMockQueryManagerFactory.create(any(Context.class),
                any(ImsServiceFeatureQueryManager.Listener.class))).thenReturn(mMockQueryManager);
        mTestImsResolver.setImsDynamicQueryManagerFactory(mMockQueryManagerFactory);
@@ -906,7 +901,11 @@ public class ImsResolverTest extends ImsTestBase {
        return controller;
    }

    private void startBind() {
    /**
     * In this case, there is a CarrierConfig already set for the sub/slot combo when initializing.
     * This automatically kicks off the binding internally.
     */
    private void startBindCarrierConfigAlreadySet() {
        mTestImsResolver.initialize();
        ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
                ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
@@ -915,6 +914,23 @@ public class ImsResolverTest extends ImsTestBase {
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
    }

    /**
     * In this case, there is no carrier config override, send CarrierConfig loaded intent to all
     * slots, indicating that the SIMs are loaded and to bind the device default.
     */
    private void startBindNoCarrierConfig(int numSlots) {
        mTestImsResolver.initialize();
        ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
                ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
        verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
        mDynamicQueryListener = queryManagerCaptor.getValue();
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
        // For ease of testing, slotId = subId
        for (int i = 0; i < numSlots; i++) {
            sendCarrierConfigChanged(i, i);
        }
    }

    private void setupDynamicQueryFeatures(ComponentName name,
            HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
        // wait for schedule to happen
@@ -1004,6 +1020,14 @@ public class ImsResolverTest extends ImsTestBase {
    }


    private void sendCarrierConfigChanged(int subId, int slotId) {
        Intent carrierConfigIntent = new Intent();
        carrierConfigIntent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, subId);
        carrierConfigIntent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, slotId);
        mTestCarrierConfigReceiver.onReceive(null, carrierConfigIntent);
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
    }

    private void setConfigCarrierString(int subId, String packageName) {
        mCarrierConfigs[subId].putString(
                CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, packageName);