Loading src/java/com/android/internal/telephony/ims/ImsResolver.java +79 −20 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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); } } } } /** Loading Loading @@ -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 Loading Loading @@ -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. Loading @@ -1082,7 +1142,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } } } } /** * Schedules a query for dynamic ImsService features. Loading src/java/com/android/internal/telephony/ims/ImsServiceController.java +3 −0 Original line number Diff line number Diff line Loading @@ -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 = Loading tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java +59 −35 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -88,6 +89,8 @@ public class ImsResolverTest extends ImsTestBase { @Mock ImsResolver.SubscriptionManagerProxy mTestSubscriptionManagerProxy; @Mock ImsResolver.TelephonyManagerProxy mTestTelephonyManagerProxy; @Mock CarrierConfigManager mMockCarrierConfigManager; @Mock ImsResolver.ImsDynamicQueryManagerFactory mMockQueryManagerFactory; Loading Loading @@ -129,7 +132,7 @@ public class ImsResolverTest extends ImsTestBase { setupController(); // Complete package manager lookup and cache. startBind(); startBindCarrierConfigAlreadySet(); ImsResolver.ImsServiceInfo testCachedService = mTestImsResolver.getImsServiceInfoFromCache( Loading @@ -155,7 +158,7 @@ public class ImsResolverTest extends ImsTestBase { setupController(); // Complete package manager lookup and cache. startBind(); startBindCarrierConfigAlreadySet(); ImsResolver.ImsServiceInfo testCachedService = mTestImsResolver.getImsServiceInfoFromCache( Loading Loading @@ -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); Loading @@ -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); Loading @@ -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(); Loading Loading @@ -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()); Loading @@ -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); Loading Loading @@ -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 Loading @@ -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()); Loading Loading @@ -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)); Loading Loading @@ -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 Loading @@ -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()); Loading Loading @@ -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); Loading @@ -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()); Loading Loading @@ -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); Loading @@ -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()); Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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<>(); Loading Loading @@ -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(), Loading @@ -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); Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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); Loading Loading
src/java/com/android/internal/telephony/ims/ImsResolver.java +79 −20 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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); } } } } /** Loading Loading @@ -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 Loading Loading @@ -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. Loading @@ -1082,7 +1142,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } } } } /** * Schedules a query for dynamic ImsService features. Loading
src/java/com/android/internal/telephony/ims/ImsServiceController.java +3 −0 Original line number Diff line number Diff line Loading @@ -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 = Loading
tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java +59 −35 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -88,6 +89,8 @@ public class ImsResolverTest extends ImsTestBase { @Mock ImsResolver.SubscriptionManagerProxy mTestSubscriptionManagerProxy; @Mock ImsResolver.TelephonyManagerProxy mTestTelephonyManagerProxy; @Mock CarrierConfigManager mMockCarrierConfigManager; @Mock ImsResolver.ImsDynamicQueryManagerFactory mMockQueryManagerFactory; Loading Loading @@ -129,7 +132,7 @@ public class ImsResolverTest extends ImsTestBase { setupController(); // Complete package manager lookup and cache. startBind(); startBindCarrierConfigAlreadySet(); ImsResolver.ImsServiceInfo testCachedService = mTestImsResolver.getImsServiceInfoFromCache( Loading @@ -155,7 +158,7 @@ public class ImsResolverTest extends ImsTestBase { setupController(); // Complete package manager lookup and cache. startBind(); startBindCarrierConfigAlreadySet(); ImsResolver.ImsServiceInfo testCachedService = mTestImsResolver.getImsServiceInfoFromCache( Loading Loading @@ -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); Loading @@ -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); Loading @@ -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(); Loading Loading @@ -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()); Loading @@ -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); Loading Loading @@ -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 Loading @@ -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()); Loading Loading @@ -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)); Loading Loading @@ -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 Loading @@ -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()); Loading Loading @@ -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); Loading @@ -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()); Loading Loading @@ -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); Loading @@ -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()); Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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<>(); Loading Loading @@ -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(), Loading @@ -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); Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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); Loading