Loading src/java/com/android/internal/telephony/ims/ImsResolver.java +18 −2 Original line number Diff line number Diff line Loading @@ -481,6 +481,13 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal Log.w(TAG, "onError: " + name + "returned with an error result"); scheduleQueryForFeatures(name, DELAY_DYNAMIC_QUERY_MS); } @Override public void onPermanentError(ComponentName name) { Log.w(TAG, "onPermanentError: component=" + name); mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget(); } }; // Array index corresponds to slot Id associated with the service package name. Loading Loading @@ -840,8 +847,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } } // Remove the ImsService from the cache. At this point, the ImsService will have already been // killed. // Remove the ImsService from the cache. This may have been due to the ImsService being removed // from the device or was returning permanent errors when bound. // Called from the handler ONLY private boolean maybeRemovedImsService(String packageName) { ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName); Loading Loading @@ -1066,6 +1073,15 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal handleFeaturesChanged(controller.getComponentName(), config.getServiceFeatures()); } @Override public void imsServiceBindPermanentError(ComponentName name) { if (name == null) { return; } Log.w(TAG, "imsServiceBindPermanentError: component=" + name); mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget(); } /** * Determines if the features specified should cause a bind or keep a binding active to an * ImsService. Loading src/java/com/android/internal/telephony/ims/ImsServiceController.java +41 −18 Original line number Diff line number Diff line Loading @@ -71,10 +71,9 @@ public class ImsServiceController { synchronized (mLock) { mIsBound = true; mIsBinding = false; try { Log.d(LOG_TAG, "ImsService(" + name + "): onServiceConnected with binder: " + service); if (service != null) { try { setServiceController(service); notifyImsServiceReady(); // create all associated features in the ImsService Loading @@ -92,7 +91,6 @@ public class ImsServiceController { } } } } @Override public void onServiceDisconnected(ComponentName name) { Loading @@ -111,10 +109,27 @@ public class ImsServiceController { mIsBound = false; } cleanupConnection(); // according to the docs, we should fully unbind before rebinding again. mContext.unbindService(mImsServiceConnection); Log.w(LOG_TAG, "ImsService(" + name + "): onBindingDied. Starting rebind..."); startDelayedRebindToService(); } @Override public void onNullBinding(ComponentName name) { Log.w(LOG_TAG, "ImsService(" + name + "): onNullBinding. Removing."); synchronized (mLock) { mIsBinding = false; mIsBound = false; } cleanupConnection(); if (mCallbacks != null) { // Will trigger an unbind. mCallbacks.imsServiceBindPermanentError(getComponentName()); } } // Does not clear features, just removes all active features. private void cleanupConnection() { cleanupAllFeatures(); cleanUpService(); Loading Loading @@ -151,6 +166,12 @@ public class ImsServiceController { */ void imsServiceFeaturesChanged(ImsFeatureConfiguration config, ImsServiceController controller); /** * Called by the ImsServiceController when there has been an error binding that is * not recoverable, such as the ImsService returning a null binder. */ void imsServiceBindPermanentError(ComponentName name); } /** Loading Loading @@ -385,6 +406,8 @@ public class ImsServiceController { removeImsServiceFeatureCallbacks(); Log.i(LOG_TAG, "Unbinding ImsService: " + mComponentName); mContext.unbindService(mImsServiceConnection); mIsBound = false; mIsBinding = false; cleanUpService(); } } Loading src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java +16 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.telephony.ims.aidl.IImsServiceController; import android.telephony.ims.stub.ImsFeatureConfiguration; import android.util.Log; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; Loading Loading @@ -71,8 +72,9 @@ public class ImsServiceFeatureQueryManager { if (service != null) { queryImsFeatures(IImsServiceController.Stub.asInterface(service)); } else { Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null, cleaning up."); Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null."); cleanup(); mListener.onPermanentError(name); } } Loading @@ -91,7 +93,14 @@ public class ImsServiceFeatureQueryManager { mListener.onError(mName); return; } Set<ImsFeatureConfiguration.FeatureSlotPair> servicePairs = config.getServiceFeatures(); Set<ImsFeatureConfiguration.FeatureSlotPair> servicePairs; if (config == null) { // ensure that if the ImsService sent a null config, we return an empty feature // set to the ImsResolver. servicePairs = Collections.emptySet(); } else { servicePairs = config.getServiceFeatures(); } // Complete, remove from active queries and notify. cleanup(); mListener.onComplete(mName, servicePairs); Loading @@ -117,6 +126,11 @@ public class ImsServiceFeatureQueryManager { * Called when a query has failed and should be retried. */ void onError(ComponentName name); /** * Called when a query has failed due to a permanent error and should not be retried. */ void onPermanentError(ComponentName name); } // Maps an active ImsService query (by Package Name String) its query. Loading tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java +103 −0 Original line number Diff line number Diff line Loading @@ -830,6 +830,97 @@ public class ImsResolverTest extends ImsTestBase { verify(deviceController).changeImsServiceFeatures(deviceFeatureSet); } /** * If a misbehaving ImsService returns null for the Binder connection when we perform a dynamic * feature query, verify we never perform a full bind for any features. */ @Test @SmallTest public void testPermanentBindFailureDuringFeatureQuery() throws RemoteException { setupResolver(1/*numSlots*/); List<ResolveInfo> info = new ArrayList<>(); Set<String> deviceFeatures = new HashSet<>(); deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE); deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE); // Set the carrier override package for slot 0 setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName()); HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>(); // Carrier service doesn't support the voice feature. carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS)); // Use device default package, which will load the ImsService that the device provides info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true)); info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true)); setupPackageQuery(info); ImsServiceController deviceController = mock(ImsServiceController.class); ImsServiceController carrierController = mock(ImsServiceController.class); setImsServiceControllerFactory(deviceController, carrierController); startBindCarrierConfigAlreadySet(); // dynamic query results in a failure. setupDynamicQueryFeaturesFailure(TEST_CARRIER_DEFAULT_NAME, 1); // Verify that a bind never occurs for the carrier controller. verify(carrierController, never()).bind(any()); verify(carrierController, never()).unbind(); // Verify that all features are used to bind to the device ImsService since the carrier // ImsService failed to bind properly. HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet = convertToHashSet(deviceFeatures, 0); verify(deviceController).bind(deviceFeatureSet); verify(deviceController, never()).unbind(); assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName()); } /** * If a misbehaving ImsService returns null for the Binder connection when we perform bind, * verify the service is disconnected. */ @Test @SmallTest public void testPermanentBindFailureDuringBind() throws RemoteException { setupResolver(1/*numSlots*/); List<ResolveInfo> info = new ArrayList<>(); Set<String> deviceFeatures = new HashSet<>(); deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE); deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE); // Set the carrier override package for slot 0 setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName()); HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>(); // Carrier service doesn't support the voice feature. carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS)); // Use device default package, which will load the ImsService that the device provides info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true)); info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true)); setupPackageQuery(info); ImsServiceController deviceController = mock(ImsServiceController.class); ImsServiceController carrierController = mock(ImsServiceController.class); setImsServiceControllerFactory(deviceController, carrierController); startBindCarrierConfigAlreadySet(); setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1); // Verify that a bind never occurs for the carrier controller. verify(carrierController).bind(carrierFeatures); verify(carrierController, never()).unbind(); // Verify that all features that are not defined in the carrier override are bound in the // 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()); mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME); waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); verify(carrierController).unbind(); // Verify that the device ImsService features are changed to include the ones previously // taken by the carrier app. HashSet<ImsFeatureConfiguration.FeatureSlotPair> originalDeviceFeatureSet = convertToHashSet(deviceFeatures, 0); verify(deviceController).changeImsServiceFeatures(originalDeviceFeatureSet); } private void setupResolver(int numSlots) { when(mMockContext.getSystemService(eq(Context.CARRIER_CONFIG_SERVICE))).thenReturn( mMockCarrierConfigManager); Loading Loading @@ -944,6 +1035,18 @@ public class ImsResolverTest extends ImsTestBase { waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); } private void setupDynamicQueryFeaturesFailure(ComponentName name, int times) { // wait for schedule to happen waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); // ensure that startQuery was called when(mMockQueryManager.startQuery(any(ComponentName.class), any(String.class))) .thenReturn(true); verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class)); mDynamicQueryListener.onPermanentError(name); // wait for handling of onPermanentError waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); } public void packageChanged(String packageName) { // Tell the package manager that a new device feature is installed Intent addPackageIntent = new Intent(); Loading tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java +35 −4 Original line number Diff line number Diff line Loading @@ -294,6 +294,26 @@ public class ImsServiceControllerTest extends ImsTestBase { verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(2)); } /** * Ensures that imsServiceBindPermanentError is called when the binder returns null. */ @SmallTest @Test public void testBindServiceAndReturnedNull() throws RemoteException { HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>(); // Slot 1, MMTel testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1)); // Slot 1, RCS testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2)); bindAndNullServiceError(testFeatures); verify(mMockCallbacks, never()).imsServiceFeatureCreated(anyInt(), anyInt(), eq(mTestImsServiceController)); verify(mMockProxyCallbacks, never()).imsFeatureCreated(anyInt(), anyInt()); verify(mMockCallbacks).imsServiceBindPermanentError(eq(mTestComponentName)); } /** * Ensures ImsService and ImsResolver are notified when a feature is added. */ Loading Loading @@ -499,16 +519,27 @@ public class ImsServiceControllerTest extends ImsTestBase { verify(mMockContext, times(2)).bindService(any(), any(), anyInt()); } private void bindAndNullServiceError( HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures) { ServiceConnection connection = bindService(testFeatures); connection.onNullBinding(mTestComponentName); } private ServiceConnection bindAndConnectService( HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures) { ServiceConnection connection = bindService(testFeatures); IImsServiceController.Stub controllerStub = mock(IImsServiceController.Stub.class); when(controllerStub.queryLocalInterface(any())).thenReturn(mMockServiceControllerBinder); connection.onServiceConnected(mTestComponentName, controllerStub); return connection; } private ServiceConnection bindService( HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures) { ArgumentCaptor<ServiceConnection> serviceCaptor = ArgumentCaptor.forClass(ServiceConnection.class); assertTrue(mTestImsServiceController.bind(testFeatures)); verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt()); IImsServiceController.Stub controllerStub = mock(IImsServiceController.Stub.class); when(controllerStub.queryLocalInterface(any())).thenReturn(mMockServiceControllerBinder); serviceCaptor.getValue().onServiceConnected(mTestComponentName, controllerStub); return serviceCaptor.getValue(); } } Loading
src/java/com/android/internal/telephony/ims/ImsResolver.java +18 −2 Original line number Diff line number Diff line Loading @@ -481,6 +481,13 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal Log.w(TAG, "onError: " + name + "returned with an error result"); scheduleQueryForFeatures(name, DELAY_DYNAMIC_QUERY_MS); } @Override public void onPermanentError(ComponentName name) { Log.w(TAG, "onPermanentError: component=" + name); mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget(); } }; // Array index corresponds to slot Id associated with the service package name. Loading Loading @@ -840,8 +847,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } } // Remove the ImsService from the cache. At this point, the ImsService will have already been // killed. // Remove the ImsService from the cache. This may have been due to the ImsService being removed // from the device or was returning permanent errors when bound. // Called from the handler ONLY private boolean maybeRemovedImsService(String packageName) { ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName); Loading Loading @@ -1066,6 +1073,15 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal handleFeaturesChanged(controller.getComponentName(), config.getServiceFeatures()); } @Override public void imsServiceBindPermanentError(ComponentName name) { if (name == null) { return; } Log.w(TAG, "imsServiceBindPermanentError: component=" + name); mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget(); } /** * Determines if the features specified should cause a bind or keep a binding active to an * ImsService. Loading
src/java/com/android/internal/telephony/ims/ImsServiceController.java +41 −18 Original line number Diff line number Diff line Loading @@ -71,10 +71,9 @@ public class ImsServiceController { synchronized (mLock) { mIsBound = true; mIsBinding = false; try { Log.d(LOG_TAG, "ImsService(" + name + "): onServiceConnected with binder: " + service); if (service != null) { try { setServiceController(service); notifyImsServiceReady(); // create all associated features in the ImsService Loading @@ -92,7 +91,6 @@ public class ImsServiceController { } } } } @Override public void onServiceDisconnected(ComponentName name) { Loading @@ -111,10 +109,27 @@ public class ImsServiceController { mIsBound = false; } cleanupConnection(); // according to the docs, we should fully unbind before rebinding again. mContext.unbindService(mImsServiceConnection); Log.w(LOG_TAG, "ImsService(" + name + "): onBindingDied. Starting rebind..."); startDelayedRebindToService(); } @Override public void onNullBinding(ComponentName name) { Log.w(LOG_TAG, "ImsService(" + name + "): onNullBinding. Removing."); synchronized (mLock) { mIsBinding = false; mIsBound = false; } cleanupConnection(); if (mCallbacks != null) { // Will trigger an unbind. mCallbacks.imsServiceBindPermanentError(getComponentName()); } } // Does not clear features, just removes all active features. private void cleanupConnection() { cleanupAllFeatures(); cleanUpService(); Loading Loading @@ -151,6 +166,12 @@ public class ImsServiceController { */ void imsServiceFeaturesChanged(ImsFeatureConfiguration config, ImsServiceController controller); /** * Called by the ImsServiceController when there has been an error binding that is * not recoverable, such as the ImsService returning a null binder. */ void imsServiceBindPermanentError(ComponentName name); } /** Loading Loading @@ -385,6 +406,8 @@ public class ImsServiceController { removeImsServiceFeatureCallbacks(); Log.i(LOG_TAG, "Unbinding ImsService: " + mComponentName); mContext.unbindService(mImsServiceConnection); mIsBound = false; mIsBinding = false; cleanUpService(); } } Loading
src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java +16 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.telephony.ims.aidl.IImsServiceController; import android.telephony.ims.stub.ImsFeatureConfiguration; import android.util.Log; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; Loading Loading @@ -71,8 +72,9 @@ public class ImsServiceFeatureQueryManager { if (service != null) { queryImsFeatures(IImsServiceController.Stub.asInterface(service)); } else { Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null, cleaning up."); Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null."); cleanup(); mListener.onPermanentError(name); } } Loading @@ -91,7 +93,14 @@ public class ImsServiceFeatureQueryManager { mListener.onError(mName); return; } Set<ImsFeatureConfiguration.FeatureSlotPair> servicePairs = config.getServiceFeatures(); Set<ImsFeatureConfiguration.FeatureSlotPair> servicePairs; if (config == null) { // ensure that if the ImsService sent a null config, we return an empty feature // set to the ImsResolver. servicePairs = Collections.emptySet(); } else { servicePairs = config.getServiceFeatures(); } // Complete, remove from active queries and notify. cleanup(); mListener.onComplete(mName, servicePairs); Loading @@ -117,6 +126,11 @@ public class ImsServiceFeatureQueryManager { * Called when a query has failed and should be retried. */ void onError(ComponentName name); /** * Called when a query has failed due to a permanent error and should not be retried. */ void onPermanentError(ComponentName name); } // Maps an active ImsService query (by Package Name String) its query. Loading
tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java +103 −0 Original line number Diff line number Diff line Loading @@ -830,6 +830,97 @@ public class ImsResolverTest extends ImsTestBase { verify(deviceController).changeImsServiceFeatures(deviceFeatureSet); } /** * If a misbehaving ImsService returns null for the Binder connection when we perform a dynamic * feature query, verify we never perform a full bind for any features. */ @Test @SmallTest public void testPermanentBindFailureDuringFeatureQuery() throws RemoteException { setupResolver(1/*numSlots*/); List<ResolveInfo> info = new ArrayList<>(); Set<String> deviceFeatures = new HashSet<>(); deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE); deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE); // Set the carrier override package for slot 0 setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName()); HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>(); // Carrier service doesn't support the voice feature. carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS)); // Use device default package, which will load the ImsService that the device provides info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true)); info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true)); setupPackageQuery(info); ImsServiceController deviceController = mock(ImsServiceController.class); ImsServiceController carrierController = mock(ImsServiceController.class); setImsServiceControllerFactory(deviceController, carrierController); startBindCarrierConfigAlreadySet(); // dynamic query results in a failure. setupDynamicQueryFeaturesFailure(TEST_CARRIER_DEFAULT_NAME, 1); // Verify that a bind never occurs for the carrier controller. verify(carrierController, never()).bind(any()); verify(carrierController, never()).unbind(); // Verify that all features are used to bind to the device ImsService since the carrier // ImsService failed to bind properly. HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet = convertToHashSet(deviceFeatures, 0); verify(deviceController).bind(deviceFeatureSet); verify(deviceController, never()).unbind(); assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName()); } /** * If a misbehaving ImsService returns null for the Binder connection when we perform bind, * verify the service is disconnected. */ @Test @SmallTest public void testPermanentBindFailureDuringBind() throws RemoteException { setupResolver(1/*numSlots*/); List<ResolveInfo> info = new ArrayList<>(); Set<String> deviceFeatures = new HashSet<>(); deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE); deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE); // Set the carrier override package for slot 0 setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName()); HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>(); // Carrier service doesn't support the voice feature. carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS)); // Use device default package, which will load the ImsService that the device provides info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true)); info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true)); setupPackageQuery(info); ImsServiceController deviceController = mock(ImsServiceController.class); ImsServiceController carrierController = mock(ImsServiceController.class); setImsServiceControllerFactory(deviceController, carrierController); startBindCarrierConfigAlreadySet(); setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1); // Verify that a bind never occurs for the carrier controller. verify(carrierController).bind(carrierFeatures); verify(carrierController, never()).unbind(); // Verify that all features that are not defined in the carrier override are bound in the // 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()); mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME); waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); verify(carrierController).unbind(); // Verify that the device ImsService features are changed to include the ones previously // taken by the carrier app. HashSet<ImsFeatureConfiguration.FeatureSlotPair> originalDeviceFeatureSet = convertToHashSet(deviceFeatures, 0); verify(deviceController).changeImsServiceFeatures(originalDeviceFeatureSet); } private void setupResolver(int numSlots) { when(mMockContext.getSystemService(eq(Context.CARRIER_CONFIG_SERVICE))).thenReturn( mMockCarrierConfigManager); Loading Loading @@ -944,6 +1035,18 @@ public class ImsResolverTest extends ImsTestBase { waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); } private void setupDynamicQueryFeaturesFailure(ComponentName name, int times) { // wait for schedule to happen waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); // ensure that startQuery was called when(mMockQueryManager.startQuery(any(ComponentName.class), any(String.class))) .thenReturn(true); verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class)); mDynamicQueryListener.onPermanentError(name); // wait for handling of onPermanentError waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT); } public void packageChanged(String packageName) { // Tell the package manager that a new device feature is installed Intent addPackageIntent = new Intent(); Loading
tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java +35 −4 Original line number Diff line number Diff line Loading @@ -294,6 +294,26 @@ public class ImsServiceControllerTest extends ImsTestBase { verify(mMockProxyCallbacks).imsFeatureRemoved(eq(1), eq(2)); } /** * Ensures that imsServiceBindPermanentError is called when the binder returns null. */ @SmallTest @Test public void testBindServiceAndReturnedNull() throws RemoteException { HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>(); // Slot 1, MMTel testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 1)); // Slot 1, RCS testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, 2)); bindAndNullServiceError(testFeatures); verify(mMockCallbacks, never()).imsServiceFeatureCreated(anyInt(), anyInt(), eq(mTestImsServiceController)); verify(mMockProxyCallbacks, never()).imsFeatureCreated(anyInt(), anyInt()); verify(mMockCallbacks).imsServiceBindPermanentError(eq(mTestComponentName)); } /** * Ensures ImsService and ImsResolver are notified when a feature is added. */ Loading Loading @@ -499,16 +519,27 @@ public class ImsServiceControllerTest extends ImsTestBase { verify(mMockContext, times(2)).bindService(any(), any(), anyInt()); } private void bindAndNullServiceError( HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures) { ServiceConnection connection = bindService(testFeatures); connection.onNullBinding(mTestComponentName); } private ServiceConnection bindAndConnectService( HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures) { ServiceConnection connection = bindService(testFeatures); IImsServiceController.Stub controllerStub = mock(IImsServiceController.Stub.class); when(controllerStub.queryLocalInterface(any())).thenReturn(mMockServiceControllerBinder); connection.onServiceConnected(mTestComponentName, controllerStub); return connection; } private ServiceConnection bindService( HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures) { ArgumentCaptor<ServiceConnection> serviceCaptor = ArgumentCaptor.forClass(ServiceConnection.class); assertTrue(mTestImsServiceController.bind(testFeatures)); verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt()); IImsServiceController.Stub controllerStub = mock(IImsServiceController.Stub.class); when(controllerStub.queryLocalInterface(any())).thenReturn(mMockServiceControllerBinder); serviceCaptor.getValue().onServiceConnected(mTestComponentName, controllerStub); return serviceCaptor.getValue(); } }