1 /* 2 * Copyright (C) 2021 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.server.telecom.tests; 18 19 import static junit.framework.Assert.assertEquals; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyString; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.never; 27 import static org.mockito.Mockito.times; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.when; 30 31 import android.Manifest; 32 import android.content.ComponentName; 33 import android.content.Intent; 34 import android.content.ServiceConnection; 35 import android.content.pm.ResolveInfo; 36 import android.content.pm.ServiceInfo; 37 import android.os.IBinder; 38 import android.os.RemoteException; 39 import android.os.UserHandle; 40 import android.telecom.ParcelableCall; 41 42 import com.android.internal.telecom.ICallDiagnosticService; 43 import com.android.server.telecom.Call; 44 import com.android.server.telecom.CallDiagnosticServiceController; 45 import com.android.server.telecom.TelecomSystem; 46 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.junit.runners.JUnit4; 51 import org.mockito.ArgumentCaptor; 52 import org.mockito.Mock; 53 import org.mockito.Mockito; 54 import org.mockito.MockitoAnnotations; 55 56 import java.util.ArrayList; 57 import java.util.List; 58 59 @RunWith(JUnit4.class) 60 public class CallDiagnosticServiceControllerTest { 61 private static final String TEST_CDS_PACKAGE = "com.test.stuff"; 62 private static final String TEST_PACKAGE = "com.android.telecom.calldiagnosticservice"; 63 private static final String TEST_CLASS = 64 "com.android.telecom.calldiagnosticservice.TestService"; 65 private static final ComponentName TEST_COMPONENT = new ComponentName(TEST_PACKAGE, TEST_CLASS); 66 private static final List<ResolveInfo> RESOLVE_INFOS = new ArrayList<>(); 67 private static final ResolveInfo TEST_RESOLVE_INFO = new ResolveInfo(); 68 static { 69 TEST_RESOLVE_INFO.serviceInfo = new ServiceInfo(); 70 TEST_RESOLVE_INFO.serviceInfo.packageName = TEST_PACKAGE; 71 TEST_RESOLVE_INFO.serviceInfo.name = TEST_CLASS; 72 TEST_RESOLVE_INFO.serviceInfo.permission = Manifest.permission.BIND_CALL_DIAGNOSTIC_SERVICE; 73 RESOLVE_INFOS.add(TEST_RESOLVE_INFO); 74 } 75 private static final String ID_1 = "1"; 76 private static final String ID_2 = "2"; 77 78 @Mock 79 private CallDiagnosticServiceController.ContextProxy mContextProxy; 80 @Mock 81 private Call mCall; 82 @Mock 83 private Call mCallTwo; 84 @Mock 85 private ICallDiagnosticService mICallDiagnosticService; 86 private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; 87 88 private CallDiagnosticServiceController mCallDiagnosticService; 89 private ServiceConnection mServiceConnection; 90 91 @Before setUp()92 public void setUp() throws Exception { 93 MockitoAnnotations.initMocks(this); 94 95 when(mCall.getId()).thenReturn(ID_1); 96 when(mCall.isSimCall()).thenReturn(true); 97 when(mCall.isExternalCall()).thenReturn(false); 98 99 when(mCallTwo.getId()).thenReturn(ID_2); 100 when(mCallTwo.isSimCall()).thenReturn(true); 101 when(mCallTwo.isExternalCall()).thenReturn(false); 102 mServiceConnection = null; 103 104 // Mock out the context and other junk that we depend on. 105 when(mContextProxy.queryIntentServicesAsUser(any(Intent.class), anyInt(), anyInt())) 106 .thenReturn(RESOLVE_INFOS); 107 when(mContextProxy.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class), 108 anyInt(), any(UserHandle.class))).thenReturn(true); 109 when(mContextProxy.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT); 110 111 mCallDiagnosticService = new CallDiagnosticServiceController(mContextProxy, 112 TEST_PACKAGE, mLock); 113 } 114 115 /** 116 * Verify no binding takes place for a non-sim call. 117 */ 118 @Test testNoBindOnNonSimCall()119 public void testNoBindOnNonSimCall() { 120 Call mockCall = Mockito.mock(Call.class); 121 when(mockCall.isSimCall()).thenReturn(false); 122 123 mCallDiagnosticService.onCallAdded(mockCall); 124 125 verify(mContextProxy, never()).bindServiceAsUser(any(Intent.class), 126 any(ServiceConnection.class), anyInt(), any(UserHandle.class)); 127 } 128 129 /** 130 * Verify no binding takes place for a SIM external call. 131 */ 132 @Test testNoBindOnExternalCall()133 public void testNoBindOnExternalCall() { 134 Call mockCall = Mockito.mock(Call.class); 135 when(mockCall.isSimCall()).thenReturn(true); 136 when(mockCall.isExternalCall()).thenReturn(true); 137 138 mCallDiagnosticService.onCallAdded(mockCall); 139 140 verify(mContextProxy, never()).bindServiceAsUser(any(Intent.class), 141 any(ServiceConnection.class), anyInt(), any(UserHandle.class)); 142 } 143 144 /** 145 * Verify a valid SIM call causes binding to initiate. 146 */ 147 @Test testAddSimCallCausesBind()148 public void testAddSimCallCausesBind() throws RemoteException { 149 mCallDiagnosticService.onCallAdded(mCall); 150 151 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 152 ArgumentCaptor<ServiceConnection> serviceConnectionCaptor = ArgumentCaptor.forClass( 153 ServiceConnection.class); 154 verify(mContextProxy).bindServiceAsUser(intentCaptor.capture(), 155 serviceConnectionCaptor.capture(), anyInt(), any(UserHandle.class)); 156 assertEquals(TEST_PACKAGE, intentCaptor.getValue().getPackage()); 157 158 // Now we'll pretend bind completed and we sent back the binder. 159 IBinder mockBinder = mock(IBinder.class); 160 when(mockBinder.queryLocalInterface(anyString())).thenReturn(mICallDiagnosticService); 161 serviceConnectionCaptor.getValue().onServiceConnected(TEST_COMPONENT, mockBinder); 162 mServiceConnection = serviceConnectionCaptor.getValue(); 163 164 // Make sure it's sent 165 verify(mICallDiagnosticService).initializeDiagnosticCall(any(ParcelableCall.class)); 166 } 167 168 /** 169 * Verify removing the active call causes it to be removed from the CallDiagnosticService and 170 * that an unbind takes place. 171 */ 172 @Test testRemoveSimCallCausesRemoveAndUnbind()173 public void testRemoveSimCallCausesRemoveAndUnbind() throws RemoteException { 174 testAddSimCallCausesBind(); 175 mCallDiagnosticService.onCallRemoved(mCall); 176 177 verify(mICallDiagnosticService).removeDiagnosticCall(eq(ID_1)); 178 verify(mContextProxy).unbindService(eq(mServiceConnection)); 179 } 180 181 /** 182 * Try to add and remove two and verify bind/unbind. 183 */ 184 @Test testAddTwo()185 public void testAddTwo() throws RemoteException { 186 testAddSimCallCausesBind(); 187 mCallDiagnosticService.onCallAdded(mCallTwo); 188 verify(mICallDiagnosticService, times(2)).initializeDiagnosticCall( 189 any(ParcelableCall.class)); 190 191 mCallDiagnosticService.onCallRemoved(mCall); 192 // Not yet! 193 verify(mContextProxy, never()).unbindService(eq(mServiceConnection)); 194 195 mCallDiagnosticService.onCallRemoved(mCallTwo); 196 197 verify(mICallDiagnosticService).removeDiagnosticCall(eq(ID_1)); 198 verify(mICallDiagnosticService).removeDiagnosticCall(eq(ID_2)); 199 verify(mContextProxy).unbindService(eq(mServiceConnection)); 200 } 201 202 /** 203 * Verifies we can override the call diagnostic service package to a test package (used by CTS 204 * tests). 205 */ 206 @Test testTestOverride()207 public void testTestOverride() { 208 mCallDiagnosticService.setTestCallDiagnosticService(TEST_CDS_PACKAGE); 209 mCallDiagnosticService.onCallAdded(mCall); 210 211 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 212 verify(mContextProxy).bindServiceAsUser(intentCaptor.capture(), 213 any(ServiceConnection.class), anyInt(), any(UserHandle.class)); 214 assertEquals(TEST_CDS_PACKAGE, intentCaptor.getValue().getPackage()); 215 } 216 } 217