• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.services.telephony.rcs;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.fail;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyInt;
25 import static org.mockito.ArgumentMatchers.eq;
26 import static org.mockito.Mockito.doReturn;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.never;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 
32 import android.telephony.AccessNetworkConstants;
33 import android.telephony.ims.ImsException;
34 import android.telephony.ims.ImsReasonInfo;
35 import android.telephony.ims.ImsRegistrationAttributes;
36 import android.telephony.ims.RegistrationManager;
37 import android.telephony.ims.aidl.IImsCapabilityCallback;
38 import android.telephony.ims.aidl.IImsRegistrationCallback;
39 import android.telephony.ims.feature.RcsFeature;
40 import android.telephony.ims.stub.ImsRegistrationImplBase;
41 
42 import androidx.test.runner.AndroidJUnit4;
43 
44 import com.android.TelephonyTestBase;
45 import com.android.ims.FeatureConnector;
46 import com.android.ims.RcsFeatureManager;
47 import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
48 
49 import org.junit.After;
50 import org.junit.Before;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 import org.mockito.ArgumentCaptor;
54 import org.mockito.Captor;
55 import org.mockito.Mock;
56 
57 import java.util.concurrent.Executor;
58 
59 @RunWith(AndroidJUnit4.class)
60 public class RcsFeatureControllerTest extends TelephonyTestBase {
61 
62     private static final int TEST_SUB_ID = 1;
63 
64     private static final ImsReasonInfo REASON_DISCONNECTED = new ImsReasonInfo(
65             ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN, 0, "test");
66 
67     @Mock RcsFeatureManager mFeatureManager;
68     @Mock RcsFeatureController.FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory;
69     @Mock ImsRegistrationCallbackHelper.ImsRegistrationUpdate mRegistrationCallback;
70     @Mock FeatureConnector<RcsFeatureManager> mFeatureConnector;
71     @Mock RcsFeatureController.Feature mMockFeature;
72     @Captor ArgumentCaptor<FeatureConnector.Listener<RcsFeatureManager>> mConnectorListener;
73 
74     private RcsFeatureController.RegistrationHelperFactory mRegistrationFactory =
75             new RcsFeatureController.RegistrationHelperFactory() {
76                 @Override
77                 public ImsRegistrationCallbackHelper create(
78                         ImsRegistrationCallbackHelper.ImsRegistrationUpdate cb, Executor executor) {
79                     // Run on current thread for testing.
80                     return new ImsRegistrationCallbackHelper(mRegistrationCallback, Runnable::run);
81                 }
82             };
83 
84     @Before
setUp()85     public void setUp() throws Exception {
86         super.setUp();
87     }
88 
89     @After
tearDown()90     public void tearDown() throws Exception {
91         super.tearDown();
92     }
93 
94     @Test
testRcsFeatureManagerConnectDisconnect()95     public void testRcsFeatureManagerConnectDisconnect() throws Exception {
96         RcsFeatureController controller = createFeatureController();
97         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
98         verify(mMockFeature).onRcsDisconnected();
99         // Connect the RcsFeatureManager
100         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
101 
102         verify(mFeatureManager).updateCapabilities(TEST_SUB_ID);
103         verify(mFeatureManager).registerImsRegistrationCallback(any());
104         verify(mMockFeature).onRcsConnected(mFeatureManager);
105 
106         // Disconnect
107         mConnectorListener.getValue().connectionUnavailable(
108                 FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
109 
110         verify(mFeatureManager).unregisterImsRegistrationCallback(any());
111         verify(mMockFeature, times(2)).onRcsDisconnected();
112     }
113 
114     @Test
testFeatureManagerConnectedAddRemoveFeature()115     public void testFeatureManagerConnectedAddRemoveFeature() throws Exception {
116         RcsFeatureController controller = createFeatureController();
117         // Connect the RcsFeatureManager
118         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
119         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
120 
121         verify(mMockFeature).onRcsConnected(mFeatureManager);
122         assertEquals(mMockFeature, controller.getFeature(RcsFeatureController.Feature.class));
123 
124         controller.removeFeature(RcsFeatureController.Feature.class);
125         verify(mMockFeature).onDestroy();
126         assertNull(controller.getFeature(RcsFeatureController.Feature.class));
127     }
128 
129     @Test
testFeatureManagerConnectedRegister()130     public void testFeatureManagerConnectedRegister() throws Exception {
131         RcsFeatureController controller = createFeatureController();
132         IImsRegistrationCallback regCb = mock(IImsRegistrationCallback.class);
133         IImsCapabilityCallback capCb = mock(IImsCapabilityCallback.class);
134         // Connect the RcsFeatureManager
135         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
136 
137         try {
138             controller.registerImsRegistrationCallback(TEST_SUB_ID, regCb);
139             controller.registerRcsAvailabilityCallback(TEST_SUB_ID, capCb);
140             controller.isCapable(RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE,
141                     ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
142             controller.isAvailable(RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE,
143                     ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
144             controller.getRegistrationTech(integer -> {
145             });
146             verify(mFeatureManager).registerImsRegistrationCallback(TEST_SUB_ID, regCb);
147             verify(mFeatureManager).registerRcsAvailabilityCallback(TEST_SUB_ID, capCb);
148             verify(mFeatureManager).isCapable(
149                     RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE,
150                     ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
151             verify(mFeatureManager).isAvailable(
152                     RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE,
153                     ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
154             verify(mFeatureManager).getImsRegistrationTech(any());
155         } catch (ImsException e) {
156             fail("ImsException not expected.");
157         }
158 
159         controller.unregisterImsRegistrationCallback(TEST_SUB_ID, regCb);
160         controller.unregisterRcsAvailabilityCallback(TEST_SUB_ID, capCb);
161         verify(mFeatureManager).unregisterImsRegistrationCallback(TEST_SUB_ID, regCb);
162         verify(mFeatureManager).unregisterRcsAvailabilityCallback(TEST_SUB_ID, capCb);
163     }
164 
165     @Test
testFeatureManagerConnectedHelper()166     public void testFeatureManagerConnectedHelper() throws Exception {
167         RcsFeatureController controller = createFeatureController();
168         // Connect the RcsFeatureManager
169         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
170         ArgumentCaptor<IImsRegistrationCallback> captor =
171                 ArgumentCaptor.forClass(IImsRegistrationCallback.class);
172         verify(mFeatureManager).registerImsRegistrationCallback(captor.capture());
173         assertNotNull(captor.getValue());
174 
175         captor.getValue().onDeregistered(REASON_DISCONNECTED, 0, 0);
176         controller.getRegistrationState(result -> {
177             assertNotNull(result);
178             assertEquals(RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED, result.intValue());
179         });
180         verify(mRegistrationCallback).handleImsUnregistered(eq(REASON_DISCONNECTED),
181                 anyInt(), anyInt());
182 
183         ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
184                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE).build();
185         captor.getValue().onRegistering(attr);
186         controller.getRegistrationState(result -> {
187             assertNotNull(result);
188             assertEquals(RegistrationManager.REGISTRATION_STATE_REGISTERING, result.intValue());
189         });
190         verify(mRegistrationCallback).handleImsRegistering(
191                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
192 
193         captor.getValue().onRegistered(attr);
194         controller.getRegistrationState(result -> {
195             assertNotNull(result);
196             assertEquals(RegistrationManager.REGISTRATION_STATE_REGISTERED, result.intValue());
197         });
198         verify(mRegistrationCallback).handleImsRegistered(attr);
199     }
200 
201     @Test
testFeatureManagerDisconnectedAddFeature()202     public void testFeatureManagerDisconnectedAddFeature() {
203         RcsFeatureController controller = createFeatureController();
204         // Disconnect the RcsFeatureManager
205         mConnectorListener.getValue().connectionUnavailable(
206                 FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
207         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
208 
209         verify(mMockFeature).onRcsDisconnected();
210     }
211 
212     @Test
testFeatureManagerDisconnectedException()213     public void testFeatureManagerDisconnectedException() {
214         RcsFeatureController controller = createFeatureController();
215         IImsRegistrationCallback regCb = mock(IImsRegistrationCallback.class);
216         IImsCapabilityCallback capCb = mock(IImsCapabilityCallback.class);
217         // Disconnect the RcsFeatureManager
218         mConnectorListener.getValue().connectionUnavailable(
219                 FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
220 
221         try {
222             controller.registerImsRegistrationCallback(TEST_SUB_ID, null /*callback*/);
223             fail("ImsException expected for IMS registration.");
224         } catch (ImsException e) {
225             //expected
226         }
227         try {
228             controller.registerRcsAvailabilityCallback(TEST_SUB_ID, null /*callback*/);
229             fail("ImsException expected for availability");
230         } catch (ImsException e) {
231             //expected
232         }
233         try {
234             controller.isCapable(RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE,
235                     ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
236             fail("ImsException expected for capability check");
237         } catch (ImsException e) {
238             //expected
239         }
240         try {
241             controller.isAvailable(RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE,
242                     ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
243             fail("ImsException expected for availability check");
244         } catch (ImsException e) {
245             //expected
246         }
247         controller.getRegistrationTech(integer -> {
248             assertNotNull(integer);
249             assertEquals(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, integer.intValue());
250         });
251         controller.unregisterImsRegistrationCallback(TEST_SUB_ID, regCb);
252         controller.unregisterRcsAvailabilityCallback(TEST_SUB_ID, capCb);
253         verify(mFeatureManager, never()).unregisterImsRegistrationCallback(TEST_SUB_ID, regCb);
254         verify(mFeatureManager, never()).unregisterRcsAvailabilityCallback(TEST_SUB_ID, capCb);
255     }
256 
257     @Test
testCarrierConfigChanged()258     public void testCarrierConfigChanged() throws Exception {
259         RcsFeatureController controller = createFeatureController();
260         // Connect the RcsFeatureManager
261         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
262         verify(mFeatureManager).updateCapabilities(TEST_SUB_ID);
263         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
264 
265         controller.onCarrierConfigChangedForSubscription();
266 
267         verify(mFeatureManager, times(2)).updateCapabilities(TEST_SUB_ID);
268         verify(mMockFeature).onCarrierConfigChanged();
269         verify(mMockFeature, never()).onAssociatedSubscriptionUpdated(anyInt());
270     }
271 
272     @Test
testChangeSubId()273     public void testChangeSubId() throws Exception {
274         RcsFeatureController controller = createFeatureController();
275         // Connect the RcsFeatureManager
276         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
277         verify(mFeatureManager).updateCapabilities(TEST_SUB_ID);
278         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
279 
280         controller.updateAssociatedSubscription(2 /*new subId*/);
281 
282         verify(mFeatureManager).updateCapabilities(2 /*new subId*/);
283         verify(mMockFeature).onAssociatedSubscriptionUpdated(2 /*new subId*/);
284     }
285 
286     @Test
testDestroy()287     public void testDestroy() throws Exception {
288         RcsFeatureController controller = createFeatureController();
289         // Connect the RcsFeatureManager
290         mConnectorListener.getValue().connectionReady(mFeatureManager, TEST_SUB_ID);
291         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
292         controller.destroy();
293 
294         verify(mFeatureConnector).disconnect();
295         verify(mMockFeature).onRcsDisconnected();
296         verify(mMockFeature).onDestroy();
297         assertNull(controller.getFeature(RcsFeatureController.Feature.class));
298     }
299 
createFeatureController()300     private RcsFeatureController createFeatureController() {
301         RcsFeatureController controller = new RcsFeatureController(mContext, 0 /*slotId*/,
302                 TEST_SUB_ID, mRegistrationFactory);
303         controller.setFeatureConnectorFactory(mFeatureFactory);
304         doReturn(mFeatureConnector).when(mFeatureFactory).create(any(), anyInt(),
305                 mConnectorListener.capture(), any(), any());
306         controller.connect();
307         assertNotNull(mConnectorListener.getValue());
308         return controller;
309     }
310 }
311