• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.ims;
18 
19 import static junit.framework.Assert.assertEquals;
20 import static junit.framework.Assert.assertNotNull;
21 import static junit.framework.Assert.assertNull;
22 import static junit.framework.Assert.assertTrue;
23 import static junit.framework.TestCase.assertFalse;
24 
25 import static org.mockito.ArgumentMatchers.argThat;
26 import static org.mockito.Matchers.any;
27 import static org.mockito.Matchers.anyInt;
28 import static org.mockito.Matchers.eq;
29 import static org.mockito.Mockito.atLeastOnce;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.never;
32 import static org.mockito.Mockito.times;
33 import static org.mockito.Mockito.verify;
34 import static org.mockito.Mockito.when;
35 
36 import android.Manifest;
37 import android.content.BroadcastReceiver;
38 import android.content.ComponentName;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.pm.PackageManager;
42 import android.content.pm.ResolveInfo;
43 import android.content.pm.ServiceInfo;
44 import android.net.Uri;
45 import android.os.Bundle;
46 import android.os.Looper;
47 import android.os.PersistableBundle;
48 import android.os.RemoteException;
49 import android.os.UserManager;
50 import android.telephony.CarrierConfigManager;
51 import android.telephony.TelephonyManager;
52 import android.telephony.ims.ImsService;
53 import android.telephony.ims.feature.ImsFeature;
54 import android.telephony.ims.stub.ImsFeatureConfiguration;
55 import android.test.suitebuilder.annotation.SmallTest;
56 import android.testing.AndroidTestingRunner;
57 import android.testing.TestableLooper;
58 import android.util.ArrayMap;
59 import android.util.ArraySet;
60 import android.util.SparseIntArray;
61 
62 import com.android.ims.ImsFeatureBinderRepository;
63 import com.android.internal.telephony.PhoneConfigurationManager;
64 
65 import org.junit.After;
66 import org.junit.Before;
67 import org.junit.Test;
68 import org.junit.runner.RunWith;
69 import org.mockito.ArgumentCaptor;
70 
71 import java.util.ArrayList;
72 import java.util.HashSet;
73 import java.util.List;
74 import java.util.Map;
75 import java.util.Objects;
76 import java.util.Set;
77 import java.util.stream.Collectors;
78 
79 /**
80  * Unit tests for ImsResolver
81  */
82 @RunWith(AndroidTestingRunner.class)
83 @TestableLooper.RunWithLooper
84 public class ImsResolverTest extends ImsTestBase {
85 
86     private static final ComponentName TEST_DEVICE_DEFAULT_NAME = new ComponentName("TestDevicePkg",
87             "DeviceImsService");
88     private static final ComponentName TEST_DEVICE2_DEFAULT_NAME = new ComponentName(
89             "TestDevicePkg2", "DeviceImsService2");
90     private static final ComponentName TEST_CARRIER_DEFAULT_NAME = new ComponentName(
91             "TestCarrierPkg", "CarrierImsService");
92     private static final ComponentName TEST_CARRIER_2_DEFAULT_NAME = new ComponentName(
93             "TestCarrier2Pkg", "Carrier2ImsService");
94 
95     private static final int NUM_MAX_SLOTS = 2;
96     private static final String TAG = ImsResolverTest.class.getSimpleName();
97 
98     // Mocked classes
99     Context mMockContext;
100     PackageManager mMockPM;
101     ImsResolver.SubscriptionManagerProxy mTestSubscriptionManagerProxy;
102     ImsResolver.TelephonyManagerProxy mTestTelephonyManagerProxy;
103     CarrierConfigManager mMockCarrierConfigManager;
104     UserManager mMockUserManager;
105     ImsResolver.ImsDynamicQueryManagerFactory mMockQueryManagerFactory;
106     ImsServiceFeatureQueryManager mMockQueryManager;
107     ImsFeatureBinderRepository mMockRepo;
108 
109     private ImsResolver mTestImsResolver;
110     private BroadcastReceiver mTestPackageBroadcastReceiver;
111     private BroadcastReceiver mTestCarrierConfigReceiver;
112     private BroadcastReceiver mTestBootCompleteReceiver;
113     private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener;
114     private PersistableBundle[] mCarrierConfigs;
115 
116     @Before
117     @Override
setUp()118     public void setUp() throws Exception {
119         super.setUp();
120         mMockContext = mock(Context.class);
121         mMockPM = mock(PackageManager.class);
122         mTestSubscriptionManagerProxy = mock(ImsResolver.SubscriptionManagerProxy.class);
123         mTestTelephonyManagerProxy = mock(ImsResolver.TelephonyManagerProxy.class);
124         mMockCarrierConfigManager = mock(CarrierConfigManager.class);
125         mMockUserManager = mock(UserManager.class);
126         mMockQueryManagerFactory = mock(ImsResolver.ImsDynamicQueryManagerFactory.class);
127         mMockQueryManager = mock(ImsServiceFeatureQueryManager.class);
128         mMockRepo = mock(ImsFeatureBinderRepository.class);
129     }
130 
131     @After
132     @Override
tearDown()133     public void tearDown() throws Exception {
134         mTestImsResolver.destroy();
135         mTestImsResolver = null;
136         mTestPackageBroadcastReceiver = null;
137         mTestCarrierConfigReceiver = null;
138         mTestBootCompleteReceiver = null;
139         mDynamicQueryListener = null;
140         mCarrierConfigs = null;
141         super.tearDown();
142     }
143 
144     /**
145      * Add a package to the package manager and make sure it is added to the cache of available
146      * ImsServices in the ImsResolver.
147      */
148     @Test
149     @SmallTest
testAddDevicePackageToCache()150     public void testAddDevicePackageToCache() {
151         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
152                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
153         HashSet<String> features = new HashSet<>();
154         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
155         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
156         features.add(ImsResolver.METADATA_RCS_FEATURE);
157         setupPackageQuery(TEST_DEVICE_DEFAULT_NAME, features, true);
158         setupController();
159 
160         // Complete package manager lookup and cache.
161         startBindCarrierConfigAlreadySet();
162 
163         ImsResolver.ImsServiceInfo testCachedService =
164                 mTestImsResolver.getImsServiceInfoFromCache(
165                         TEST_DEVICE_DEFAULT_NAME.getPackageName());
166         assertNotNull(testCachedService);
167         assertTrue(isImsServiceInfoEqual(TEST_DEVICE_DEFAULT_NAME, features, testCachedService));
168     }
169 
170     /**
171      * Add a carrier ImsService to the package manager and make sure the features declared here are
172      * ignored. We should only allow dynamic query for these services.
173      */
174     @Test
175     @SmallTest
testAddCarrierPackageToCache()176     public void testAddCarrierPackageToCache() {
177         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
178                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
179         HashSet<String> features = new HashSet<>();
180         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
181         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
182         features.add(ImsResolver.METADATA_RCS_FEATURE);
183         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
184         setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, features, true);
185         setupController();
186 
187         // Complete package manager lookup and cache.
188         startBindCarrierConfigAlreadySet();
189 
190         ImsResolver.ImsServiceInfo testCachedService =
191                 mTestImsResolver.getImsServiceInfoFromCache(
192                         TEST_CARRIER_DEFAULT_NAME.getPackageName());
193         assertNotNull(testCachedService);
194         // none of the manifest features we added above should be reported for carrier package.
195         assertTrue(testCachedService.getSupportedFeatures().isEmpty());
196         // we should report that the service does not use metadata to report features.
197         assertFalse(testCachedService.featureFromMetadata);
198     }
199 
200     /**
201      * Add a device ImsService and ensure that querying ImsResolver to see if an ImsService is
202      * configured succeeds.
203      */
204     @Test
205     @SmallTest
testIsDeviceImsServiceConfigured()206     public void testIsDeviceImsServiceConfigured() throws Exception {
207         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
208                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
209         HashSet<String> features = new HashSet<>();
210         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
211         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
212         features.add(ImsResolver.METADATA_RCS_FEATURE);
213         setupPackageQuery(TEST_DEVICE_DEFAULT_NAME, features, true);
214         setupController();
215 
216         // Complete package manager lookup and cache.
217         startBindCarrierConfigAlreadySet();
218 
219         // device package name should be returned for both features.
220         final Boolean[] isConfigured = new Boolean[1];
221         isConfigured[0] = mTestImsResolver.isImsServiceConfiguredForFeature(0,
222                 ImsFeature.FEATURE_MMTEL);
223         assertTrue(isConfigured[0]);
224         isConfigured[0] = mTestImsResolver.isImsServiceConfiguredForFeature(0,
225                 ImsFeature.FEATURE_RCS);
226         assertTrue(isConfigured[0]);
227     }
228 
229     /**
230      * Add a device ImsService and ensure that querying the configured ImsService for all features
231      * reports the device ImsService.
232      */
233     @Test
234     @SmallTest
testGetConfiguredImsServiceDevice()235     public void testGetConfiguredImsServiceDevice() throws Exception {
236         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
237                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
238         HashSet<String> features = new HashSet<>();
239         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
240         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
241         features.add(ImsResolver.METADATA_RCS_FEATURE);
242         setupPackageQuery(TEST_DEVICE_DEFAULT_NAME, features, true);
243         setupController();
244 
245         // Complete package manager lookup and cache.
246         startBindCarrierConfigAlreadySet();
247 
248         // device package name should be returned for both features.
249         final String[] packageName = new String[1];
250         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
251                 ImsFeature.FEATURE_MMTEL);
252         assertEquals(TEST_DEVICE_DEFAULT_NAME.getPackageName(), packageName[0]);
253         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
254                 ImsFeature.FEATURE_RCS);
255         assertEquals(TEST_DEVICE_DEFAULT_NAME.getPackageName(), packageName[0]);
256     }
257 
258     /**
259      * In the case that there is no device or carrier ImsService found, we return null for
260      * configuration queries.
261      */
262     @Test
263     @SmallTest
testGetConfiguredImsServiceNoDeviceOrCarrier()264     public void testGetConfiguredImsServiceNoDeviceOrCarrier() throws Exception {
265         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
266                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
267         // package query returns null
268         setupController();
269         // Complete package manager lookup and cache.
270         startBindCarrierConfigAlreadySet();
271 
272         // device package name should be returned for both features.
273         final String[] packageName = new String[1];
274         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
275                 ImsFeature.FEATURE_MMTEL);
276         assertNull(packageName[0]);
277         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
278                 ImsFeature.FEATURE_RCS);
279         assertNull(packageName[0]);
280     }
281 
282     /**
283      * In the case that there is no device or carrier ImsService configured, we return null for
284      * configuration queries.
285      */
286     @Test
287     @SmallTest
testGetConfiguredImsServiceNoDeviceConfig()288     public void testGetConfiguredImsServiceNoDeviceConfig() throws Exception {
289         // device configuration for MMTEL and RCS is null
290         setupResolver(1 /*numSlots*/, null, null);
291         HashSet<String> features = new HashSet<>();
292         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
293         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
294         features.add(ImsResolver.METADATA_RCS_FEATURE);
295         // ImsService query does report a device ImsService
296         setupPackageQuery(TEST_DEVICE_DEFAULT_NAME, features, true);
297         setupController();
298         // Complete package manager lookup and cache.
299         startBindCarrierConfigAlreadySet();
300 
301         // device package name should be returned for both features.
302         final String[] packageName = new String[1];
303         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
304                 ImsFeature.FEATURE_MMTEL);
305         assertNull(packageName[0]);
306         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
307                 ImsFeature.FEATURE_RCS);
308         assertNull(packageName[0]);
309     }
310 
311     /**
312      * Add a device and carrier ImsService and ensure that querying the configured ImsService for
313      * all features reports the carrier ImsService and not device.
314      */
315     @Test
316     @SmallTest
testGetConfiguredImsServiceCarrier()317     public void testGetConfiguredImsServiceCarrier() throws Exception {
318         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
319                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
320         HashSet<String> features = new HashSet<>();
321         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
322         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
323         features.add(ImsResolver.METADATA_RCS_FEATURE);
324         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
325         List<ResolveInfo> info = new ArrayList<>();
326         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
327         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
328         setupPackageQuery(info);
329         setupController();
330 
331         // Complete package manager lookup and cache.
332         startBindCarrierConfigAlreadySet();
333         // Setup the carrier features and response.
334         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
335         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
336                 ImsFeature.FEATURE_MMTEL));
337         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
338                 ImsFeature.FEATURE_RCS));
339         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
340 
341         // carrier package name should be returned for both features.
342         final String[] packageName = new String[1];
343         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
344                 ImsFeature.FEATURE_MMTEL);
345         assertEquals(TEST_CARRIER_DEFAULT_NAME.getPackageName(), packageName[0]);
346         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
347                 ImsFeature.FEATURE_RCS);
348         assertEquals(TEST_CARRIER_DEFAULT_NAME.getPackageName(), packageName[0]);
349     }
350 
351     /**
352      * Add a device ImsService and ensure that querying the configured ImsService for all features
353      * reports the device ImsService though there is a configuration for carrier (but no cached
354      * ImsService).
355      */
356     @Test
357     @SmallTest
testGetConfiguredImsServiceCarrierDevice()358     public void testGetConfiguredImsServiceCarrierDevice() throws Exception {
359         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
360                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
361         HashSet<String> features = new HashSet<>();
362         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
363         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
364         features.add(ImsResolver.METADATA_RCS_FEATURE);
365         // Carrier service is configured
366         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
367         List<ResolveInfo> info = new ArrayList<>();
368         // Carrier ImsService is not found during package query.
369         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
370         setupPackageQuery(info);
371         setupController();
372 
373         // Complete package manager lookup and cache.
374         startBindCarrierConfigAlreadySet();
375 
376         final String[] packageName = new String[1];
377         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
378                 ImsFeature.FEATURE_MMTEL);
379         assertEquals(TEST_DEVICE_DEFAULT_NAME.getPackageName(), packageName[0]);
380         packageName[0] = mTestImsResolver.getConfiguredImsServicePackageName(0,
381                 ImsFeature.FEATURE_RCS);
382         assertEquals(TEST_DEVICE_DEFAULT_NAME.getPackageName(), packageName[0]);
383     }
384 
385     /**
386      * Set the carrier config override value and ensure that ImsResolver calls .bind on that
387      * package name with the correct ImsFeatures.
388      */
389     @Test
390     @SmallTest
testCarrierPackageBind()391     public void testCarrierPackageBind() throws RemoteException {
392         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
393                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
394         // Setup the carrier features
395         HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = new HashSet<>();
396         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_MMTEL));
397         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
398         // Set CarrierConfig default package name and make it available as the CarrierConfig.
399         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
400         setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
401         ImsServiceController controller = setupController();
402 
403         // Start bind to carrier service
404         startBindCarrierConfigAlreadySet();
405         // setup features response
406         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
407 
408         ArgumentCaptor<SparseIntArray> arrayCaptor =
409                         ArgumentCaptor.forClass(SparseIntArray.class);
410         verify(controller).bind(eq(features), arrayCaptor.capture());
411         SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
412         SparseIntArray compareMap = new SparseIntArray();
413         compareMap.put(0, 0);
414         //ensure that slotIdToSubIdMap was delivered properly.
415         for (int i = 0; i < slotIdToSubIdMap.size(); i++) {
416             assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
417         }
418         verify(controller, never()).unbind();
419         assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
420     }
421 
422     /**
423      * Set the carrier config override value to many separate services for MMTEL and RCS and ensure
424      * that ImsResolver calls .bind on those package names with the correct ImsFeatures.
425      */
426     @Test
427     @SmallTest
testDeviceCarrierPackageBindMultipleServices()428     public void testDeviceCarrierPackageBindMultipleServices() throws RemoteException {
429         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
430                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
431         // Setup the carrier features: carrier 1 - MMTEL, slot 0; carrier 2 RCS, slot 0
432         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featuresMmTel = new HashSet<>();
433         featuresMmTel.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_MMTEL));
434         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featuresRcs = new HashSet<>();
435         featuresRcs.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
436         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featuresAll = new HashSet<>(featuresMmTel);
437         featuresAll.addAll(featuresRcs);
438         // Setup the device features: MMTEL, RCS on slot 0,1
439         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featuresDevice = new HashSet<>();
440         featuresDevice.add(new ImsFeatureConfiguration.FeatureSlotPair(1,
441                 ImsFeature.FEATURE_MMTEL));
442         featuresDevice.add(new ImsFeatureConfiguration.FeatureSlotPair(1, ImsFeature.FEATURE_RCS));
443         // Set CarrierConfig default package name and make it available as the CarrierConfig.
444         setConfigCarrierStringMmTel(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
445         setConfigCarrierStringRcs(0, TEST_CARRIER_2_DEFAULT_NAME.getPackageName());
446         Set<String> deviceFeatures = new ArraySet<>();
447         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
448         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
449         List<ResolveInfo> info = new ArrayList<>();
450         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
451         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
452         info.add(getResolveInfo(TEST_CARRIER_2_DEFAULT_NAME, new HashSet<>(), true));
453         setupPackageQuery(info);
454         ImsServiceController deviceController = mock(ImsServiceController.class);
455         ImsServiceController carrierController1 = mock(ImsServiceController.class);
456         ImsServiceController carrierController2 = mock(ImsServiceController.class);
457         setImsServiceControllerFactory(deviceController, carrierController1, carrierController2);
458 
459         // Start bind to carrier service
460         startBindCarrierConfigAlreadySet();
461         // setup features response
462         // emulate mMockQueryManager returning information about pending queries.
463         when(mMockQueryManager.isQueryInProgress()).thenReturn(true);
464         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, featuresAll, 1);
465         when(mMockQueryManager.isQueryInProgress()).thenReturn(false);
466         setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, featuresAll, 1);
467 
468         verify(deviceController).bind(eq(featuresDevice), any(SparseIntArray.class));
469         verify(deviceController, never()).unbind();
470         verify(carrierController1).bind(eq(featuresMmTel), any(SparseIntArray.class));
471         verify(carrierController1, never()).unbind();
472         verify(carrierController2).bind(eq(featuresRcs), any(SparseIntArray.class));
473         verify(carrierController2, never()).unbind();
474         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController1.getComponentName());
475         assertEquals(TEST_CARRIER_2_DEFAULT_NAME, carrierController2.getComponentName());
476     }
477 
478     /**
479      * Set the carrier config override value to two separate services for MMTEL and RCS and ensure
480      * that ImsResolver calls .bind on those package names with the correct ImsFeatures.
481      */
482     @Test
483     @SmallTest
testCarrierPackageBindOneConfigTwoSupport()484     public void testCarrierPackageBindOneConfigTwoSupport() throws RemoteException {
485         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
486                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
487         // Setup the carrier features
488         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featuresMmTel = new HashSet<>();
489         featuresMmTel.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_MMTEL));
490         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featuresRcs = new HashSet<>();
491         featuresRcs.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
492         featuresRcs.add(new ImsFeatureConfiguration.FeatureSlotPair(1, ImsFeature.FEATURE_RCS));
493         HashSet<ImsFeatureConfiguration.FeatureSlotPair> allFeatures = new HashSet<>(featuresMmTel);
494         allFeatures.addAll(featuresRcs);
495         // Set CarrierConfig default package name and make it available as the CarrierConfig.
496         setConfigCarrierStringMmTel(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
497         // TEST_CARRIER_DEFAULT_NAME isnt configured for MMTEL on slot 1.
498         featuresMmTel.remove(new ImsFeatureConfiguration.FeatureSlotPair(1,
499                 ImsFeature.FEATURE_MMTEL));
500         setConfigCarrierStringRcs(0, TEST_CARRIER_2_DEFAULT_NAME.getPackageName());
501         setConfigCarrierStringRcs(1, TEST_CARRIER_2_DEFAULT_NAME.getPackageName());
502         List<ResolveInfo> info = new ArrayList<>();
503         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
504         info.add(getResolveInfo(TEST_CARRIER_2_DEFAULT_NAME, new HashSet<>(), true));
505         setupPackageQuery(info);
506         ImsServiceController deviceController = mock(ImsServiceController.class);
507         ImsServiceController carrierController1 = mock(ImsServiceController.class);
508         ImsServiceController carrierController2 = mock(ImsServiceController.class);
509         setImsServiceControllerFactory(deviceController, carrierController1, carrierController2);
510 
511         // Start bind to carrier service
512         startBindCarrierConfigAlreadySet();
513         // setup features response
514         // emulate mMockQueryManager returning information about pending queries.
515         when(mMockQueryManager.isQueryInProgress()).thenReturn(true);
516         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, allFeatures, 1);
517         when(mMockQueryManager.isQueryInProgress()).thenReturn(false);
518         setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, allFeatures, 1);
519 
520         verify(deviceController, never()).bind(any(), any(SparseIntArray.class));
521         verify(deviceController, never()).unbind();
522         verify(carrierController1).bind(eq(featuresMmTel), any(SparseIntArray.class));
523         verify(carrierController1, never()).unbind();
524         verify(carrierController2).bind(eq(featuresRcs), any(SparseIntArray.class));
525         verify(carrierController2, never()).unbind();
526         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController1.getComponentName());
527         assertEquals(TEST_CARRIER_2_DEFAULT_NAME, carrierController2.getComponentName());
528     }
529 
530     /**
531      * Creates a carrier ImsService that defines FEATURE_EMERGENCY_MMTEL and ensure that the
532      * controller sets this capability.
533      */
534     @Test
535     @SmallTest
testCarrierPackageBindWithEmergencyCalling()536     public void testCarrierPackageBindWithEmergencyCalling() throws RemoteException {
537         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
538                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
539         // Set CarrierConfig default package name and make it available to the package manager
540         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
541         HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = new HashSet<>();
542         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
543                 ImsFeature.FEATURE_EMERGENCY_MMTEL));
544         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_MMTEL));
545         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
546         setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
547         ImsServiceController controller = setupController();
548 
549         startBindCarrierConfigAlreadySet();
550         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
551 
552         verify(controller).bind(eq(features), any(SparseIntArray.class));
553         verify(controller, never()).unbind();
554         assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
555     }
556 
557     /**
558      * Creates a carrier ImsService that defines FEATURE_EMERGENCY_MMTEL but not FEATURE_MMTEL and
559      * ensure that the controller doesn't set FEATURE_EMERGENCY_MMTEL.
560      */
561     @Test
562     @SmallTest
testCarrierPackageBindWithEmergencyButNotMmtel()563     public void testCarrierPackageBindWithEmergencyButNotMmtel() throws RemoteException {
564         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
565                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
566         // Set CarrierConfig default package name and make it available to the package manager
567         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
568         HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = new HashSet<>();
569         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
570                 ImsFeature.FEATURE_EMERGENCY_MMTEL));
571         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
572         setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
573         ImsServiceController controller = setupController();
574 
575         startBindCarrierConfigAlreadySet();
576         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
577 
578         // We will not bind with FEATURE_EMERGENCY_MMTEL
579         features.remove(new ImsFeatureConfiguration.FeatureSlotPair(0,
580                 ImsFeature.FEATURE_EMERGENCY_MMTEL));
581         verify(controller).bind(eq(features), any(SparseIntArray.class));
582         verify(controller, never()).unbind();
583         assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
584     }
585 
586     /**
587      * Ensure enabling and disabling IMS only happens one time per controller.
588      */
589     @Test
590     @SmallTest
testEnableDisableImsDedupe()591     public void testEnableDisableImsDedupe() {
592         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
593                 TEST_DEVICE2_DEFAULT_NAME.getPackageName());
594         List<ResolveInfo> info = new ArrayList<>();
595         Set<String> featuresController1 = new HashSet<>();
596         featuresController1.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
597         featuresController1.add(ImsResolver.METADATA_MMTEL_FEATURE);
598         Set<String> featuresController2 = new HashSet<>();
599         featuresController2.add(ImsResolver.METADATA_RCS_FEATURE);
600         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, featuresController1, true));
601         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, featuresController2, true));
602         setupPackageQuery(info);
603         ImsServiceController deviceController1 = mock(ImsServiceController.class);
604         ImsServiceController deviceController2 = mock(ImsServiceController.class);
605         setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
606         // Bind using default features
607         startBindNoCarrierConfig(1);
608         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
609                 convertToHashSet(featuresController1, 0);
610         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
611                 convertToHashSet(featuresController2, 0);
612         verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
613         verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
614         // simulate ImsServiceController binding and setup
615         mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_EMERGENCY_MMTEL,
616                 deviceController1);
617         mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_MMTEL, deviceController1);
618         mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_RCS, deviceController2);
619 
620         mTestImsResolver.enableIms(0 /*slotId*/);
621         // Verify enableIms is only called once per controller.
622         verify(deviceController1).enableIms(eq(0), eq(0));
623         verify(deviceController2).enableIms(eq(0), eq(0));
624 
625         mTestImsResolver.disableIms(0 /*slotId*/);
626         // Verify disableIms is only called once per controller.
627         verify(deviceController1).disableIms(eq(0), eq(0));
628         verify(deviceController2).disableIms(eq(0), eq(0));
629     }
630 
631     /**
632      * Creates a carrier ImsService that does not report FEATURE_EMERGENCY_MMTEL and then update the
633      * ImsService to define it. Ensure that the controller sets this capability once enabled.
634      */
635     @Test
636     @SmallTest
testCarrierPackageChangeEmergencyCalling()637     public void testCarrierPackageChangeEmergencyCalling() throws RemoteException {
638         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
639                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
640         // Set CarrierConfig default package name and make it available to the package manager
641         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
642         HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = new HashSet<>();
643         features.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_MMTEL));
644         setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
645         ImsServiceController controller = setupController();
646 
647         // Bind without emergency calling
648         startBindCarrierConfigAlreadySet();
649         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
650         verify(controller).bind(eq(features), any(SparseIntArray.class));
651         verify(controller, never()).unbind();
652         assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
653 
654         packageChanged(TEST_CARRIER_DEFAULT_NAME.getPackageName());
655         HashSet<ImsFeatureConfiguration.FeatureSlotPair> newFeatures = new HashSet<>();
656         newFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
657                 ImsFeature.FEATURE_MMTEL));
658         newFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
659                 ImsFeature.FEATURE_EMERGENCY_MMTEL));
660         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, newFeatures, 2);
661 
662         //Verify new feature is added to the carrier override.
663         // add all features for slot 0
664         verify(controller, atLeastOnce()).changeImsServiceFeatures(eq(newFeatures),
665                 any(SparseIntArray.class));
666     }
667 
668     /**
669      * Ensure that no ImsService is bound if there is no carrier or device package explicitly set.
670      */
671     @Test
672     @SmallTest
testDontBindWhenNullCarrierPackage()673     public void testDontBindWhenNullCarrierPackage() throws RemoteException {
674         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
675                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
676         setupPackageQuery(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true);
677         ImsServiceController controller = setupController();
678 
679         // Set the CarrierConfig string to null so that ImsResolver will not bind to the available
680         // Services
681         setConfigCarrierStringMmTelRcs(0, null);
682         startBindCarrierConfigAlreadySet();
683 
684         processAllMessages();
685         verify(mMockQueryManager, never()).startQuery(any(), any());
686         verify(controller, never()).bind(any(), any(SparseIntArray.class));
687         verify(controller, never()).unbind();
688     }
689 
690     /**
691      * Test that the ImsService corresponding to the default device ImsService package name is
692      * bound.
693      */
694     @Test
695     @SmallTest
testDevicePackageBind()696     public void testDevicePackageBind() throws RemoteException {
697         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
698                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
699         List<ResolveInfo> info = new ArrayList<>();
700         Set<String> features = new HashSet<>();
701         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
702         features.add(ImsResolver.METADATA_RCS_FEATURE);
703         // Use device default package, which will load the ImsService that the device provides
704         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
705         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
706         setupPackageQuery(info);
707         ImsServiceController controller = setupController();
708 
709 
710         startBindNoCarrierConfig(1);
711         processAllMessages();
712 
713         // There is no carrier override set, so make sure that the ImsServiceController binds
714         // to all SIMs.
715         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
716         ArgumentCaptor<SparseIntArray> arrayCaptor =
717                         ArgumentCaptor.forClass(SparseIntArray.class);
718         verify(controller).bind(eq(featureSet), arrayCaptor.capture());
719         SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
720         SparseIntArray compareMap = new SparseIntArray();
721         compareMap.put(0, 0);
722         //ensure that slotIdToSubIdMap was delivered properly.
723         for (int i = 0; i < slotIdToSubIdMap.size(); i++) {
724             assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
725         }
726 
727         verify(controller, never()).unbind();
728         verify(mMockQueryManager, never()).startQuery(any(), any());
729         assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
730     }
731 
732     /**
733      * Test that the ImsService corresponding to the default device ImsService package name is
734      * bound and when there is a configuration change from two SIMs to one, the features are
735      * updated correctly.
736      */
737     @Test
738     @SmallTest
testDevicePackageBind_MsimToOneSim()739     public void testDevicePackageBind_MsimToOneSim() throws RemoteException {
740         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
741                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
742         List<ResolveInfo> info = new ArrayList<>();
743         Set<String> features = new HashSet<>();
744         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
745         features.add(ImsResolver.METADATA_RCS_FEATURE);
746         // Use device default package, which will load the ImsService that the device provides
747         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
748         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
749         setupPackageQuery(info);
750         ImsServiceController controller = setupController();
751 
752 
753         startBindNoCarrierConfig(1);
754         processAllMessages();
755 
756         // There is no carrier override set, so make sure that the ImsServiceController binds
757         // to all SIMs.
758         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
759         featureSet.addAll(convertToHashSet(features, 1));
760         ArgumentCaptor<SparseIntArray> arrayCaptor =
761                         ArgumentCaptor.forClass(SparseIntArray.class);
762         verify(controller).bind(eq(featureSet), arrayCaptor.capture());
763         SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
764         assertEquals(slotIdToSubIdMap.size(), 2);
765         SparseIntArray compareMap = new SparseIntArray();
766         compareMap.put(0, 0);
767         compareMap.put(1, -1);
768         //ensure that slotIdToSubIdMap was delivered properly.
769         for (int i = 0; i < slotIdToSubIdMap.size(); i++) {
770             assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
771         }
772         verify(controller, never()).unbind();
773         verify(mMockQueryManager, never()).startQuery(any(), any());
774         assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
775 
776         // Change number of SIMs and verify the features in the ImsServiceController are changed
777         // as well
778         PhoneConfigurationManager.notifyMultiSimConfigChange(1);
779         processAllMessages();
780         compareMap.delete(1);
781         featureSet = convertToHashSet(features, 0);
782         verify(controller).changeImsServiceFeatures(eq(featureSet), arrayCaptor.capture());
783         slotIdToSubIdMap = arrayCaptor.getValue();
784         assertEquals(slotIdToSubIdMap.size(), compareMap.size());
785         //ensure that slotIdToSubIdMap was delivered properly.
786         for (int i = 0; i < slotIdToSubIdMap.size(); i++) {
787             assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
788         }
789         verify(controller, never()).unbind();
790     }
791 
792     /**
793      * Test that the ImsService corresponding to the default device ImsService package name is
794      * bound and when there is a configuration change from one to two SIMs, the features are
795      * updated correctly.
796      */
797     @Test
798     @SmallTest
testDevicePackageBind_OneSimToMsim()799     public void testDevicePackageBind_OneSimToMsim() throws RemoteException {
800         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
801                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
802         List<ResolveInfo> info = new ArrayList<>();
803         Set<String> features = new HashSet<>();
804         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
805         features.add(ImsResolver.METADATA_RCS_FEATURE);
806         // Use device default package, which will load the ImsService that the device provides
807         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
808         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
809         setupPackageQuery(info);
810         ImsServiceController controller = setupController();
811 
812 
813         startBindNoCarrierConfig(1);
814         processAllMessages();
815 
816         // There is no carrier override set, so make sure that the ImsServiceController binds
817         // to all SIMs.
818         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
819 
820         ArgumentCaptor<SparseIntArray> arrayCaptor =
821                         ArgumentCaptor.forClass(SparseIntArray.class);
822         verify(controller).bind(eq(featureSet), arrayCaptor.capture());
823         SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
824         assertEquals(slotIdToSubIdMap.size(), 1);
825         SparseIntArray compareMap = new SparseIntArray();
826         compareMap.put(0, 0);
827         //ensure that slotIdToSubIdMap was delivered properly.
828         for (int i = 0; i < slotIdToSubIdMap.size(); i++) {
829             assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
830         }
831         verify(controller, never()).unbind();
832         verify(mMockQueryManager, never()).startQuery(any(), any());
833         assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
834 
835         // Change number of SIMs and verify the features in the ImsServiceController are changed
836         // as well
837         PhoneConfigurationManager.notifyMultiSimConfigChange(2);
838         // Carrier config changed should happen for slot 1 (independent of carrier ImsService)
839         sendCarrierConfigChanged(1, 1);
840         compareMap.put(1, 1);
841         featureSet.addAll(convertToHashSet(features, 1));
842         verify(controller).changeImsServiceFeatures(eq(featureSet), arrayCaptor.capture());
843         slotIdToSubIdMap = arrayCaptor.getValue();
844         assertEquals(slotIdToSubIdMap.size(), compareMap.size());
845         //ensure that slotIdToSubIdMap was delivered properly.
846         for (int i = 0; i < slotIdToSubIdMap.size(); i++) {
847             assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
848         }
849         verify(controller, never()).unbind();
850     }
851 
852     /**
853      * Test that the dynamic ims services are bound in the event that the user is not yet unlocked
854      * but the carrier config changed event is fired.
855      * @throws RemoteException
856      */
857     @Test
858     @SmallTest
testDeviceDynamicQueryBindsOnCarrierConfigChanged()859     public void testDeviceDynamicQueryBindsOnCarrierConfigChanged() throws RemoteException {
860         //Set package names with no features set in metadata
861         List<ResolveInfo> info = new ArrayList<>();
862         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, new HashSet<>(), true));
863         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, new HashSet<>(), true));
864         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
865         setupPackageQuery(info);
866 
867         //setupResolver
868         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
869                 TEST_DEVICE2_DEFAULT_NAME.getPackageName());
870 
871         //Set controllers
872         ImsServiceController deviceController = mock(ImsServiceController.class);
873         ImsServiceController deviceController2 = mock(ImsServiceController.class);
874         ImsServiceController carrierController = mock(ImsServiceController.class);
875 
876         Map<String, ImsServiceController> controllerMap = new ArrayMap<>();
877         controllerMap.put(TEST_DEVICE_DEFAULT_NAME.getPackageName(), deviceController);
878         controllerMap.put(TEST_DEVICE2_DEFAULT_NAME.getPackageName(), deviceController2);
879         controllerMap.put(TEST_CARRIER_DEFAULT_NAME.getPackageName(), carrierController);
880         setImsServiceControllerFactory(controllerMap);
881 
882         //Set features to device ims services
883         Set<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatures1 =
884                 convertToFeatureSlotPairs(0, ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE,
885                         ImsResolver.METADATA_MMTEL_FEATURE);
886 
887         Set<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatures2 =
888                 convertToFeatureSlotPairs(0, ImsResolver.METADATA_RCS_FEATURE);
889 
890         startBindNoCarrierConfig(1);
891         processAllMessages();
892         // ensure that startQuery was called
893         verify(mMockQueryManager, times(1)).startQuery(eq(TEST_DEVICE_DEFAULT_NAME),
894                 any(String.class));
895 
896         verify(mMockQueryManager, times(1)).startQuery(eq(TEST_DEVICE2_DEFAULT_NAME),
897                 any(String.class));
898 
899         mDynamicQueryListener.onComplete(TEST_DEVICE_DEFAULT_NAME, deviceFeatures1);
900         mDynamicQueryListener.onComplete(TEST_DEVICE2_DEFAULT_NAME, deviceFeatures2);
901         processAllMessages();
902 
903         verify(deviceController, times(2)).bind(eq(deviceFeatures1), any(SparseIntArray.class));
904         verify(deviceController2, times(1)).bind(eq(deviceFeatures2), any(SparseIntArray.class));
905     }
906 
907     /**
908      * Test that when a device and carrier override package are set, both ImsServices are bound.
909      * Verify that the carrier ImsService features are created and the device default features
910      * are created for all features that are not covered by the carrier ImsService. When the device
911      * configuration is changed from one SIM to MSIM, ensure that the capabilities are reflected.
912      */
913     @Test
914     @SmallTest
testDeviceAndCarrierPackageBind_OneSimToMsim()915     public void testDeviceAndCarrierPackageBind_OneSimToMsim() throws RemoteException {
916         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
917                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
918         List<ResolveInfo> info = new ArrayList<>();
919         // set device features to MMTEL, RCS
920         Set<String> deviceFeatures = new HashSet<>();
921         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
922         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
923         // Set the carrier override package for slot 0
924         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
925         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
926         // Carrier service only supports RCS on slot 0
927         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
928         // Use device default package, which will load the ImsService that the device provides
929         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
930         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
931         // Only return info if not using the compat argument
932         setupPackageQuery(info);
933         ImsServiceController deviceController = mock(ImsServiceController.class);
934         ImsServiceController carrierController = mock(ImsServiceController.class);
935         setImsServiceControllerFactory(deviceController, carrierController);
936 
937         startBindCarrierConfigAlreadySet();
938         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
939 
940         // Verify that all features that have been defined for the carrier override are bound
941         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
942         verify(carrierController, never()).unbind();
943         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
944         // Verify that all features that are not defined in the carrier override are bound in the
945         // device controller (including emergency voice for slot 0)
946         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
947                 convertToHashSet(deviceFeatures, 0);
948         deviceFeatureSet.removeAll(carrierFeatures);
949         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
950         verify(deviceController, never()).unbind();
951         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
952 
953         // Move to MSIM and verify the features in the ImsServiceController are changed as well
954         PhoneConfigurationManager.notifyMultiSimConfigChange(2);
955         setConfigCarrierStringMmTelRcs(1, TEST_CARRIER_DEFAULT_NAME.getPackageName());
956         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, ImsFeature.FEATURE_RCS));
957         // Assume that there is a CarrierConfig change that kicks off query to carrier service.
958         sendCarrierConfigChanged(1, 1);
959         setupDynamicQueryFeaturesMultiSim(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 2);
960         verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
961                         any(SparseIntArray.class));
962         deviceFeatureSet = convertToHashSet(deviceFeatures, 0);
963         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 1));
964         deviceFeatureSet.removeAll(carrierFeatures);
965         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
966                         any(SparseIntArray.class));
967         verify(deviceController, never()).unbind();
968     }
969 
970     /**
971      * Test that when a device and carrier override package are set, both ImsServices are bound.
972      * Verify that the carrier ImsService features are created and the device default features
973      * are created for all features that are not covered by the carrier ImsService. When the device
974      * configuration is changed from one SIM to MSIM, ensure that the capabilities are reflected.
975      */
976     @Test
977     @SmallTest
testDeviceAndCarrierPackageBind_MsimToOneSim()978     public void testDeviceAndCarrierPackageBind_MsimToOneSim() throws RemoteException {
979         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
980                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
981         List<ResolveInfo> info = new ArrayList<>();
982         // set device features to MMTEL, RCS
983         Set<String> deviceFeatures = new HashSet<>();
984         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
985         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
986         // Set the carrier override package for slot 0, slot 1 as RCS
987         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
988         setConfigCarrierStringMmTelRcs(1, TEST_CARRIER_DEFAULT_NAME.getPackageName());
989         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
990         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
991         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(1, ImsFeature.FEATURE_RCS));
992         // Use device default package, which will load the ImsService that the device provides
993         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
994         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
995         // Only return info if not using the compat argument
996         setupPackageQuery(info);
997         ImsServiceController deviceController = mock(ImsServiceController.class);
998         ImsServiceController carrierController = mock(ImsServiceController.class);
999         setImsServiceControllerFactory(deviceController, carrierController);
1000 
1001         startBindCarrierConfigAlreadySet();
1002         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1003 
1004         // Verify that all features that have been defined for the carrier override are bound
1005         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1006         verify(carrierController, never()).unbind();
1007         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
1008         // Verify that all features that are not defined in the carrier override are bound in the
1009         // device controller (including emergency voice for slot 0)
1010         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1011                 convertToHashSet(deviceFeatures, 0);
1012         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 1));
1013         deviceFeatureSet.removeAll(carrierFeatures);
1014         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
1015         verify(deviceController, never()).unbind();
1016         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
1017 
1018         // Move to single SIM and verify the features in the ImsServiceController are changed as
1019         // well.
1020         PhoneConfigurationManager.notifyMultiSimConfigChange(1);
1021         processAllMessages();
1022         carrierFeatures = new HashSet<>();
1023         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1024         verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
1025                 any(SparseIntArray.class));
1026         deviceFeatureSet = convertToHashSet(deviceFeatures, 0);
1027         deviceFeatureSet.removeAll(carrierFeatures);
1028         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
1029                 any(SparseIntArray.class));
1030         verify(deviceController, never()).unbind();
1031     }
1032 
1033     /**
1034      * Test that the ImsService corresponding to the default device ImsService package name is
1035      * bound to only RCS if METADATA_EMERGENCY_MMTEL_FEATURE but not METADATA_MMTEL_FEATURE.
1036      */
1037     @Test
1038     @SmallTest
testDevicePackageInvalidMmTelBind()1039     public void testDevicePackageInvalidMmTelBind() throws RemoteException {
1040         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1041                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1042         List<ResolveInfo> info = new ArrayList<>();
1043         Set<String> features = new HashSet<>();
1044         features.add(ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE);
1045         features.add(ImsResolver.METADATA_RCS_FEATURE);
1046         // Use device default package, which will load the ImsService that the device provides
1047         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
1048         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1049         setupPackageQuery(info);
1050         ImsServiceController controller = setupController();
1051 
1052         startBindNoCarrierConfig(1);
1053         processAllMessages();
1054 
1055         // If MMTEL_FEATURE is not set, EMERGENCY_MMTEL_FEATURE should not be in feature set.
1056         features.clear();
1057         features.add(ImsResolver.METADATA_RCS_FEATURE);
1058         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
1059         // There is no carrier override set, so make sure that the ImsServiceController binds
1060         // to all SIMs.
1061         verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
1062         verify(controller, never()).unbind();
1063         verify(mMockQueryManager, never()).startQuery(any(), any());
1064         assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
1065     }
1066 
1067     /**
1068      * Test that when a device and carrier override package are set, both ImsServices are bound.
1069      * Verify that the carrier ImsService features are created and the device default features
1070      * are created for all features that are not covered by the carrier ImsService.
1071      */
1072     @Test
1073     @SmallTest
testDeviceAndCarrierPackageBind()1074     public void testDeviceAndCarrierPackageBind() throws RemoteException {
1075         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1076                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1077         List<ResolveInfo> info = new ArrayList<>();
1078         Set<String> deviceFeatures = new HashSet<>();
1079         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1080         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1081         // Set the carrier override package for slot 0
1082         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1083         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1084         // Carrier service doesn't support the voice feature.
1085         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1086         // Use device default package, which will load the ImsService that the device provides
1087         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1088         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1089         // Only return info if not using the compat argument
1090         setupPackageQuery(info);
1091         ImsServiceController deviceController = mock(ImsServiceController.class);
1092         ImsServiceController carrierController = mock(ImsServiceController.class);
1093         setImsServiceControllerFactory(deviceController, carrierController);
1094 
1095         startBindCarrierConfigAlreadySet();
1096         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1097 
1098         // Verify that all features that have been defined for the carrier override are bound
1099         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1100         verify(carrierController, never()).unbind();
1101         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
1102         // Verify that all features that are not defined in the carrier override are bound in the
1103         // device controller (including emergency voice for slot 0)
1104         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1105                 convertToHashSet(deviceFeatures, 0);
1106         deviceFeatureSet.removeAll(carrierFeatures);
1107         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
1108         verify(deviceController, never()).unbind();
1109         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
1110     }
1111 
1112     /**
1113      * Verify that the ImsServiceController is available for the feature specified
1114      * (carrier for VOICE/RCS and device for emergency).
1115      */
1116     @Test
1117     @SmallTest
testGetDeviceCarrierFeatures()1118     public void testGetDeviceCarrierFeatures() throws RemoteException {
1119         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1120                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1121         ImsServiceController deviceController = mock(ImsServiceController.class);
1122         ImsServiceController carrierController = mock(ImsServiceController.class);
1123 
1124         // Callback from mock ImsServiceControllers
1125         // All features on slot 1 should be the device default
1126         mTestImsResolver.imsServiceFeatureCreated(1, ImsFeature.FEATURE_MMTEL, deviceController);
1127         mTestImsResolver.imsServiceFeatureCreated(1, ImsFeature.FEATURE_RCS, deviceController);
1128         mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_MMTEL, deviceController);
1129         // The carrier override contains this feature
1130         mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_RCS, carrierController);
1131     }
1132 
1133     /**
1134      * Bind to device ImsService and change the feature set. Verify that changeImsServiceFeature
1135      * is called with the new feature set.
1136      */
1137     @Test
1138     @SmallTest
testAddDeviceFeatureNoCarrier()1139     public void testAddDeviceFeatureNoCarrier() throws RemoteException {
1140         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1141                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1142         List<ResolveInfo> info = new ArrayList<>();
1143         Set<String> features = new HashSet<>();
1144         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
1145         // Doesn't include RCS feature by default
1146         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
1147         setupPackageQuery(info);
1148         ImsServiceController controller = setupController();
1149         // Bind using default features
1150         startBindNoCarrierConfig(2);
1151         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
1152                 convertToHashSet(features, 0);
1153         featureSet.addAll(convertToHashSet(features, 1));
1154         verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
1155 
1156         // add RCS to features list
1157         Set<String> newFeatures = new HashSet<>(features);
1158         newFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1159         info.clear();
1160         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, newFeatures, true));
1161 
1162         packageChanged(TEST_DEVICE_DEFAULT_NAME.getPackageName());
1163 
1164         //Verify new feature is added to the device default.
1165         HashSet<ImsFeatureConfiguration.FeatureSlotPair> newFeatureSet =
1166                 convertToHashSet(newFeatures, 0);
1167         newFeatureSet.addAll(convertToHashSet(newFeatures, 1));
1168         verify(controller).changeImsServiceFeatures(eq(newFeatureSet), any(SparseIntArray.class));
1169     }
1170 
1171     /**
1172      * Bind to device ImsServices and change the feature set to include one that is not configured.
1173      * Ensure it is not added.
1174      */
1175     @Test
1176     @SmallTest
testMultipleDeviceAddFeatureNoCarrier()1177     public void testMultipleDeviceAddFeatureNoCarrier() throws RemoteException {
1178         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1179                 TEST_DEVICE2_DEFAULT_NAME.getPackageName());
1180         List<ResolveInfo> info = new ArrayList<>();
1181         Set<String> featuresController1 = new HashSet<>();
1182         featuresController1.add(ImsResolver.METADATA_MMTEL_FEATURE);
1183         Set<String> featuresController2 = new HashSet<>();
1184         featuresController2.add(ImsResolver.METADATA_RCS_FEATURE);
1185         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, featuresController1, true));
1186         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, featuresController2, true));
1187         setupPackageQuery(info);
1188         ImsServiceController deviceController1 = mock(ImsServiceController.class);
1189         ImsServiceController deviceController2 = mock(ImsServiceController.class);
1190         setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
1191         // Bind using default features
1192         startBindNoCarrierConfig(2);
1193         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
1194                 convertToHashSet(featuresController1, 0);
1195         featureSet1.addAll(convertToHashSet(featuresController1, 1));
1196         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
1197                 convertToHashSet(featuresController2, 0);
1198         featureSet2.addAll(convertToHashSet(featuresController2, 1));
1199         verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
1200         verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
1201 
1202         // add RCS to features list for device 1
1203         Set<String> newFeatures1 = new HashSet<>(featuresController1);
1204         newFeatures1.add(ImsResolver.METADATA_RCS_FEATURE);
1205         info.clear();
1206         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, newFeatures1, true));
1207 
1208         packageChanged(TEST_DEVICE_DEFAULT_NAME.getPackageName());
1209 
1210         // verify the devices have not changed features (because their configurations are still
1211         // the same)
1212         verify(deviceController1, times(2)).changeImsServiceFeatures(eq(featureSet1),
1213                 any(SparseIntArray.class));
1214         verify(deviceController2, times(2)).changeImsServiceFeatures(eq(featureSet2),
1215                 any(SparseIntArray.class));
1216     }
1217 
1218     /**
1219      * Bind to device ImsService and change the feature set while not supporting that configuration.
1220      * Verify that changeImsServiceFeature is called with the original feature set.
1221      */
1222     @Test
1223     @SmallTest
testAddDeviceFeatureNoCarrierRcsNotSupported()1224     public void testAddDeviceFeatureNoCarrierRcsNotSupported() throws RemoteException {
1225         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(), "");
1226         List<ResolveInfo> info = new ArrayList<>();
1227         Set<String> features = new HashSet<>();
1228         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
1229         // Doesn't include RCS feature by default
1230         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
1231         setupPackageQuery(info);
1232         ImsServiceController controller = setupController();
1233         // Bind using default features
1234         startBindNoCarrierConfig(2);
1235         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
1236                 convertToHashSet(features, 0);
1237         featureSet.addAll(convertToHashSet(features, 1));
1238         verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
1239 
1240         // add RCS to features list
1241         Set<String> newFeatures = new HashSet<>(features);
1242         newFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1243         info.clear();
1244         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, newFeatures, true));
1245 
1246         packageChanged(TEST_DEVICE_DEFAULT_NAME.getPackageName());
1247 
1248         // Verify new feature is not added to the device default, since it is not configured.
1249         // This happens twice because two CarrierConfigChanged events occur, causing a
1250         // changeImsServiceFeatures after bind() and then another after packageChanged.
1251         verify(controller, times(2)).changeImsServiceFeatures(eq(featureSet),
1252                 any(SparseIntArray.class));
1253     }
1254 
1255     /**
1256      * Bind to device ImsService and change the feature set. Verify that changeImsServiceFeature
1257      * is called with the new feature set on the sub that doesn't include the carrier override.
1258      */
1259     @Test
1260     @SmallTest
testAddDeviceFeatureWithCarrier()1261     public void testAddDeviceFeatureWithCarrier() throws RemoteException {
1262         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1263                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1264         List<ResolveInfo> info = new ArrayList<>();
1265         Set<String> deviceFeatures = new HashSet<>();
1266         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1267         // Set the carrier override package for slot 0
1268         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1269         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1270         // Carrier service doesn't support the emergency voice feature.
1271         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
1272                 ImsFeature.FEATURE_MMTEL));
1273         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
1274                 ImsFeature.FEATURE_RCS));
1275         // Use device default package, which will load the ImsService that the device provides
1276         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1277         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1278         setupPackageQuery(info);
1279         ImsServiceController deviceController = mock(ImsServiceController.class);
1280         ImsServiceController carrierController = mock(ImsServiceController.class);
1281         setImsServiceControllerFactory(deviceController, carrierController);
1282 
1283         startBindCarrierConfigAlreadySet();
1284         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1285 
1286         // Verify that all features that have been defined for the carrier override are bound
1287         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1288         verify(carrierController, never()).unbind();
1289         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
1290         // Verify that all features that are not defined in the carrier override are bound in the
1291         // device controller (including emergency voice for slot 0)
1292         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1293                 convertToHashSet(deviceFeatures, 1);
1294         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1295         deviceFeatureSet.removeAll(carrierFeatures);
1296         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
1297         verify(deviceController, never()).unbind();
1298         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
1299 
1300         // add RCS to features list
1301         Set<String> newDeviceFeatures = new HashSet<>();
1302         newDeviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1303         newDeviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1304         info.clear();
1305         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, newDeviceFeatures, true));
1306 
1307         // Tell the package manager that a new device feature is installed
1308         packageChanged(TEST_DEVICE_DEFAULT_NAME.getPackageName());
1309 
1310         //Verify new feature is added to the device default.
1311         // add all features for slot 1
1312         HashSet<ImsFeatureConfiguration.FeatureSlotPair> newDeviceFeatureSet =
1313                 convertToHashSet(newDeviceFeatures, 1);
1314         newDeviceFeatureSet.addAll(convertToHashSet(newDeviceFeatures, 0));
1315         // remove carrier overrides for slot 0
1316         newDeviceFeatureSet.removeAll(carrierFeatures);
1317         verify(deviceController).changeImsServiceFeatures(eq(newDeviceFeatureSet),
1318                 any(SparseIntArray.class));
1319         // features should be the same as before, ImsServiceController will disregard change if it
1320         // is the same feature set anyway.
1321         verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
1322                 any(SparseIntArray.class));
1323     }
1324 
1325     /**
1326      * Bind to device ImsServices and change the feature set of the carrier overridden ImsService.
1327      * Verify that the device and carrier ImsServices are changed.
1328      */
1329     @Test
1330     @SmallTest
testAddCarrierFeature()1331     public void testAddCarrierFeature() throws RemoteException {
1332         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1333                 TEST_DEVICE2_DEFAULT_NAME.getPackageName());
1334         List<ResolveInfo> info = new ArrayList<>();
1335         Set<String> deviceFeatures1 = new HashSet<>();
1336         deviceFeatures1.add(ImsResolver.METADATA_MMTEL_FEATURE);
1337         Set<String> deviceFeatures2 = new HashSet<>();
1338         deviceFeatures2.add(ImsResolver.METADATA_RCS_FEATURE);
1339         Set<String> allDeviceFeatures = new HashSet<>(deviceFeatures1);
1340         allDeviceFeatures.addAll(deviceFeatures2);
1341         // Set the carrier override package for slot 0
1342         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1343         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1344         // Carrier service doesn't support the emergency voice feature.
1345         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
1346                 ImsFeature.FEATURE_MMTEL));
1347         // Use device default packages, which will load the ImsServices that the device provides
1348         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, allDeviceFeatures, true));
1349         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, allDeviceFeatures, true));
1350         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1351         setupPackageQuery(info);
1352         ImsServiceController deviceController1 = mock(ImsServiceController.class);
1353         ImsServiceController deviceController2 = mock(ImsServiceController.class);
1354         ImsServiceController carrierController = mock(ImsServiceController.class);
1355         setImsServiceControllerFactory(deviceController1, deviceController2, carrierController,
1356                 null);
1357 
1358         startBindCarrierConfigAlreadySet();
1359         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1360         // Verify that all features that have been defined for the carrier override are bound
1361         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1362         verify(carrierController, never()).unbind();
1363         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
1364         // Verify that all features that are not defined in the carrier override are bound in the
1365         // device controllers.
1366         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet1 =
1367                 convertToHashSet(deviceFeatures1, 1);
1368         deviceFeatureSet1.removeAll(carrierFeatures);
1369         verify(deviceController1).bind(eq(deviceFeatureSet1), any(SparseIntArray.class));
1370         verify(deviceController1, never()).unbind();
1371         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet2 =
1372                 convertToHashSet(deviceFeatures2, 0);
1373         deviceFeatureSet2.addAll(convertToHashSet(deviceFeatures2, 1));
1374         deviceFeatureSet2.removeAll(carrierFeatures);
1375         verify(deviceController2).bind(eq(deviceFeatureSet2), any(SparseIntArray.class));
1376         verify(deviceController2, never()).unbind();
1377         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
1378         assertEquals(TEST_DEVICE2_DEFAULT_NAME, deviceController2.getComponentName());
1379 
1380         // add RCS to carrier features list
1381         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1382 
1383         // A new carrier feature is installed
1384         packageChanged(TEST_CARRIER_DEFAULT_NAME.getPackageName());
1385         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 2);
1386 
1387         //Verify new feature is added to the carrier override.
1388         verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
1389                 any(SparseIntArray.class));
1390         deviceFeatureSet1.removeAll(carrierFeatures);
1391         verify(deviceController1, times(2)).changeImsServiceFeatures(eq(deviceFeatureSet1),
1392                 any(SparseIntArray.class));
1393         deviceFeatureSet2.removeAll(carrierFeatures);
1394         verify(deviceController2).changeImsServiceFeatures(eq(deviceFeatureSet2),
1395                 any(SparseIntArray.class));
1396     }
1397 
1398     /**
1399      * Bind to device ImsService and change the feature set of the carrier overridden ImsService by
1400      * removing a feature.
1401      * Verify that the device and carrier ImsServices are changed.
1402      */
1403     @Test
1404     @SmallTest
testRemoveCarrierFeature()1405     public void testRemoveCarrierFeature() throws RemoteException {
1406         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1407                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1408         List<ResolveInfo> info = new ArrayList<>();
1409         Set<String> deviceFeatures = new HashSet<>();
1410         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1411         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1412         // Set the carrier override package for slot 0
1413         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1414         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1415         // Carrier service doesn't support the voice feature.
1416         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1417         // Use device default package, which will load the ImsService that the device provides
1418         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1419         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1420         setupPackageQuery(info);
1421         ImsServiceController deviceController = mock(ImsServiceController.class);
1422         ImsServiceController carrierController = mock(ImsServiceController.class);
1423         setImsServiceControllerFactory(deviceController, carrierController);
1424 
1425         startBindCarrierConfigAlreadySet();
1426         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1427         // Verify that all features that have been defined for the carrier override are bound
1428         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1429         verify(carrierController, never()).unbind();
1430         assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
1431         // Verify that all features that are not defined in the carrier override are bound in the
1432         // device controller (including emergency voice for slot 0)
1433         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1434                 convertToHashSet(deviceFeatures, 1);
1435         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1436         deviceFeatureSet.removeAll(carrierFeatures);
1437         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
1438         verify(deviceController, never()).unbind();
1439         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
1440 
1441         // change supported feature to MMTEL only
1442         carrierFeatures.clear();
1443         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
1444                 ImsFeature.FEATURE_MMTEL));
1445         //  new carrier feature has been removed
1446         packageChanged(TEST_CARRIER_DEFAULT_NAME.getPackageName());
1447         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 2);
1448 
1449         //Verify new feature is added to the carrier override.
1450         verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
1451                 any(SparseIntArray.class));
1452         Set<String> newDeviceFeatures = new HashSet<>();
1453         newDeviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1454         newDeviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1455         HashSet<ImsFeatureConfiguration.FeatureSlotPair> newDeviceFeatureSet =
1456                 convertToHashSet(newDeviceFeatures, 1);
1457         newDeviceFeatureSet.addAll(convertToHashSet(newDeviceFeatures, 0));
1458         newDeviceFeatureSet.removeAll(carrierFeatures);
1459         verify(deviceController).changeImsServiceFeatures(eq(newDeviceFeatureSet),
1460                 any(SparseIntArray.class));
1461     }
1462 
1463     /**
1464      * Inform the ImsResolver that a Carrier ImsService has been installed and must be bound.
1465      */
1466     @Test
1467     @SmallTest
testInstallCarrierImsService()1468     public void testInstallCarrierImsService() throws RemoteException {
1469         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1470                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1471         List<ResolveInfo> info = new ArrayList<>();
1472         Set<String> deviceFeatures = new HashSet<>();
1473         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1474         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1475         // Set the carrier override package for slot 0
1476         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1477         // Use device default package, which will load the ImsService that the device provides
1478         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1479         setupPackageQuery(info);
1480         ImsServiceController deviceController = mock(ImsServiceController.class);
1481         ImsServiceController carrierController = mock(ImsServiceController.class);
1482         setImsServiceControllerFactory(deviceController, carrierController);
1483 
1484         startBindCarrierConfigAlreadySet();
1485 
1486         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1487         // Carrier service doesn't support the voice feature.
1488         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1489         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1490 
1491         // Tell the package manager that a new carrier app is installed
1492         packageChanged(TEST_CARRIER_DEFAULT_NAME.getPackageName());
1493         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1494 
1495         // Verify that all features that have been defined for the carrier override are bound
1496         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1497         // device features change
1498         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1499                 convertToHashSet(deviceFeatures, 1);
1500         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1501         deviceFeatureSet.removeAll(carrierFeatures);
1502         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
1503                 any(SparseIntArray.class));
1504     }
1505 
1506     /**
1507      * Inform the ImsResolver that a carrier ImsService has been uninstalled and the device default
1508      * must now use those features.
1509      */
1510     @Test
1511     @SmallTest
testUninstallCarrierImsService()1512     public void testUninstallCarrierImsService() throws RemoteException {
1513         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1514                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1515         List<ResolveInfo> info = new ArrayList<>();
1516         Set<String> deviceFeatures = new HashSet<>();
1517         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1518         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1519         // Set the carrier override package for slot 0
1520         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1521         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1522         // Carrier service doesn't support the voice feature.
1523         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1524         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1525         // Use device default package, which will load the ImsService that the device provides
1526         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1527         setupPackageQuery(info);
1528         ImsServiceController deviceController = mock(ImsServiceController.class);
1529         ImsServiceController carrierController = mock(ImsServiceController.class);
1530         setImsServiceControllerFactory(deviceController, carrierController);
1531 
1532         startBindCarrierConfigAlreadySet();
1533         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1534 
1535         // Tell the package manager that carrier app is uninstalled
1536         info.clear();
1537         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1538         packageRemoved(TEST_CARRIER_DEFAULT_NAME.getPackageName());
1539 
1540         // Verify that the carrier controller is unbound
1541         verify(carrierController).unbind();
1542         assertNull(mTestImsResolver.getImsServiceInfoFromCache(
1543                 TEST_CARRIER_DEFAULT_NAME.getPackageName()));
1544         // device features change to include all supported functionality
1545         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1546                 convertToHashSet(deviceFeatures, 1);
1547         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1548         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
1549                 any(SparseIntArray.class));
1550     }
1551 
1552     /**
1553      * Inform ImsResolver that the carrier config has changed to none, requiring the device
1554      * ImsService to be bound/set up and the previous carrier ImsService to be unbound.
1555      */
1556     @Test
1557     @SmallTest
testCarrierConfigChangedToNone()1558     public void testCarrierConfigChangedToNone() throws RemoteException {
1559         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1560                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1561         List<ResolveInfo> info = new ArrayList<>();
1562         Set<String> deviceFeatures = new HashSet<>();
1563         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1564         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1565         // Set the carrier override package for slot 0
1566         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1567         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1568         // Carrier service doesn't support the voice feature.
1569         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1570         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1571         // Use device default package, which will load the ImsService that the device provides
1572         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1573         setupPackageQuery(info);
1574         ImsServiceController deviceController = mock(ImsServiceController.class);
1575         ImsServiceController carrierController = mock(ImsServiceController.class);
1576         setImsServiceControllerFactory(deviceController, carrierController);
1577 
1578         startBindCarrierConfigAlreadySet();
1579         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1580 
1581         setConfigCarrierStringMmTelRcs(0, null);
1582         sendCarrierConfigChanged(0, 0);
1583 
1584         // Verify that the carrier controller is unbound
1585         verify(carrierController).unbind();
1586         assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
1587                 TEST_CARRIER_DEFAULT_NAME.getPackageName()));
1588         // device features change
1589         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1590                 convertToHashSet(deviceFeatures, 1);
1591         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1592         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
1593                 any(SparseIntArray.class));
1594     }
1595 
1596     /**
1597      * Inform ImsResolver that the carrier config has changed to another, requiring the new carrier
1598      * ImsService to be bound/set up and the previous carrier ImsService to be unbound.
1599      */
1600     @Test
1601     @SmallTest
testCarrierConfigChangedToAnotherService()1602     public void testCarrierConfigChangedToAnotherService() throws RemoteException {
1603         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1604                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1605         List<ResolveInfo> info = new ArrayList<>();
1606         Set<String> deviceFeatures = new HashSet<>();
1607         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1608         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1609         // Set the carrier override package for slot 0
1610         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1611         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures1 = new HashSet<>();
1612         // Carrier service 1
1613         carrierFeatures1.add(new ImsFeatureConfiguration.FeatureSlotPair(0,
1614                 ImsFeature.FEATURE_MMTEL));
1615         carrierFeatures1.add(
1616                 new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1617         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures2 = new HashSet<>();
1618         // Carrier service 2 doesn't support the voice feature.
1619         carrierFeatures2.add(
1620                 new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1621         info.add(getResolveInfo(TEST_CARRIER_2_DEFAULT_NAME, new HashSet<>(), true));
1622         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1623         // Use device default package, which will load the ImsService that the device provides
1624         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1625         setupPackageQuery(info);
1626         ImsServiceController deviceController = mock(ImsServiceController.class);
1627         ImsServiceController carrierController1 = mock(ImsServiceController.class);
1628         ImsServiceController carrierController2 = mock(ImsServiceController.class);
1629         setImsServiceControllerFactory(deviceController, carrierController1, carrierController2);
1630 
1631         startBindCarrierConfigAlreadySet();
1632         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures1, 1);
1633 
1634         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_2_DEFAULT_NAME.getPackageName());
1635         sendCarrierConfigChanged(0, 0);
1636         setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, carrierFeatures2, 1);
1637 
1638         // Verify that carrier 1 is unbound
1639         verify(carrierController1).unbind();
1640         assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
1641                 TEST_CARRIER_DEFAULT_NAME.getPackageName()));
1642         // Verify that carrier 2 is bound
1643         verify(carrierController2).bind(eq(carrierFeatures2), any(SparseIntArray.class));
1644         assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
1645                 TEST_CARRIER_2_DEFAULT_NAME.getPackageName()));
1646         // device features change to accommodate for the features carrier 2 lacks
1647         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1648                 convertToHashSet(deviceFeatures, 1);
1649         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1650         deviceFeatureSet.removeAll(carrierFeatures2);
1651         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
1652                 any(SparseIntArray.class));
1653     }
1654 
1655     /**
1656      * Inform the ImsResolver that BOOT_COMPLETE has happened. A non-FBE enabled ImsService is now
1657      * available to be bound.
1658      */
1659     @Test
1660     @SmallTest
testBootCompleteNonFbeEnabledCarrierImsService()1661     public void testBootCompleteNonFbeEnabledCarrierImsService() throws RemoteException {
1662         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1663                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1664         List<ResolveInfo> info = new ArrayList<>();
1665         Set<String> deviceFeatures = new HashSet<>();
1666         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1667         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1668         // Set the carrier override package for slot 0
1669         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1670         // Use device default package, which will load the ImsService that the device provides
1671         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1672         setupPackageQuery(info);
1673         ImsServiceController deviceController = mock(ImsServiceController.class);
1674         ImsServiceController carrierController = mock(ImsServiceController.class);
1675         setImsServiceControllerFactory(deviceController, carrierController);
1676 
1677         // Bind with device ImsService
1678         startBindCarrierConfigAlreadySet();
1679 
1680         // Boot complete happens and the Carrier ImsService is now available.
1681         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1682         // Carrier service doesn't support the voice feature.
1683         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1684         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1685         // Boot complete has happened and the carrier ImsService is now available.
1686         mTestBootCompleteReceiver.onReceive(null, new Intent(Intent.ACTION_BOOT_COMPLETED));
1687         processAllMessages();
1688         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1689 
1690         // Verify that all features that have been defined for the carrier override are bound
1691         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1692         // device features change
1693         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1694                 convertToHashSet(deviceFeatures, 1);
1695         deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
1696         deviceFeatureSet.removeAll(carrierFeatures);
1697         verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
1698                 any(SparseIntArray.class));
1699     }
1700 
1701     /**
1702      * If a misbehaving ImsService returns null for the Binder connection when we perform a dynamic
1703      * feature query, verify we never perform a full bind for any features.
1704      */
1705     @Test
1706     @SmallTest
testPermanentBindFailureDuringFeatureQuery()1707     public void testPermanentBindFailureDuringFeatureQuery() throws RemoteException {
1708         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1709                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1710         List<ResolveInfo> info = new ArrayList<>();
1711         Set<String> deviceFeatures = new HashSet<>();
1712         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1713         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1714         // Set the carrier override package for slot 0
1715         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1716         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1717         // Carrier service doesn't support the voice feature.
1718         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1719         // Use device default package, which will load the ImsService that the device provides
1720         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1721         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1722         setupPackageQuery(info);
1723         ImsServiceController deviceController = mock(ImsServiceController.class);
1724         ImsServiceController carrierController = mock(ImsServiceController.class);
1725         setImsServiceControllerFactory(deviceController, carrierController);
1726 
1727         startBindCarrierConfigAlreadySet();
1728         // dynamic query results in a failure.
1729         setupDynamicQueryFeaturesFailure(TEST_CARRIER_DEFAULT_NAME, 1);
1730 
1731         // Verify that a bind never occurs for the carrier controller.
1732         verify(carrierController, never()).bind(any(), any(SparseIntArray.class));
1733         verify(carrierController, never()).unbind();
1734         // Verify that all features are used to bind to the device ImsService since the carrier
1735         // ImsService failed to bind properly.
1736         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1737                 convertToHashSet(deviceFeatures, 0);
1738         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
1739         verify(deviceController, never()).unbind();
1740         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
1741     }
1742 
1743     /**
1744      * If a misbehaving ImsService returns null for the Binder connection when we perform bind,
1745      * verify the service is disconnected.
1746      */
1747     @Test
1748     @SmallTest
testPermanentBindFailureDuringBind()1749     public void testPermanentBindFailureDuringBind() throws RemoteException {
1750         setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1751                 TEST_DEVICE_DEFAULT_NAME.getPackageName());
1752         List<ResolveInfo> info = new ArrayList<>();
1753         Set<String> deviceFeatures = new HashSet<>();
1754         deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
1755         deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
1756         // Set the carrier override package for slot 0
1757         setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
1758         HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
1759         // Carrier service doesn't support the voice feature.
1760         carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
1761         // Use device default package, which will load the ImsService that the device provides
1762         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
1763         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1764         setupPackageQuery(info);
1765         ImsServiceController deviceController = mock(ImsServiceController.class);
1766         ImsServiceController carrierController = mock(ImsServiceController.class);
1767         setImsServiceControllerFactory(deviceController, carrierController);
1768 
1769         startBindCarrierConfigAlreadySet();
1770         setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
1771 
1772         // Verify that a bind never occurs for the carrier controller.
1773         verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
1774         verify(carrierController, never()).unbind();
1775         // Verify that all features that are not defined in the carrier override are bound in the
1776         // device controller (including emergency voice for slot 0)
1777         HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
1778                 convertToHashSet(deviceFeatures, 0);
1779         deviceFeatureSet.removeAll(carrierFeatures);
1780         verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
1781         verify(deviceController, never()).unbind();
1782         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
1783 
1784         mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME);
1785         processAllMessages();
1786         verify(carrierController).unbind();
1787         // Verify that the device ImsService features are changed to include the ones previously
1788         // taken by the carrier app.
1789         HashSet<ImsFeatureConfiguration.FeatureSlotPair> originalDeviceFeatureSet =
1790                 convertToHashSet(deviceFeatures, 0);
1791         verify(deviceController).changeImsServiceFeatures(eq(originalDeviceFeatureSet),
1792                 any(SparseIntArray.class));
1793     }
1794 
1795     /**
1796      * Bind to device ImsService only, which is configured to be the MMTEL ImsService. Ensure it
1797      * does not also try to bind to RCS.
1798      */
1799     @Test
1800     @SmallTest
testDifferentDevicePackagesMmTelOnly()1801     public void testDifferentDevicePackagesMmTelOnly() throws RemoteException {
1802         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(), "");
1803         List<ResolveInfo> info = new ArrayList<>();
1804         Set<String> features = new HashSet<>();
1805         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
1806         features.add(ImsResolver.METADATA_RCS_FEATURE);
1807         // Use device default package, which will load the ImsService that the device provides
1808         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
1809         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, features, true));
1810         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1811         setupPackageQuery(info);
1812         ImsServiceController deviceController1 = mock(ImsServiceController.class);
1813         ImsServiceController deviceController2 = mock(ImsServiceController.class);
1814         setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
1815 
1816         startBindNoCarrierConfig(1);
1817         processAllMessages();
1818 
1819         Set<String> featureResult = new HashSet<>();
1820         featureResult.add(ImsResolver.METADATA_MMTEL_FEATURE);
1821         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureResultSet =
1822                 convertToHashSet(featureResult, 0);
1823         featureResultSet.addAll(convertToHashSet(featureResult, 1));
1824         verify(deviceController1).bind(eq(featureResultSet), any(SparseIntArray.class));
1825         verify(deviceController1, never()).unbind();
1826         verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
1827         verify(deviceController2, never()).unbind();
1828         verify(mMockQueryManager, never()).startQuery(any(), any());
1829         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
1830     }
1831 
1832     /**
1833      * Bind to device ImsService only, which is configured to be the RCS ImsService. Ensure it
1834      * does not also try to bind to MMTEL.
1835      */
1836     @Test
1837     @SmallTest
testDifferentDevicePackagesRcsOnly()1838     public void testDifferentDevicePackagesRcsOnly() throws RemoteException {
1839         setupResolver(2 /*numSlots*/, "", TEST_DEVICE_DEFAULT_NAME.getPackageName());
1840         List<ResolveInfo> info = new ArrayList<>();
1841         Set<String> features = new HashSet<>();
1842         features.add(ImsResolver.METADATA_MMTEL_FEATURE);
1843         features.add(ImsResolver.METADATA_RCS_FEATURE);
1844         // Use device default package, which will load the ImsService that the device provides
1845         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features, true));
1846         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, features, true));
1847         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1848         setupPackageQuery(info);
1849         ImsServiceController deviceController1 = mock(ImsServiceController.class);
1850         ImsServiceController deviceController2 = mock(ImsServiceController.class);
1851         setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
1852 
1853         startBindNoCarrierConfig(1);
1854         processAllMessages();
1855 
1856         Set<String> featureResult = new HashSet<>();
1857         featureResult.add(ImsResolver.METADATA_RCS_FEATURE);
1858         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureResultSet =
1859                 convertToHashSet(featureResult, 0);
1860         featureResultSet.addAll(convertToHashSet(featureResult, 1));
1861         verify(deviceController1).bind(eq(featureResultSet), any(SparseIntArray.class));
1862         verify(deviceController1, never()).unbind();
1863         verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
1864         verify(deviceController2, never()).unbind();
1865         verify(mMockQueryManager, never()).startQuery(any(), any());
1866         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
1867     }
1868 
1869     /**
1870      * Bind to multiple ImsServices, one for MMTEL and one for RCS. Ensure neither of them bind to
1871      * both.
1872      */
1873     @Test
1874     @SmallTest
testDifferentDevicePackagesMmTelRcs()1875     public void testDifferentDevicePackagesMmTelRcs() throws RemoteException {
1876         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1877                 TEST_DEVICE2_DEFAULT_NAME.getPackageName());
1878         List<ResolveInfo> info = new ArrayList<>();
1879         Set<String> features1 = new HashSet<>();
1880         features1.add(ImsResolver.METADATA_MMTEL_FEATURE);
1881         Set<String> features2 = new HashSet<>();
1882         features2.add(ImsResolver.METADATA_RCS_FEATURE);
1883         Set<String> allFeatures = new HashSet<>(features1);
1884         allFeatures.addAll(features2);
1885         // Use device default package, which will load the ImsService that the device provides
1886         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, allFeatures, true));
1887         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, allFeatures, true));
1888         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1889         setupPackageQuery(info);
1890         ImsServiceController deviceController1 = mock(ImsServiceController.class);
1891         ImsServiceController deviceController2 = mock(ImsServiceController.class);
1892         setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
1893 
1894         startBindNoCarrierConfig(1);
1895         processAllMessages();
1896 
1897         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
1898                 convertToHashSet(features1, 0);
1899         featureSet1.addAll(convertToHashSet(features1, 1));
1900         HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
1901                 convertToHashSet(features2, 0);
1902         featureSet2.addAll(convertToHashSet(features2, 1));
1903         verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
1904         verify(deviceController1, never()).unbind();
1905         verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
1906         verify(deviceController2, never()).unbind();
1907         verify(mMockQueryManager, never()).startQuery(any(), any());
1908         assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
1909         assertEquals(TEST_DEVICE2_DEFAULT_NAME, deviceController2.getComponentName());
1910     }
1911 
1912     /**
1913      * Set the device configuration to opposite of the supported features in the metadata and ensure
1914      * there is no bind.
1915      */
1916     @Test
1917     @SmallTest
testDifferentDevicePackagesNoSupported()1918     public void testDifferentDevicePackagesNoSupported() throws RemoteException {
1919         setupResolver(2 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
1920                 TEST_DEVICE2_DEFAULT_NAME.getPackageName());
1921         List<ResolveInfo> info = new ArrayList<>();
1922         Set<String> features1 = new HashSet<>();
1923         features1.add(ImsResolver.METADATA_RCS_FEATURE);
1924         Set<String> features2 = new HashSet<>();
1925         features2.add(ImsResolver.METADATA_MMTEL_FEATURE);
1926         // The configuration is opposite of the device supported features
1927         info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, features1, true));
1928         info.add(getResolveInfo(TEST_DEVICE2_DEFAULT_NAME, features2, true));
1929         info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
1930         setupPackageQuery(info);
1931         ImsServiceController deviceController1 = mock(ImsServiceController.class);
1932         ImsServiceController deviceController2 = mock(ImsServiceController.class);
1933         setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
1934 
1935         startBindNoCarrierConfig(1);
1936         processAllMessages();
1937 
1938         verify(deviceController1, never()).bind(any(), any(SparseIntArray.class));
1939         verify(deviceController1, never()).unbind();
1940         verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
1941         verify(deviceController2, never()).unbind();
1942         verify(mMockQueryManager, never()).startQuery(any(), any());
1943     }
1944 
setupResolver(int numSlots, String deviceMmTelPkgName, String deviceRcsPkgName)1945     private void setupResolver(int numSlots, String deviceMmTelPkgName,
1946             String deviceRcsPkgName) {
1947         // all tests call setupResolver before running
1948         when(mMockContext.getPackageManager()).thenReturn(mMockPM);
1949         when(mMockContext.createContextAsUser(any(), eq(0))).thenReturn(mMockContext);
1950         when(mMockContext.getSystemService(eq(Context.CARRIER_CONFIG_SERVICE))).thenReturn(
1951                 mMockCarrierConfigManager);
1952         when(mMockContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mMockUserManager);
1953 
1954         //If this is not false, then HANDLER_BOOT_COMPLETE is fired now but the controller factories
1955         //used in the test methods aren't created in time.
1956         when(mMockUserManager.isUserUnlocked()).thenReturn(false);
1957 
1958         // Support configs for MSIM always in case we are testing dynamic sim slot config changes.
1959         mCarrierConfigs = new PersistableBundle[NUM_MAX_SLOTS];
1960         for (int i = 0; i < NUM_MAX_SLOTS; i++) {
1961             mCarrierConfigs[i] = new PersistableBundle();
1962             when(mMockCarrierConfigManager.getConfigForSubId(eq(i))).thenReturn(
1963                     mCarrierConfigs[i]);
1964             when(mTestSubscriptionManagerProxy.getSlotIndex(eq(i))).thenReturn(i);
1965             when(mTestSubscriptionManagerProxy.getSubId(eq(i))).thenReturn(i);
1966             when(mTestTelephonyManagerProxy.getSimState(any(Context.class), eq(i))).thenReturn(
1967                     TelephonyManager.SIM_STATE_READY);
1968         }
1969 
1970         mTestImsResolver = new ImsResolver(mMockContext, deviceMmTelPkgName, deviceRcsPkgName,
1971                 numSlots, mMockRepo, Looper.myLooper());
1972 
1973         mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
1974         mTestImsResolver.setTelephonyManagerProxy(mTestTelephonyManagerProxy);
1975         when(mMockQueryManagerFactory.create(any(Context.class),
1976                 any(ImsServiceFeatureQueryManager.Listener.class))).thenReturn(mMockQueryManager);
1977         mTestImsResolver.setImsDynamicQueryManagerFactory(mMockQueryManagerFactory);
1978         processAllMessages();
1979     }
1980 
setupPackageQuery(List<ResolveInfo> infos)1981     private void setupPackageQuery(List<ResolveInfo> infos) {
1982         // Only return info if not using the compat argument
1983         when(mMockPM.queryIntentServicesAsUser(
1984                 argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
1985                 anyInt(), any())).thenReturn(infos);
1986     }
1987 
setupPackageQuery(ComponentName name, Set<String> features, boolean isPermissionGranted)1988     private void setupPackageQuery(ComponentName name, Set<String> features,
1989             boolean isPermissionGranted) {
1990         List<ResolveInfo> info = new ArrayList<>();
1991         info.add(getResolveInfo(name, features, isPermissionGranted));
1992         // Only return info if not using the compat argument
1993         when(mMockPM.queryIntentServicesAsUser(
1994                 argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
1995                 anyInt(), any())).thenReturn(info);
1996     }
1997 
setupController()1998     private ImsServiceController setupController() {
1999         ImsServiceController controller = mock(ImsServiceController.class);
2000         mTestImsResolver.setImsServiceControllerFactory(
2001                 new ImsResolver.ImsServiceControllerFactory() {
2002                     @Override
2003                     public String getServiceInterface() {
2004                         return ImsService.SERVICE_INTERFACE;
2005                     }
2006 
2007                     @Override
2008                     public ImsServiceController create(Context context, ComponentName componentName,
2009                             ImsServiceController.ImsServiceControllerCallbacks callbacks,
2010                             ImsFeatureBinderRepository r) {
2011                         when(controller.getComponentName()).thenReturn(componentName);
2012                         return controller;
2013                     }
2014                 });
2015         return controller;
2016     }
2017 
2018     /**
2019      * In this case, there is a CarrierConfig already set for the sub/slot combo when initializing.
2020      * This automatically kicks off the binding internally.
2021      */
startBindCarrierConfigAlreadySet()2022     private void startBindCarrierConfigAlreadySet() {
2023         mTestImsResolver.initialize();
2024         processAllMessages();
2025         ArgumentCaptor<BroadcastReceiver> receiversCaptor =
2026                 ArgumentCaptor.forClass(BroadcastReceiver.class);
2027         verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
2028         mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
2029         mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
2030         mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
2031         ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
2032                 ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
2033         verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
2034         mDynamicQueryListener = queryManagerCaptor.getValue();
2035         when(mMockQueryManager.startQuery(any(ComponentName.class), any(String.class)))
2036                 .thenReturn(true);
2037         processAllMessages();
2038     }
2039 
2040     /**
2041      * In this case, there is no carrier config override, send CarrierConfig loaded intent to all
2042      * slots, indicating that the SIMs are loaded and to bind the device default.
2043      */
startBindNoCarrierConfig(int numSlots)2044     private void startBindNoCarrierConfig(int numSlots) {
2045         mTestImsResolver.initialize();
2046         processAllMessages();
2047         ArgumentCaptor<BroadcastReceiver> receiversCaptor =
2048                 ArgumentCaptor.forClass(BroadcastReceiver.class);
2049         verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
2050         mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
2051         mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
2052         mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
2053         ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
2054                 ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
2055         verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
2056         mDynamicQueryListener = queryManagerCaptor.getValue();
2057         processAllMessages();
2058         // For ease of testing, slotId = subId
2059         for (int i = 0; i < numSlots; i++) {
2060             sendCarrierConfigChanged(i, i);
2061         }
2062     }
2063 
setupDynamicQueryFeatures(ComponentName name, HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times)2064     private void setupDynamicQueryFeatures(ComponentName name,
2065             HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
2066         processAllMessages();
2067         // ensure that startQuery was called
2068         verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
2069         mDynamicQueryListener.onComplete(name, features);
2070         processAllMessages();
2071     }
2072 
setupDynamicQueryFeaturesMultiSim(ComponentName name, HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times)2073     private void setupDynamicQueryFeaturesMultiSim(ComponentName name,
2074             HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
2075         processAllFutureMessages();
2076         // ensure that startQuery was called
2077         verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
2078         mDynamicQueryListener.onComplete(name, features);
2079         processAllMessages();
2080     }
2081 
setupDynamicQueryFeaturesFailure(ComponentName name, int times)2082     private void setupDynamicQueryFeaturesFailure(ComponentName name, int times) {
2083         processAllMessages();
2084         // ensure that startQuery was called
2085         verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
2086         mDynamicQueryListener.onPermanentError(name);
2087         processAllMessages();
2088     }
2089 
packageChanged(String packageName)2090     public void packageChanged(String packageName) {
2091         // Tell the package manager that a new device feature is installed
2092         Intent addPackageIntent = new Intent();
2093         addPackageIntent.setAction(Intent.ACTION_PACKAGE_CHANGED);
2094         addPackageIntent.setData(new Uri.Builder().scheme("package").opaquePart(packageName)
2095                 .build());
2096         mTestPackageBroadcastReceiver.onReceive(null, addPackageIntent);
2097         processAllMessages();
2098     }
2099 
packageRemoved(String packageName)2100     public void packageRemoved(String packageName) {
2101         Intent removePackageIntent = new Intent();
2102         removePackageIntent.setAction(Intent.ACTION_PACKAGE_REMOVED);
2103         removePackageIntent.setData(new Uri.Builder().scheme("package")
2104                 .opaquePart(TEST_CARRIER_DEFAULT_NAME.getPackageName()).build());
2105         mTestPackageBroadcastReceiver.onReceive(null, removePackageIntent);
2106         processAllMessages();
2107     }
2108 
setImsServiceControllerFactory(Map<String, ImsServiceController> controllerMap)2109     private void setImsServiceControllerFactory(Map<String, ImsServiceController> controllerMap) {
2110         mTestImsResolver.setImsServiceControllerFactory(
2111                 new ImsResolver.ImsServiceControllerFactory() {
2112                     @Override
2113                     public String getServiceInterface() {
2114                         return ImsService.SERVICE_INTERFACE;
2115                     }
2116 
2117                     @Override
2118                     public ImsServiceController create(Context context, ComponentName componentName,
2119                             ImsServiceController.ImsServiceControllerCallbacks callbacks,
2120                             ImsFeatureBinderRepository r) {
2121                         return controllerMap.get(componentName.getPackageName());
2122                     }
2123                 });
2124     }
2125 
setImsServiceControllerFactory(ImsServiceController deviceController, ImsServiceController carrierController)2126     private void setImsServiceControllerFactory(ImsServiceController deviceController,
2127             ImsServiceController carrierController) {
2128         mTestImsResolver.setImsServiceControllerFactory(
2129                 new ImsResolver.ImsServiceControllerFactory() {
2130                     @Override
2131                     public String getServiceInterface() {
2132                         return ImsService.SERVICE_INTERFACE;
2133                     }
2134 
2135                     @Override
2136                     public ImsServiceController create(Context context, ComponentName componentName,
2137                             ImsServiceController.ImsServiceControllerCallbacks callbacks,
2138                             ImsFeatureBinderRepository r) {
2139                         if (TEST_DEVICE_DEFAULT_NAME.getPackageName().equals(
2140                                 componentName.getPackageName())) {
2141                             when(deviceController.getComponentName()).thenReturn(componentName);
2142                             return deviceController;
2143                         } else if (TEST_CARRIER_DEFAULT_NAME.getPackageName().equals(
2144                                 componentName.getPackageName())) {
2145                             when(carrierController.getComponentName()).thenReturn(componentName);
2146                             return carrierController;
2147                         }
2148                         return null;
2149                     }
2150                 });
2151     }
2152 
setImsServiceControllerFactory(ImsServiceController deviceController, ImsServiceController carrierController1, ImsServiceController carrierController2)2153     private void setImsServiceControllerFactory(ImsServiceController deviceController,
2154             ImsServiceController carrierController1, ImsServiceController carrierController2) {
2155         mTestImsResolver.setImsServiceControllerFactory(
2156                 new ImsResolver.ImsServiceControllerFactory() {
2157                     @Override
2158                     public String getServiceInterface() {
2159                         return ImsService.SERVICE_INTERFACE;
2160                     }
2161 
2162                     @Override
2163                     public ImsServiceController create(Context context, ComponentName componentName,
2164                             ImsServiceController.ImsServiceControllerCallbacks callbacks,
2165                             ImsFeatureBinderRepository r) {
2166                         if (TEST_DEVICE_DEFAULT_NAME.getPackageName().equals(
2167                                 componentName.getPackageName())) {
2168                             when(deviceController.getComponentName()).thenReturn(componentName);
2169                             return deviceController;
2170                         } else if (TEST_CARRIER_DEFAULT_NAME.getPackageName().equals(
2171                                 componentName.getPackageName())) {
2172                             when(carrierController1.getComponentName()).thenReturn(componentName);
2173                             return carrierController1;
2174                         } else if (TEST_CARRIER_2_DEFAULT_NAME.getPackageName().equals(
2175                                 componentName.getPackageName())) {
2176                             when(carrierController2.getComponentName()).thenReturn(componentName);
2177                             return carrierController2;
2178                         }
2179                         return null;
2180                     }
2181                 });
2182     }
2183 
setImsServiceControllerFactory(ImsServiceController deviceController1, ImsServiceController deviceController2, ImsServiceController carrierController1, ImsServiceController carrierController2)2184     private void setImsServiceControllerFactory(ImsServiceController deviceController1,
2185             ImsServiceController deviceController2, ImsServiceController carrierController1,
2186             ImsServiceController carrierController2) {
2187         mTestImsResolver.setImsServiceControllerFactory(
2188                 new ImsResolver.ImsServiceControllerFactory() {
2189                     @Override
2190                     public String getServiceInterface() {
2191                         return ImsService.SERVICE_INTERFACE;
2192                     }
2193 
2194                     @Override
2195                     public ImsServiceController create(Context context, ComponentName componentName,
2196                             ImsServiceController.ImsServiceControllerCallbacks callbacks,
2197                             ImsFeatureBinderRepository r) {
2198                         if (TEST_DEVICE_DEFAULT_NAME.getPackageName().equals(
2199                                 componentName.getPackageName())) {
2200                             when(deviceController1.getComponentName()).thenReturn(componentName);
2201                             return deviceController1;
2202                         } else if (TEST_DEVICE2_DEFAULT_NAME.getPackageName().equals(
2203                                 componentName.getPackageName())) {
2204                             when(deviceController2.getComponentName()).thenReturn(componentName);
2205                             return deviceController2;
2206                         } else if (TEST_CARRIER_DEFAULT_NAME.getPackageName().equals(
2207                                 componentName.getPackageName())) {
2208                             when(carrierController1.getComponentName()).thenReturn(componentName);
2209                             return carrierController1;
2210                         } else if (TEST_CARRIER_2_DEFAULT_NAME.getPackageName().equals(
2211                                 componentName.getPackageName())) {
2212                             when(carrierController2.getComponentName()).thenReturn(componentName);
2213                             return carrierController2;
2214                         }
2215                         return null;
2216                     }
2217                 });
2218     }
2219 
2220 
sendCarrierConfigChanged(int subId, int slotId)2221     private void sendCarrierConfigChanged(int subId, int slotId) {
2222         Intent carrierConfigIntent = new Intent();
2223         carrierConfigIntent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, subId);
2224         carrierConfigIntent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, slotId);
2225         mTestCarrierConfigReceiver.onReceive(null, carrierConfigIntent);
2226         processAllMessages();
2227     }
2228 
setConfigCarrierStringMmTelRcs(int subId, String packageName)2229     private void setConfigCarrierStringMmTelRcs(int subId, String packageName) {
2230         mCarrierConfigs[subId].putString(
2231                 CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, packageName);
2232     }
2233 
setConfigCarrierStringMmTel(int subId, String packageName)2234     private void setConfigCarrierStringMmTel(int subId, String packageName) {
2235         mCarrierConfigs[subId].putString(
2236                 CarrierConfigManager.KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING, packageName);
2237     }
2238 
setConfigCarrierStringRcs(int subId, String packageName)2239     private void setConfigCarrierStringRcs(int subId, String packageName) {
2240         mCarrierConfigs[subId].putString(
2241                 CarrierConfigManager.KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING, packageName);
2242     }
2243 
convertToHashSet( Set<String> features, int slotId)2244     private HashSet<ImsFeatureConfiguration.FeatureSlotPair> convertToHashSet(
2245             Set<String> features, int slotId) {
2246         return features.stream()
2247                 .map(f -> new ImsFeatureConfiguration.FeatureSlotPair(slotId,
2248                         metadataStringToFeature(f)))
2249                 .collect(Collectors.toCollection(HashSet::new));
2250     }
2251 
convertToFeatureSlotPairs( int slotId, String... features)2252     private HashSet<ImsFeatureConfiguration.FeatureSlotPair> convertToFeatureSlotPairs(
2253             int slotId, String... features) {
2254         return convertToHashSet(new ArraySet<>(features), slotId);
2255     }
2256 
metadataStringToFeature(String f)2257     private int metadataStringToFeature(String f) {
2258         switch (f) {
2259             case ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE:
2260                 return ImsFeature.FEATURE_EMERGENCY_MMTEL;
2261             case ImsResolver.METADATA_MMTEL_FEATURE:
2262                 return ImsFeature.FEATURE_MMTEL;
2263             case ImsResolver.METADATA_RCS_FEATURE:
2264                 return ImsFeature.FEATURE_RCS;
2265         }
2266         return -1;
2267     }
2268 
2269     // Make sure the metadata provided in the service definition creates the associated features in
2270     // the ImsServiceInfo. Note: this only tests for one slot.
isImsServiceInfoEqual(ComponentName name, Set<String> features, ImsResolver.ImsServiceInfo sInfo)2271     private boolean isImsServiceInfoEqual(ComponentName name, Set<String> features,
2272             ImsResolver.ImsServiceInfo sInfo) {
2273         if (!Objects.equals(sInfo.name, name)) {
2274             return false;
2275         }
2276         for (String f : features) {
2277             switch (f) {
2278                 case ImsResolver.METADATA_EMERGENCY_MMTEL_FEATURE:
2279                     if (!sInfo.getSupportedFeatures().contains(
2280                             new ImsFeatureConfiguration.FeatureSlotPair(0,
2281                                     ImsFeature.FEATURE_EMERGENCY_MMTEL))) {
2282                         return false;
2283                     }
2284                     break;
2285                 case ImsResolver.METADATA_MMTEL_FEATURE:
2286                     if (!sInfo.getSupportedFeatures().contains(
2287                             new ImsFeatureConfiguration.FeatureSlotPair(0,
2288                                     ImsFeature.FEATURE_MMTEL))) {
2289                         return false;
2290                     }
2291                     break;
2292                 case ImsResolver.METADATA_RCS_FEATURE:
2293                     if (!sInfo.getSupportedFeatures().contains(
2294                             new ImsFeatureConfiguration.FeatureSlotPair(0,
2295                                     ImsFeature.FEATURE_RCS))) {
2296                         return false;
2297                     }
2298                     break;
2299             }
2300         }
2301         return true;
2302     }
2303 
getResolveInfo(ComponentName name, Set<String> features, boolean isPermissionGranted)2304     private ResolveInfo getResolveInfo(ComponentName name, Set<String> features,
2305             boolean isPermissionGranted) {
2306         ResolveInfo info = new ResolveInfo();
2307         info.serviceInfo = new ServiceInfo();
2308         info.serviceInfo.packageName = name.getPackageName();
2309         info.serviceInfo.name = name.getClassName();
2310         info.serviceInfo.metaData = new Bundle();
2311         for (String s : features) {
2312             info.serviceInfo.metaData.putBoolean(s, true);
2313         }
2314         if (isPermissionGranted) {
2315             info.serviceInfo.permission = Manifest.permission.BIND_IMS_SERVICE;
2316         }
2317         return info;
2318     }
2319 }
2320