blob: 0671a4ed5cbe8f04c71150469cb9d56a3c471b89 [file] [log] [blame]
Santos Cordonf0f99f32016-02-18 16:13:57 -08001/*
2 * Copyright (C) 2016 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
17package com.android.server.telecom.tests;
18
Santos Cordon501b9b32016-03-07 14:40:07 -080019import android.Manifest;
Santos Cordonf0f99f32016-02-18 16:13:57 -080020import android.content.ComponentName;
Hall Liu28b82f02016-07-26 17:38:56 -070021import android.content.ContentResolver;
Santos Cordonf0f99f32016-02-18 16:13:57 -080022import android.content.Context;
23import android.content.Intent;
24import android.content.ServiceConnection;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
Santos Cordon501b9b32016-03-07 14:40:07 -080027import android.content.pm.ServiceInfo;
Santos Cordonf0f99f32016-02-18 16:13:57 -080028import android.content.res.Resources;
29import android.os.Bundle;
Santos Cordon501b9b32016-03-07 14:40:07 -080030import android.os.IBinder;
mike dooley21fb1af2016-12-05 14:25:53 -080031import android.os.Handler;
32import android.os.Looper;
Santos Cordonf0f99f32016-02-18 16:13:57 -080033import android.os.UserHandle;
Santos Cordonf0f99f32016-02-18 16:13:57 -080034import android.telecom.InCallService;
Hall Liu28b82f02016-07-26 17:38:56 -070035import android.telecom.ParcelableCall;
Santos Cordonf0f99f32016-02-18 16:13:57 -080036import android.telecom.PhoneAccountHandle;
37import android.telecom.TelecomManager;
38import android.test.mock.MockContext;
Hall Liua3799ae2016-03-16 11:37:51 -070039import android.test.suitebuilder.annotation.MediumTest;
Tyler Gunnf15dc332016-06-07 16:01:41 -070040import android.text.TextUtils;
Santos Cordonf0f99f32016-02-18 16:13:57 -080041
Santos Cordon501b9b32016-03-07 14:40:07 -080042import com.android.internal.telecom.IInCallAdapter;
43import com.android.internal.telecom.IInCallService;
Hall Liu3f54d492016-09-06 17:12:46 -070044import com.android.server.telecom.Analytics;
Santos Cordonf0f99f32016-02-18 16:13:57 -080045import com.android.server.telecom.BluetoothHeadsetProxy;
46import com.android.server.telecom.Call;
47import com.android.server.telecom.CallsManager;
Hall Liu7c928322016-12-06 18:15:39 -080048import com.android.server.telecom.DefaultDialerCache;
mike dooley66f26d12016-12-19 13:25:47 -080049import com.android.server.telecom.EmergencyCallHelper;
Santos Cordonf0f99f32016-02-18 16:13:57 -080050import com.android.server.telecom.InCallController;
51import com.android.server.telecom.PhoneAccountRegistrar;
52import com.android.server.telecom.R;
53import com.android.server.telecom.SystemStateProvider;
54import com.android.server.telecom.TelecomSystem;
Hall Liu28b82f02016-07-26 17:38:56 -070055import com.android.server.telecom.Timeouts;
Santos Cordonf0f99f32016-02-18 16:13:57 -080056
Hall Liuc8a396b2017-12-27 18:23:28 -080057import org.junit.After;
58import org.junit.Before;
59import org.junit.Test;
60import org.junit.runner.RunWith;
61import org.junit.runners.JUnit4;
Santos Cordonf0f99f32016-02-18 16:13:57 -080062import org.mockito.ArgumentCaptor;
63import org.mockito.Mock;
64import org.mockito.MockitoAnnotations;
Tyler Gunnf15dc332016-06-07 16:01:41 -070065import org.mockito.invocation.InvocationOnMock;
66import org.mockito.stubbing.Answer;
Santos Cordonf0f99f32016-02-18 16:13:57 -080067
Hall Liu28b82f02016-07-26 17:38:56 -070068import java.util.Collections;
Santos Cordonf0f99f32016-02-18 16:13:57 -080069import java.util.LinkedList;
70
Hall Liuc8a396b2017-12-27 18:23:28 -080071import static org.junit.Assert.assertEquals;
72import static org.junit.Assert.assertNull;
Brad Ebingerd0fe76e2017-03-20 13:17:15 -070073import static org.mockito.ArgumentMatchers.nullable;
Santos Cordonf0f99f32016-02-18 16:13:57 -080074import static org.mockito.Matchers.any;
Santos Cordonf0f99f32016-02-18 16:13:57 -080075import static org.mockito.Matchers.anyInt;
76import static org.mockito.Matchers.anyString;
77import static org.mockito.Matchers.eq;
Tyler Gunnf15dc332016-06-07 16:01:41 -070078import static org.mockito.Mockito.doAnswer;
Santos Cordonf0f99f32016-02-18 16:13:57 -080079import static org.mockito.Mockito.doReturn;
80import static org.mockito.Mockito.mock;
81import static org.mockito.Mockito.never;
82import static org.mockito.Mockito.times;
83import static org.mockito.Mockito.when;
84import static org.mockito.Mockito.verify;
85
Hall Liuc8a396b2017-12-27 18:23:28 -080086@RunWith(JUnit4.class)
Santos Cordonf0f99f32016-02-18 16:13:57 -080087public class InCallControllerTests extends TelecomTestCase {
88 @Mock CallsManager mMockCallsManager;
89 @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
90 @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;
91 @Mock SystemStateProvider mMockSystemStateProvider;
92 @Mock PackageManager mMockPackageManager;
93 @Mock Call mMockCall;
94 @Mock Resources mMockResources;
95 @Mock MockContext mMockContext;
Hall Liu28b82f02016-07-26 17:38:56 -070096 @Mock Timeouts.Adapter mTimeoutsAdapter;
Hall Liu7c928322016-12-06 18:15:39 -080097 @Mock DefaultDialerCache mDefaultDialerCache;
Santos Cordonf0f99f32016-02-18 16:13:57 -080098
99 private static final int CURRENT_USER_ID = 900973;
100 private static final String DEF_PKG = "defpkg";
101 private static final String DEF_CLASS = "defcls";
Santos Cordon501b9b32016-03-07 14:40:07 -0800102 private static final String SYS_PKG = "syspkg";
103 private static final String SYS_CLASS = "syscls";
Santos Cordonf0f99f32016-02-18 16:13:57 -0800104 private static final PhoneAccountHandle PA_HANDLE =
105 new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"), "pa_id");
106
107 private UserHandle mUserHandle = UserHandle.of(CURRENT_USER_ID);
108 private InCallController mInCallController;
Brad Ebinger6e8f3d72016-06-20 11:35:42 -0700109 private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {};
mike dooley66f26d12016-12-19 13:25:47 -0800110 private EmergencyCallHelper mEmergencyCallHelper;
Santos Cordonf0f99f32016-02-18 16:13:57 -0800111
112 @Override
Hall Liuc8a396b2017-12-27 18:23:28 -0800113 @Before
Santos Cordonf0f99f32016-02-18 16:13:57 -0800114 public void setUp() throws Exception {
115 super.setUp();
116 MockitoAnnotations.initMocks(this);
Hall Liu3f54d492016-09-06 17:12:46 -0700117 when(mMockCall.getAnalytics()).thenReturn(new Analytics.CallInfo());
Santos Cordonf0f99f32016-02-18 16:13:57 -0800118 doReturn(mMockResources).when(mMockContext).getResources();
Santos Cordon501b9b32016-03-07 14:40:07 -0800119 doReturn(SYS_PKG).when(mMockResources).getString(R.string.ui_default_package);
120 doReturn(SYS_CLASS).when(mMockResources).getString(R.string.incall_default_class);
Brad Ebinger782f9112017-05-30 15:35:38 -0700121 doReturn(true).when(mMockResources).getBoolean(R.bool.grant_location_permission_enabled);
mike dooley66f26d12016-12-19 13:25:47 -0800122 mEmergencyCallHelper = new EmergencyCallHelper(mMockContext, SYS_PKG,
mike dooley21fb1af2016-12-05 14:25:53 -0800123 mTimeoutsAdapter);
Santos Cordonf0f99f32016-02-18 16:13:57 -0800124 mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
mike dooley21fb1af2016-12-05 14:25:53 -0800125 mMockSystemStateProvider, mDefaultDialerCache, mTimeoutsAdapter,
mike dooley66f26d12016-12-19 13:25:47 -0800126 mEmergencyCallHelper);
Santos Cordonf0f99f32016-02-18 16:13:57 -0800127 }
128
129 @Override
Hall Liuc8a396b2017-12-27 18:23:28 -0800130 @After
Santos Cordonf0f99f32016-02-18 16:13:57 -0800131 public void tearDown() throws Exception {
132 super.tearDown();
133 }
134
Hall Liua3799ae2016-03-16 11:37:51 -0700135 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800136 @Test
Santos Cordonf0f99f32016-02-18 16:13:57 -0800137 public void testBindToService_NoServicesFound_IncomingCall() throws Exception {
138 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
139 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
140 when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
141 when(mMockCall.isIncoming()).thenReturn(true);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700142 when(mMockCall.isExternalCall()).thenReturn(false);
mike dooley21fb1af2016-12-05 14:25:53 -0800143 when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
144 .thenReturn(300_000L);
Santos Cordonf0f99f32016-02-18 16:13:57 -0800145
Tyler Gunnf15dc332016-06-07 16:01:41 -0700146 setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
Santos Cordonf0f99f32016-02-18 16:13:57 -0800147 mInCallController.bindToServices(mMockCall);
148
149 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
150 verify(mMockContext).bindServiceAsUser(
151 bindIntentCaptor.capture(),
152 any(ServiceConnection.class),
153 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
154 eq(UserHandle.CURRENT));
155
156 Intent bindIntent = bindIntentCaptor.getValue();
157 assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
Santos Cordon501b9b32016-03-07 14:40:07 -0800158 assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
159 assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
Santos Cordonf0f99f32016-02-18 16:13:57 -0800160 assertNull(bindIntent.getExtras());
161 }
162
Hall Liua3799ae2016-03-16 11:37:51 -0700163 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800164 @Test
Santos Cordonf0f99f32016-02-18 16:13:57 -0800165 public void testBindToService_NoServicesFound_OutgoingCall() throws Exception {
166 Bundle callExtras = new Bundle();
167 callExtras.putBoolean("whatever", true);
168
169 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
170 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
171 when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
172 when(mMockCall.isIncoming()).thenReturn(false);
173 when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
174 when(mMockCall.getIntentExtras()).thenReturn(callExtras);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700175 when(mMockCall.isExternalCall()).thenReturn(false);
mike dooley21fb1af2016-12-05 14:25:53 -0800176 when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
177 .thenReturn(300_000L);
Santos Cordonf0f99f32016-02-18 16:13:57 -0800178
179 Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700180 setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
Santos Cordonf0f99f32016-02-18 16:13:57 -0800181 mInCallController.bindToServices(mMockCall);
182
183 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
184 verify(mMockContext).bindServiceAsUser(
185 bindIntentCaptor.capture(),
186 any(ServiceConnection.class),
187 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
188 eq(UserHandle.CURRENT));
189
190 Intent bindIntent = bindIntentCaptor.getValue();
191 assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
Santos Cordon501b9b32016-03-07 14:40:07 -0800192 assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
193 assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
194 assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
195 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
196 assertEquals(callExtras, bindIntent.getExtras().getParcelable(
197 TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
198 }
199
200 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800201 @Test
Santos Cordon501b9b32016-03-07 14:40:07 -0800202 public void testBindToService_DefaultDialer_NoEmergency() throws Exception {
203 Bundle callExtras = new Bundle();
204 callExtras.putBoolean("whatever", true);
205
206 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
207 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
208 when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
209 when(mMockCall.isIncoming()).thenReturn(false);
210 when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
211 when(mMockCall.getIntentExtras()).thenReturn(callExtras);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700212 when(mMockCall.isExternalCall()).thenReturn(false);
Hall Liu7c928322016-12-06 18:15:39 -0800213 when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
Santos Cordon501b9b32016-03-07 14:40:07 -0800214 .thenReturn(DEF_PKG);
215 when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
216 anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
217
Tyler Gunnf15dc332016-06-07 16:01:41 -0700218 setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
Santos Cordon501b9b32016-03-07 14:40:07 -0800219 mInCallController.bindToServices(mMockCall);
220
221 // Query for the different InCallServices
222 ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700223 verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
Santos Cordon501b9b32016-03-07 14:40:07 -0800224 queryIntentCaptor.capture(),
225 eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
226
227 // Verify call for default dialer InCallService
228 assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
229 // Verify call for car-mode InCallService
230 assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
231 // Verify call for non-UI InCallServices
232 assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
233
234 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
235 verify(mMockContext, times(1)).bindServiceAsUser(
236 bindIntentCaptor.capture(),
237 any(ServiceConnection.class),
238 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
239 eq(UserHandle.CURRENT));
240
241 Intent bindIntent = bindIntentCaptor.getValue();
242 assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
Santos Cordonf0f99f32016-02-18 16:13:57 -0800243 assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
244 assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
245 assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
246 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
247 assertEquals(callExtras, bindIntent.getExtras().getParcelable(
248 TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
249 }
Santos Cordon501b9b32016-03-07 14:40:07 -0800250
251 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800252 @Test
Santos Cordon501b9b32016-03-07 14:40:07 -0800253 public void testBindToService_SystemDialer_Emergency() throws Exception {
254 Bundle callExtras = new Bundle();
255 callExtras.putBoolean("whatever", true);
256
257 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
258 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
259 when(mMockCallsManager.hasEmergencyCall()).thenReturn(true);
mike dooley21fb1af2016-12-05 14:25:53 -0800260 when(mMockCall.isEmergencyCall()).thenReturn(true);
Santos Cordon501b9b32016-03-07 14:40:07 -0800261 when(mMockCall.isIncoming()).thenReturn(false);
262 when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
263 when(mMockCall.getIntentExtras()).thenReturn(callExtras);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700264 when(mMockCall.isExternalCall()).thenReturn(false);
Hall Liu7c928322016-12-06 18:15:39 -0800265 when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
Santos Cordon501b9b32016-03-07 14:40:07 -0800266 .thenReturn(DEF_PKG);
267 when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
268 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
269 eq(UserHandle.CURRENT))).thenReturn(true);
mike dooley21fb1af2016-12-05 14:25:53 -0800270 when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
271 .thenReturn(300_000L);
Santos Cordon501b9b32016-03-07 14:40:07 -0800272
Tyler Gunnf15dc332016-06-07 16:01:41 -0700273 setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
mike dooley21fb1af2016-12-05 14:25:53 -0800274 setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700275
Santos Cordon501b9b32016-03-07 14:40:07 -0800276 mInCallController.bindToServices(mMockCall);
277
278 // Query for the different InCallServices
279 ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700280 verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
Santos Cordon501b9b32016-03-07 14:40:07 -0800281 queryIntentCaptor.capture(),
282 eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
283
284 // Verify call for default dialer InCallService
285 assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
286 // Verify call for car-mode InCallService
287 assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
288 // Verify call for non-UI InCallServices
289 assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
290
291 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
292 verify(mMockContext, times(1)).bindServiceAsUser(
293 bindIntentCaptor.capture(),
294 any(ServiceConnection.class),
295 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
296 eq(UserHandle.CURRENT));
297
298 Intent bindIntent = bindIntentCaptor.getValue();
299 assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
300 assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
301 assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
302 assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
303 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
304 assertEquals(callExtras, bindIntent.getExtras().getParcelable(
305 TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
mike dooley21fb1af2016-12-05 14:25:53 -0800306
307 verify(mMockPackageManager).grantRuntimePermission(eq(SYS_PKG),
308 eq(Manifest.permission.ACCESS_FINE_LOCATION), eq(mUserHandle));
309
310 // Pretend that the call has gone away.
311 when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
312 mInCallController.onCallRemoved(mMockCall);
313 waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT);
314
315 verify(mMockPackageManager).revokeRuntimePermission(eq(SYS_PKG),
316 eq(Manifest.permission.ACCESS_FINE_LOCATION), eq(mUserHandle));
Santos Cordon501b9b32016-03-07 14:40:07 -0800317 }
318
319 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800320 @Test
Santos Cordon501b9b32016-03-07 14:40:07 -0800321 public void testBindToService_DefaultDialer_FallBackToSystem() throws Exception {
322 Bundle callExtras = new Bundle();
323 callExtras.putBoolean("whatever", true);
324
325 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
326 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
327 when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
Hall Liu28b82f02016-07-26 17:38:56 -0700328 when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
329 when(mMockCallsManager.getAudioState()).thenReturn(null);
330 when(mMockCallsManager.canAddCall()).thenReturn(false);
Santos Cordon501b9b32016-03-07 14:40:07 -0800331 when(mMockCall.isIncoming()).thenReturn(false);
332 when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
333 when(mMockCall.getIntentExtras()).thenReturn(callExtras);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700334 when(mMockCall.isExternalCall()).thenReturn(false);
Hall Liu28b82f02016-07-26 17:38:56 -0700335 when(mMockCall.getConferenceableCalls()).thenReturn(Collections.emptyList());
Hall Liu7c928322016-12-06 18:15:39 -0800336 when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
Santos Cordon501b9b32016-03-07 14:40:07 -0800337 .thenReturn(DEF_PKG);
338 when(mMockContext.bindServiceAsUser(
339 any(Intent.class), any(ServiceConnection.class), anyInt(), any(UserHandle.class)))
340 .thenReturn(true);
341
Tyler Gunnf15dc332016-06-07 16:01:41 -0700342 setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
Santos Cordon501b9b32016-03-07 14:40:07 -0800343 mInCallController.bindToServices(mMockCall);
344
345 // Query for the different InCallServices
346 ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700347 verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
Santos Cordon501b9b32016-03-07 14:40:07 -0800348 queryIntentCaptor.capture(),
349 eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
350
351 // Verify call for default dialer InCallService
352 assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
353 // Verify call for car-mode InCallService
354 assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
355 // Verify call for non-UI InCallServices
356 assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
357
358 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
359 ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
360 ArgumentCaptor.forClass(ServiceConnection.class);
361 verify(mMockContext, times(1)).bindServiceAsUser(
362 bindIntentCaptor.capture(),
363 serviceConnectionCaptor.capture(),
364 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
365 eq(UserHandle.CURRENT));
366
367 Intent bindIntent = bindIntentCaptor.getValue();
368 assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
369 assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
370 assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
371 assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
372 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
373 assertEquals(callExtras, bindIntent.getExtras().getParcelable(
374 TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
375
376 // We have a ServiceConnection for the default dialer, lets start the connection, and then
377 // simulate a crash so that we fallback to system.
378 ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
379 ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
380 IBinder mockBinder = mock(IBinder.class);
381 IInCallService mockInCallService = mock(IInCallService.class);
382 when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
383
384
385 // Start the connection with IInCallService
386 serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
387 verify(mockInCallService).setInCallAdapter(any(IInCallAdapter.class));
388
389 // Now crash the damn thing!
390 serviceConnection.onServiceDisconnected(defDialerComponentName);
391
392 ArgumentCaptor<Intent> bindIntentCaptor2 = ArgumentCaptor.forClass(Intent.class);
393 verify(mMockContext, times(2)).bindServiceAsUser(
394 bindIntentCaptor2.capture(),
395 any(ServiceConnection.class),
396 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
397 eq(UserHandle.CURRENT));
398
399 bindIntent = bindIntentCaptor2.getValue();
400 assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
401 assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
402 }
Tyler Gunnf15dc332016-06-07 16:01:41 -0700403
404 /**
405 * Ensures that the {@link InCallController} will bind to an {@link InCallService} which
406 * supports external calls.
407 */
408 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800409 @Test
Tyler Gunnf15dc332016-06-07 16:01:41 -0700410 public void testBindToService_IncludeExternal() throws Exception {
411 setupMocks(true /* isExternalCall */);
412 setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
413 mInCallController.bindToServices(mMockCall);
414
415 // Query for the different InCallServices
416 ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
417 verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
418 queryIntentCaptor.capture(),
419 eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
420
421 // Verify call for default dialer InCallService
422 assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
423 // Verify call for car-mode InCallService
424 assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
425 // Verify call for non-UI InCallServices
426 assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
427
428 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
429 verify(mMockContext, times(1)).bindServiceAsUser(
430 bindIntentCaptor.capture(),
431 any(ServiceConnection.class),
432 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
433 eq(UserHandle.CURRENT));
434
435 Intent bindIntent = bindIntentCaptor.getValue();
436 assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
437 assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
438 assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
439 }
440
Hall Liu28b82f02016-07-26 17:38:56 -0700441 /**
442 * Make sure that if a call goes away before the in-call service finishes binding and another
443 * call gets connected soon after, the new call will still be sent to the in-call service.
444 */
445 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800446 @Test
Hall Liu28b82f02016-07-26 17:38:56 -0700447 public void testUnbindDueToCallDisconnect() throws Exception {
448 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
449 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
450 when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
451 when(mMockCall.isIncoming()).thenReturn(true);
452 when(mMockCall.isExternalCall()).thenReturn(false);
Hall Liu7c928322016-12-06 18:15:39 -0800453 when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
Brad Ebingerd0fe76e2017-03-20 13:17:15 -0700454 when(mMockContext.bindServiceAsUser(nullable(Intent.class),
455 nullable(ServiceConnection.class), anyInt(), nullable(UserHandle.class)))
Hall Liu28b82f02016-07-26 17:38:56 -0700456 .thenReturn(true);
Brad Ebingerd0fe76e2017-03-20 13:17:15 -0700457 when(mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
458 nullable(ContentResolver.class))).thenReturn(500L);
Hall Liu28b82f02016-07-26 17:38:56 -0700459
460 when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
461 setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
462 mInCallController.bindToServices(mMockCall);
463
464 ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
465 ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
466 ArgumentCaptor.forClass(ServiceConnection.class);
467 verify(mMockContext, times(1)).bindServiceAsUser(
468 bindIntentCaptor.capture(),
469 serviceConnectionCaptor.capture(),
470 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
471 eq(UserHandle.CURRENT));
472
473 // Pretend that the call has gone away.
474 when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
475 mInCallController.onCallRemoved(mMockCall);
476
477 // Start the connection, make sure we don't unbind, and make sure that we don't send
478 // anything to the in-call service yet.
479 ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
480 ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
481 IBinder mockBinder = mock(IBinder.class);
482 IInCallService mockInCallService = mock(IInCallService.class);
483 when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
484
485 serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
Brad Ebingerd0fe76e2017-03-20 13:17:15 -0700486 verify(mockInCallService).setInCallAdapter(nullable(IInCallAdapter.class));
Hall Liu28b82f02016-07-26 17:38:56 -0700487 verify(mMockContext, never()).unbindService(serviceConnection);
488 verify(mockInCallService, never()).addCall(any(ParcelableCall.class));
489
490 // Now, we add in the call again and make sure that it's sent to the InCallService.
491 when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
492 mInCallController.onCallAdded(mMockCall);
493 verify(mockInCallService).addCall(any(ParcelableCall.class));
494 }
495
Tyler Gunnf15dc332016-06-07 16:01:41 -0700496 private void setupMocks(boolean isExternalCall) {
497 when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
498 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
499 when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
500 when(mMockCall.isIncoming()).thenReturn(false);
501 when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
Hall Liu7c928322016-12-06 18:15:39 -0800502 when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
Tyler Gunnf15dc332016-06-07 16:01:41 -0700503 when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
504 anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
505 when(mMockCall.isExternalCall()).thenReturn(isExternalCall);
506 }
507
508 private ResolveInfo getDefResolveInfo(final boolean includeExternalCalls) {
509 return new ResolveInfo() {{
510 serviceInfo = new ServiceInfo();
511 serviceInfo.packageName = DEF_PKG;
512 serviceInfo.name = DEF_CLASS;
513 serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
514 serviceInfo.metaData = new Bundle();
515 serviceInfo.metaData.putBoolean(
516 TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
517 if (includeExternalCalls) {
518 serviceInfo.metaData.putBoolean(
519 TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
520 }
521 }};
522 }
523
524 private ResolveInfo getSysResolveinfo() {
525 return new ResolveInfo() {{
526 serviceInfo = new ServiceInfo();
527 serviceInfo.packageName = SYS_PKG;
528 serviceInfo.name = SYS_CLASS;
529 serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
530 }};
531 }
532
533 private void setupMockPackageManager(final boolean useDefaultDialer,
534 final boolean useSystemDialer, final boolean includeExternalCalls) {
535
536 doAnswer(new Answer() {
537 @Override
538 public Object answer(InvocationOnMock invocation) throws Throwable {
539 Object[] args = invocation.getArguments();
540 Intent intent = (Intent) args[0];
541 String packageName = intent.getPackage();
542 ComponentName componentName = intent.getComponent();
543 if (componentName != null) {
544 packageName = componentName.getPackageName();
545 }
546 LinkedList<ResolveInfo> resolveInfo = new LinkedList<ResolveInfo>();
547 if (!TextUtils.isEmpty(packageName)) {
548 if ((TextUtils.isEmpty(packageName) || packageName.equals(DEF_PKG)) &&
549 useDefaultDialer) {
550 resolveInfo.add(getDefResolveInfo(includeExternalCalls));
551 }
552
553 if ((TextUtils.isEmpty(packageName) || packageName.equals(SYS_PKG)) &&
554 useSystemDialer) {
555 resolveInfo.add(getSysResolveinfo());
556 }
557 }
558 return resolveInfo;
559 }
560 }).when(mMockPackageManager).queryIntentServicesAsUser(
561 any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
562 }
mike dooley21fb1af2016-12-05 14:25:53 -0800563
564 private void setupMockPackageManagerLocationPermission(final String pkg,
565 final boolean granted) {
566 when(mMockPackageManager.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, pkg))
567 .thenReturn(granted
568 ? PackageManager.PERMISSION_GRANTED
569 : PackageManager.PERMISSION_DENIED);
570 }
Santos Cordonf0f99f32016-02-18 16:13:57 -0800571}