| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package com.android.server.telecom.tests; |
| |
| import static android.Manifest.permission.CALL_PHONE; |
| import static android.Manifest.permission.CALL_PRIVILEGED; |
| import static android.Manifest.permission.MODIFY_PHONE_STATE; |
| import static android.Manifest.permission.READ_PHONE_NUMBERS; |
| import static android.Manifest.permission.READ_PHONE_STATE; |
| import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; |
| |
| import android.app.ActivityManager; |
| import android.app.AppOpsManager; |
| import android.content.ComponentName; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageManager; |
| import android.net.Uri; |
| import android.os.Binder; |
| import android.os.Build; |
| import android.os.Bundle; |
| import android.os.RemoteException; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.telecom.PhoneAccount; |
| import android.telecom.PhoneAccountHandle; |
| import android.telecom.TelecomManager; |
| import android.telecom.VideoProfile; |
| import android.telephony.TelephonyManager; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import com.android.internal.telecom.ITelecomService; |
| import com.android.server.telecom.Call; |
| import com.android.server.telecom.CallIntentProcessor; |
| import com.android.server.telecom.CallState; |
| import com.android.server.telecom.CallsManager; |
| import com.android.server.telecom.DefaultDialerCache; |
| import com.android.server.telecom.PhoneAccountRegistrar; |
| import com.android.server.telecom.TelecomServiceImpl; |
| import com.android.server.telecom.TelecomSystem; |
| import com.android.server.telecom.components.UserCallIntentProcessor; |
| import com.android.server.telecom.components.UserCallIntentProcessorFactory; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.ArgumentMatcher; |
| import org.mockito.Mock; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.concurrent.Executor; |
| import java.util.function.IntConsumer; |
| |
| import static android.Manifest.permission.READ_SMS; |
| import static android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION; |
| import static android.Manifest.permission.WRITE_SECURE_SETTINGS; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.mockito.ArgumentMatchers.nullable; |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Matchers.anyBoolean; |
| import static org.mockito.Matchers.anyInt; |
| import static org.mockito.Matchers.anyString; |
| import static org.mockito.Matchers.argThat; |
| import static org.mockito.Matchers.eq; |
| import static org.mockito.Matchers.isNull; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.doNothing; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.doThrow; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.spy; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| @RunWith(JUnit4.class) |
| public class TelecomServiceImplTest extends TelecomTestCase { |
| |
| public static final String TEST_PACKAGE = "com.test"; |
| public static final String PACKAGE_NAME = "test"; |
| |
| public static class CallIntentProcessAdapterFake implements CallIntentProcessor.Adapter { |
| @Override |
| public void processOutgoingCallIntent(Context context, CallsManager callsManager, |
| Intent intent, String callingPackage) { |
| |
| } |
| |
| @Override |
| public void processIncomingCallIntent(CallsManager callsManager, Intent intent) { |
| |
| } |
| |
| @Override |
| public void processUnknownCallIntent(CallsManager callsManager, Intent intent) { |
| |
| } |
| } |
| |
| public static class SubscriptionManagerAdapterFake |
| implements TelecomServiceImpl.SubscriptionManagerAdapter { |
| @Override |
| public int getDefaultVoiceSubId() { |
| return 0; |
| } |
| } |
| |
| public static class SettingsSecureAdapterFake implements |
| TelecomServiceImpl.SettingsSecureAdapter { |
| @Override |
| public void putStringForUser(ContentResolver resolver, String name, String value, |
| int userHandle) { |
| |
| } |
| |
| @Override |
| public String getStringForUser(ContentResolver resolver, String name, int userHandle) { |
| return THIRD_PARTY_CALL_SCREENING.flattenToString(); |
| } |
| } |
| |
| private static class AnyStringIn implements ArgumentMatcher<String> { |
| private Collection<String> mStrings; |
| public AnyStringIn(Collection<String> strings) { |
| this.mStrings = strings; |
| } |
| |
| @Override |
| public boolean matches(String string) { |
| return mStrings.contains(string); |
| } |
| } |
| |
| private ITelecomService.Stub mTSIBinder; |
| private AppOpsManager mAppOpsManager; |
| private UserManager mUserManager; |
| |
| @Mock private CallsManager mFakeCallsManager; |
| @Mock private PhoneAccountRegistrar mFakePhoneAccountRegistrar; |
| @Mock private TelecomManager mTelecomManager; |
| private CallIntentProcessor.Adapter mCallIntentProcessorAdapter = |
| spy(new CallIntentProcessAdapterFake()); |
| @Mock private DefaultDialerCache mDefaultDialerCache; |
| private IntConsumer mDefaultDialerObserver; |
| private TelecomServiceImpl.SubscriptionManagerAdapter mSubscriptionManagerAdapter = |
| spy(new SubscriptionManagerAdapterFake()); |
| private TelecomServiceImpl.SettingsSecureAdapter mSettingsSecureAdapter = |
| spy(new SettingsSecureAdapterFake()); |
| @Mock private UserCallIntentProcessor mUserCallIntentProcessor; |
| private PackageManager mPackageManager; |
| @Mock private ApplicationInfo mApplicationInfo; |
| |
| private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; |
| |
| private static final String DEFAULT_DIALER_PACKAGE = "com.google.android.dialer"; |
| private static final UserHandle USER_HANDLE_16 = new UserHandle(16); |
| private static final UserHandle USER_HANDLE_17 = new UserHandle(17); |
| private static final PhoneAccountHandle TEL_PA_HANDLE_16 = new PhoneAccountHandle( |
| new ComponentName(PACKAGE_NAME, "telComponentName"), "0", USER_HANDLE_16); |
| private static final PhoneAccountHandle SIP_PA_HANDLE_17 = new PhoneAccountHandle( |
| new ComponentName(PACKAGE_NAME, "sipComponentName"), "1", USER_HANDLE_17); |
| private static final PhoneAccountHandle TEL_PA_HANDLE_CURRENT = new PhoneAccountHandle( |
| new ComponentName(PACKAGE_NAME, "telComponentName"), "2", |
| Binder.getCallingUserHandle()); |
| private static final PhoneAccountHandle SIP_PA_HANDLE_CURRENT = new PhoneAccountHandle( |
| new ComponentName(PACKAGE_NAME, "sipComponentName"), "3", |
| Binder.getCallingUserHandle()); |
| private static final ComponentName THIRD_PARTY_CALL_SCREENING = new ComponentName( |
| "com.android.thirdparty", "com.android.thirdparty.callscreeningserviceimpl"); |
| |
| @Override |
| @Before |
| public void setUp() throws Exception { |
| super.setUp(); |
| mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); |
| |
| TelephonyManager mockTelephonyManager = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| when(mockTelephonyManager.isVoiceCapable()).thenReturn(true); |
| |
| doReturn(mContext).when(mContext).getApplicationContext(); |
| doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt()); |
| doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class), |
| anyString()); |
| doAnswer(invocation -> { |
| mDefaultDialerObserver = invocation.getArgument(1); |
| return null; |
| }).when(mDefaultDialerCache).observeDefaultDialerApplication(any(Executor.class), |
| any(IntConsumer.class)); |
| TelecomServiceImpl telecomServiceImpl = new TelecomServiceImpl( |
| mContext, |
| mFakeCallsManager, |
| mFakePhoneAccountRegistrar, |
| mCallIntentProcessorAdapter, |
| new UserCallIntentProcessorFactory() { |
| @Override |
| public UserCallIntentProcessor create(Context context, UserHandle userHandle) { |
| return mUserCallIntentProcessor; |
| } |
| }, |
| mDefaultDialerCache, |
| mSubscriptionManagerAdapter, |
| mSettingsSecureAdapter, |
| mLock); |
| mTSIBinder = telecomServiceImpl.getBinder(); |
| mComponentContextFixture.setTelecomManager(mTelecomManager); |
| when(mTelecomManager.getDefaultDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE); |
| when(mTelecomManager.getSystemDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE); |
| |
| mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); |
| mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); |
| |
| when(mDefaultDialerCache.getDefaultDialerApplication(anyInt())) |
| .thenReturn(DEFAULT_DIALER_PACKAGE); |
| when(mDefaultDialerCache.isDefaultOrSystemDialer(eq(DEFAULT_DIALER_PACKAGE), anyInt())) |
| .thenReturn(true); |
| |
| mPackageManager = mContext.getPackageManager(); |
| when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid()); |
| } |
| |
| @Override |
| @After |
| public void tearDown() throws Exception { |
| super.tearDown(); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetDefaultOutgoingPhoneAccount() throws RemoteException { |
| when(mFakePhoneAccountRegistrar |
| .getOutgoingPhoneAccountForScheme(eq("tel"), any(UserHandle.class))) |
| .thenReturn(TEL_PA_HANDLE_16); |
| when(mFakePhoneAccountRegistrar |
| .getOutgoingPhoneAccountForScheme(eq("sip"), any(UserHandle.class))) |
| .thenReturn(SIP_PA_HANDLE_17); |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17); |
| PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build(); |
| phoneAccount.setIsEnabled(true); |
| doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| |
| PhoneAccountHandle returnedHandleTel |
| = mTSIBinder.getDefaultOutgoingPhoneAccount("tel", DEFAULT_DIALER_PACKAGE, null); |
| assertEquals(TEL_PA_HANDLE_16, returnedHandleTel); |
| |
| PhoneAccountHandle returnedHandleSip |
| = mTSIBinder.getDefaultOutgoingPhoneAccount("sip", DEFAULT_DIALER_PACKAGE, null); |
| assertEquals(SIP_PA_HANDLE_17, returnedHandleSip); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetDefaultOutgoingPhoneAccountSucceedsIfCallerIsSimCallManager() |
| throws RemoteException { |
| when(mFakePhoneAccountRegistrar |
| .getOutgoingPhoneAccountForScheme(eq("tel"), any(UserHandle.class))) |
| .thenReturn(TEL_PA_HANDLE_16); |
| when(mFakePhoneAccountRegistrar |
| .getOutgoingPhoneAccountForScheme(eq("sip"), any(UserHandle.class))) |
| .thenReturn(SIP_PA_HANDLE_17); |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17); |
| PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build(); |
| phoneAccount.setIsEnabled(true); |
| doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| doReturn(TEL_PA_HANDLE_CURRENT).when(mFakePhoneAccountRegistrar) |
| .getSimCallManagerFromHandle( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| // doNothing will make #isCallerSimCallManager return true |
| doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| doThrow(new SecurityException()).when(mContext) |
| .enforceCallingOrSelfPermission(eq(READ_PRIVILEGED_PHONE_STATE), anyString()); |
| |
| PhoneAccountHandle returnedHandleTel |
| = mTSIBinder.getDefaultOutgoingPhoneAccount("tel", DEFAULT_DIALER_PACKAGE, null); |
| assertEquals(TEL_PA_HANDLE_16, returnedHandleTel); |
| |
| PhoneAccountHandle returnedHandleSip |
| = mTSIBinder.getDefaultOutgoingPhoneAccount("sip", DEFAULT_DIALER_PACKAGE, null); |
| assertEquals(SIP_PA_HANDLE_17, returnedHandleSip); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetDefaultOutgoingPhoneAccountFailure() throws RemoteException { |
| // make sure that the list of user profiles doesn't include anything the PhoneAccountHandles |
| // are associated with |
| |
| when(mFakePhoneAccountRegistrar |
| .getOutgoingPhoneAccountForScheme(eq("tel"), any(UserHandle.class))) |
| .thenReturn(TEL_PA_HANDLE_16); |
| when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_16)).thenReturn( |
| makePhoneAccount(TEL_PA_HANDLE_16).build()); |
| when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_READ_PHONE_STATE), anyInt(), anyString(), |
| nullable(String.class), nullable(String.class))) |
| .thenReturn(AppOpsManager.MODE_IGNORED); |
| PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build(); |
| phoneAccount.setIsEnabled(true); |
| doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| doReturn(TEL_PA_HANDLE_16).when(mFakePhoneAccountRegistrar).getSimCallManagerFromHandle( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| doThrow(new SecurityException()).when(mContext) |
| .enforceCallingOrSelfPermission(eq(READ_PRIVILEGED_PHONE_STATE), anyString()); |
| |
| PhoneAccountHandle returnedHandleTel |
| = mTSIBinder.getDefaultOutgoingPhoneAccount("tel", "", null); |
| assertNull(returnedHandleTel); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetUserSelectedOutgoingPhoneAccount() throws RemoteException { |
| when(mFakePhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount(any(UserHandle.class))) |
| .thenReturn(TEL_PA_HANDLE_16); |
| when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_16)).thenReturn( |
| makeMultiUserPhoneAccount(TEL_PA_HANDLE_16).build()); |
| |
| PhoneAccountHandle returnedHandle |
| = mTSIBinder.getUserSelectedOutgoingPhoneAccount( |
| TEL_PA_HANDLE_16.getComponentName().getPackageName()); |
| assertEquals(TEL_PA_HANDLE_16, returnedHandle); |
| } |
| |
| @SmallTest |
| @Test |
| public void testSetUserSelectedOutgoingPhoneAccount() throws RemoteException { |
| mTSIBinder.setUserSelectedOutgoingPhoneAccount(TEL_PA_HANDLE_16); |
| verify(mFakePhoneAccountRegistrar) |
| .setUserSelectedOutgoingPhoneAccount(eq(TEL_PA_HANDLE_16), any(UserHandle.class)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testSetUserSelectedOutgoingPhoneAccountFailure() throws RemoteException { |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( |
| anyString(), nullable(String.class)); |
| try { |
| mTSIBinder.setUserSelectedOutgoingPhoneAccount(TEL_PA_HANDLE_16); |
| } catch (SecurityException e) { |
| // desired result |
| } |
| verify(mFakePhoneAccountRegistrar, never()) |
| .setUserSelectedOutgoingPhoneAccount( |
| any(PhoneAccountHandle.class), any(UserHandle.class)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetCallCapablePhoneAccounts() throws RemoteException { |
| List<PhoneAccountHandle> fullPHList = new ArrayList<PhoneAccountHandle>() {{ |
| add(TEL_PA_HANDLE_16); |
| add(SIP_PA_HANDLE_17); |
| }}; |
| |
| List<PhoneAccountHandle> smallPHList = new ArrayList<PhoneAccountHandle>() {{ |
| add(SIP_PA_HANDLE_17); |
| }}; |
| // Returns all phone accounts when getCallCapablePhoneAccounts is called. |
| when(mFakePhoneAccountRegistrar |
| .getCallCapablePhoneAccounts(nullable(String.class), eq(true), |
| nullable(UserHandle.class))).thenReturn(fullPHList); |
| // Returns only enabled phone accounts when getCallCapablePhoneAccounts is called. |
| when(mFakePhoneAccountRegistrar |
| .getCallCapablePhoneAccounts(nullable(String.class), eq(false), |
| nullable(UserHandle.class))).thenReturn(smallPHList); |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17); |
| |
| assertEquals(fullPHList, |
| mTSIBinder.getCallCapablePhoneAccounts( |
| true, DEFAULT_DIALER_PACKAGE, null).getList()); |
| assertEquals(smallPHList, |
| mTSIBinder.getCallCapablePhoneAccounts( |
| false, DEFAULT_DIALER_PACKAGE, null).getList()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetCallCapablePhoneAccountsFailure() throws RemoteException { |
| List<String> enforcedPermissions = new ArrayList<String>() {{ |
| add(READ_PHONE_STATE); |
| add(READ_PRIVILEGED_PHONE_STATE); |
| }}; |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( |
| argThat(new AnyStringIn(enforcedPermissions)), anyString()); |
| |
| List<PhoneAccountHandle> result = null; |
| try { |
| result = mTSIBinder.getCallCapablePhoneAccounts(true, "", null).getList(); |
| } catch (SecurityException e) { |
| // intended behavior |
| } |
| assertNull(result); |
| verify(mFakePhoneAccountRegistrar, never()) |
| .getCallCapablePhoneAccounts(anyString(), anyBoolean(), any(UserHandle.class)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetPhoneAccountsSupportingScheme() throws RemoteException { |
| List<PhoneAccountHandle> sipPHList = new ArrayList<PhoneAccountHandle>() {{ |
| add(SIP_PA_HANDLE_17); |
| }}; |
| |
| List<PhoneAccountHandle> telPHList = new ArrayList<PhoneAccountHandle>() {{ |
| add(TEL_PA_HANDLE_16); |
| }}; |
| when(mFakePhoneAccountRegistrar |
| .getCallCapablePhoneAccounts(eq("tel"), anyBoolean(), any(UserHandle.class))) |
| .thenReturn(telPHList); |
| when(mFakePhoneAccountRegistrar |
| .getCallCapablePhoneAccounts(eq("sip"), anyBoolean(), any(UserHandle.class))) |
| .thenReturn(sipPHList); |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17); |
| |
| assertEquals(telPHList, |
| mTSIBinder.getPhoneAccountsSupportingScheme( |
| "tel", DEFAULT_DIALER_PACKAGE).getList()); |
| assertEquals(sipPHList, |
| mTSIBinder.getPhoneAccountsSupportingScheme( |
| "sip", DEFAULT_DIALER_PACKAGE).getList()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetPhoneAccountsForPackage() throws RemoteException { |
| List<PhoneAccountHandle> phoneAccountHandleList = new ArrayList<PhoneAccountHandle>() {{ |
| add(TEL_PA_HANDLE_16); |
| add(SIP_PA_HANDLE_17); |
| }}; |
| when(mFakePhoneAccountRegistrar |
| .getPhoneAccountsForPackage(anyString(), any(UserHandle.class))) |
| .thenReturn(phoneAccountHandleList); |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17); |
| assertEquals(phoneAccountHandleList, |
| mTSIBinder.getPhoneAccountsForPackage( |
| TEL_PA_HANDLE_16.getComponentName().getPackageName()).getList()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetPhoneAccount() throws Exception { |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17); |
| assertEquals(TEL_PA_HANDLE_16, mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_16, |
| mContext.getPackageName()).getAccountHandle()); |
| assertEquals(SIP_PA_HANDLE_17, mTSIBinder.getPhoneAccount(SIP_PA_HANDLE_17, |
| mContext.getPackageName()).getAccountHandle()); |
| try { |
| // Try to call the method without using the caller's package name |
| mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_16, null); |
| fail("Should have thrown a SecurityException"); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetAllPhoneAccounts() throws RemoteException { |
| List<PhoneAccount> phoneAccountList = new ArrayList<PhoneAccount>() {{ |
| add(makePhoneAccount(TEL_PA_HANDLE_16).build()); |
| add(makePhoneAccount(SIP_PA_HANDLE_17).build()); |
| }}; |
| when(mFakePhoneAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class))) |
| .thenReturn(phoneAccountList); |
| |
| assertEquals(2, mTSIBinder.getAllPhoneAccounts().getList().size()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testRegisterPhoneAccount() throws RemoteException { |
| String packageNameToUse = "com.android.officialpackage"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "test", Binder.getCallingUserHandle()); |
| PhoneAccount phoneAccount = makePhoneAccount(phHandle).build(); |
| doReturn(PackageManager.PERMISSION_GRANTED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| |
| registerPhoneAccountTestHelper(phoneAccount, true); |
| } |
| |
| @SmallTest |
| @Test |
| public void testRegisterPhoneAccountWithoutModifyPermission() throws RemoteException { |
| // tests the case where the package does not have MODIFY_PHONE_STATE but is |
| // registering its own phone account as a third-party connection service |
| String packageNameToUse = "com.thirdparty.connectionservice"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "asdf", Binder.getCallingUserHandle()); |
| PhoneAccount phoneAccount = makePhoneAccount(phHandle).build(); |
| |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| PackageManager pm = mContext.getPackageManager(); |
| when(pm.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE)).thenReturn(true); |
| |
| registerPhoneAccountTestHelper(phoneAccount, true); |
| } |
| |
| @SmallTest |
| @Test |
| public void testRegisterPhoneAccountWithoutModifyPermissionFailure() throws RemoteException { |
| // tests the case where the third party package should not be allowed to register a phone |
| // account due to the lack of modify permission. |
| String packageNameToUse = "com.thirdparty.connectionservice"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "asdf", Binder.getCallingUserHandle()); |
| PhoneAccount phoneAccount = makePhoneAccount(phHandle).build(); |
| |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| PackageManager pm = mContext.getPackageManager(); |
| when(pm.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE)).thenReturn(false); |
| |
| registerPhoneAccountTestHelper(phoneAccount, false); |
| } |
| |
| @SmallTest |
| @Test |
| public void testRegisterPhoneAccountWithoutSimSubscriptionPermissionFailure() |
| throws RemoteException { |
| String packageNameToUse = "com.thirdparty.connectionservice"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "asdf", Binder.getCallingUserHandle()); |
| PhoneAccount phoneAccount = makePhoneAccount(phHandle) |
| .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION).build(); |
| |
| doReturn(PackageManager.PERMISSION_GRANTED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| doThrow(new SecurityException()) |
| .when(mContext) |
| .enforceCallingOrSelfPermission(eq(REGISTER_SIM_SUBSCRIPTION), |
| nullable(String.class)); |
| |
| registerPhoneAccountTestHelper(phoneAccount, false); |
| } |
| |
| @SmallTest |
| @Test |
| public void testRegisterPhoneAccountWithoutMultiUserPermissionFailure() |
| throws Exception { |
| String packageNameToUse = "com.thirdparty.connectionservice"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "asdf", Binder.getCallingUserHandle()); |
| PhoneAccount phoneAccount = makeMultiUserPhoneAccount(phHandle).build(); |
| |
| doReturn(PackageManager.PERMISSION_GRANTED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| |
| PackageManager packageManager = mContext.getPackageManager(); |
| when(packageManager.getApplicationInfo(packageNameToUse, PackageManager.GET_META_DATA)) |
| .thenReturn(new ApplicationInfo()); |
| |
| registerPhoneAccountTestHelper(phoneAccount, false); |
| } |
| |
| private void registerPhoneAccountTestHelper(PhoneAccount testPhoneAccount, |
| boolean shouldSucceed) throws RemoteException { |
| ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); |
| boolean didExceptionOccur = false; |
| try { |
| mTSIBinder.registerPhoneAccount(testPhoneAccount); |
| } catch (Exception e) { |
| didExceptionOccur = true; |
| } |
| |
| if (shouldSucceed) { |
| assertFalse(didExceptionOccur); |
| verify(mFakePhoneAccountRegistrar).registerPhoneAccount(testPhoneAccount); |
| } else { |
| assertTrue(didExceptionOccur); |
| verify(mFakePhoneAccountRegistrar, never()) |
| .registerPhoneAccount(any(PhoneAccount.class)); |
| } |
| } |
| |
| @SmallTest |
| @Test |
| public void testUnregisterPhoneAccount() throws RemoteException { |
| String packageNameToUse = "com.android.officialpackage"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "test", Binder.getCallingUserHandle()); |
| |
| ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); |
| doReturn(PackageManager.PERMISSION_GRANTED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| |
| mTSIBinder.unregisterPhoneAccount(phHandle); |
| verify(mFakePhoneAccountRegistrar).unregisterPhoneAccount(phHandle); |
| } |
| |
| @SmallTest |
| @Test |
| public void testUnregisterPhoneAccountFailure() throws RemoteException { |
| String packageNameToUse = "com.thirdparty.connectionservice"; |
| PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( |
| packageNameToUse, "cs"), "asdf", Binder.getCallingUserHandle()); |
| |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); |
| PackageManager pm = mContext.getPackageManager(); |
| when(pm.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE)).thenReturn(false); |
| |
| try { |
| mTSIBinder.unregisterPhoneAccount(phHandle); |
| } catch (UnsupportedOperationException e) { |
| // expected behavior |
| } |
| verify(mFakePhoneAccountRegistrar, never()) |
| .unregisterPhoneAccount(any(PhoneAccountHandle.class)); |
| verify(mContext, never()) |
| .sendBroadcastAsUser(any(Intent.class), any(UserHandle.class), anyString()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testAddNewIncomingCall() throws Exception { |
| PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build(); |
| phoneAccount.setIsEnabled(true); |
| doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| Bundle extras = createSampleExtras(); |
| |
| mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_CURRENT, extras); |
| |
| addCallTestHelper(TelecomManager.ACTION_INCOMING_CALL, |
| CallIntentProcessor.KEY_IS_INCOMING_CALL, extras, false); |
| } |
| |
| @SmallTest |
| @Test |
| public void testAddNewIncomingCallFailure() throws Exception { |
| try { |
| mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, null); |
| } catch (SecurityException e) { |
| // expected |
| } |
| |
| doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| |
| try { |
| mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_CURRENT, null); |
| } catch (SecurityException e) { |
| // expected |
| } |
| |
| // Verify that neither of these attempts got through |
| verify(mCallIntentProcessorAdapter, never()) |
| .processIncomingCallIntent(any(CallsManager.class), any(Intent.class)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testAddNewUnknownCall() throws Exception { |
| PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build(); |
| phoneAccount.setIsEnabled(true); |
| doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount( |
| eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)); |
| doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| Bundle extras = createSampleExtras(); |
| |
| mTSIBinder.addNewUnknownCall(TEL_PA_HANDLE_CURRENT, extras); |
| |
| addCallTestHelper(TelecomManager.ACTION_NEW_UNKNOWN_CALL, |
| CallIntentProcessor.KEY_IS_UNKNOWN_CALL, extras, true); |
| } |
| |
| @SmallTest |
| @Test |
| public void testAddNewUnknownCallFailure() throws Exception { |
| try { |
| mTSIBinder.addNewUnknownCall(TEL_PA_HANDLE_16, null); |
| } catch (SecurityException e) { |
| // expected |
| } |
| |
| doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); |
| |
| try { |
| mTSIBinder.addNewUnknownCall(TEL_PA_HANDLE_CURRENT, null); |
| } catch (SecurityException e) { |
| // expected |
| } |
| |
| // Verify that neither of these attempts got through |
| verify(mCallIntentProcessorAdapter, never()) |
| .processIncomingCallIntent(any(CallsManager.class), any(Intent.class)); |
| } |
| |
| private void addCallTestHelper(String expectedAction, String extraCallKey, |
| Bundle expectedExtras, boolean isUnknown) { |
| ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); |
| if (isUnknown) { |
| verify(mCallIntentProcessorAdapter).processUnknownCallIntent(any(CallsManager.class), |
| intentCaptor.capture()); |
| } else { |
| verify(mCallIntentProcessorAdapter).processIncomingCallIntent(any(CallsManager.class), |
| intentCaptor.capture()); |
| } |
| Intent capturedIntent = intentCaptor.getValue(); |
| assertEquals(expectedAction, capturedIntent.getAction()); |
| Bundle intentExtras = capturedIntent.getExtras(); |
| assertEquals(TEL_PA_HANDLE_CURRENT, |
| intentExtras.get(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE)); |
| assertTrue(intentExtras.getBoolean(extraCallKey)); |
| |
| if (isUnknown) { |
| for (String expectedKey : expectedExtras.keySet()) { |
| assertTrue(intentExtras.containsKey(expectedKey)); |
| assertEquals(expectedExtras.get(expectedKey), intentExtras.get(expectedKey)); |
| } |
| } |
| else { |
| assertTrue(areBundlesEqual(expectedExtras, |
| (Bundle) intentExtras.get(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS))); |
| } |
| } |
| |
| @SmallTest |
| @Test |
| public void testPlaceCallWithNonEmergencyPermission() throws Exception { |
| Uri handle = Uri.parse("tel:6505551234"); |
| Bundle extras = createSampleExtras(); |
| |
| when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(), |
| nullable(String.class), nullable(String.class))) |
| .thenReturn(AppOpsManager.MODE_ALLOWED); |
| doReturn(PackageManager.PERMISSION_GRANTED) |
| .when(mContext).checkCallingPermission(CALL_PHONE); |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingPermission(CALL_PRIVILEGED); |
| |
| mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null); |
| placeCallTestHelper(handle, extras, true); |
| } |
| |
| @SmallTest |
| @Test |
| public void testPlaceCallWithAppOpsOff() throws Exception { |
| Uri handle = Uri.parse("tel:6505551234"); |
| Bundle extras = createSampleExtras(); |
| |
| when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(), |
| nullable(String.class), nullable(String.class))) |
| .thenReturn(AppOpsManager.MODE_IGNORED); |
| doReturn(PackageManager.PERMISSION_GRANTED) |
| .when(mContext).checkCallingPermission(CALL_PHONE); |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingPermission(CALL_PRIVILEGED); |
| |
| mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null); |
| placeCallTestHelper(handle, extras, false); |
| } |
| |
| @SmallTest |
| @Test |
| public void testPlaceCallWithNoCallingPermission() throws Exception { |
| Uri handle = Uri.parse("tel:6505551234"); |
| Bundle extras = createSampleExtras(); |
| |
| when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(), |
| nullable(String.class), nullable(String.class))) |
| .thenReturn(AppOpsManager.MODE_ALLOWED); |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingPermission(CALL_PHONE); |
| doReturn(PackageManager.PERMISSION_DENIED) |
| .when(mContext).checkCallingPermission(CALL_PRIVILEGED); |
| |
| mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null); |
| placeCallTestHelper(handle, extras, false); |
| } |
| |
| private void placeCallTestHelper(Uri expectedHandle, Bundle expectedExtras, |
| boolean shouldNonEmergencyBeAllowed) { |
| ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); |
| verify(mUserCallIntentProcessor).processIntent(intentCaptor.capture(), anyString(), |
| eq(shouldNonEmergencyBeAllowed), eq(true)); |
| Intent capturedIntent = intentCaptor.getValue(); |
| assertEquals(Intent.ACTION_CALL, capturedIntent.getAction()); |
| assertEquals(expectedHandle, capturedIntent.getData()); |
| assertTrue(areBundlesEqual(expectedExtras, capturedIntent.getExtras())); |
| } |
| |
| @SmallTest |
| @Test |
| public void testPlaceCallFailure() throws Exception { |
| Uri handle = Uri.parse("tel:6505551234"); |
| Bundle extras = createSampleExtras(); |
| |
| doThrow(new SecurityException()) |
| .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString()); |
| |
| try { |
| mTSIBinder.placeCall(handle, extras, "arbitrary_package_name", null); |
| } catch (SecurityException e) { |
| // expected |
| } |
| |
| verify(mUserCallIntentProcessor, never()) |
| .processIntent(any(Intent.class), anyString(), anyBoolean(), eq(true)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testSetDefaultDialer() throws Exception { |
| String packageName = "sample.package"; |
| int currentUser = ActivityManager.getCurrentUser(); |
| |
| String[] defaultDialer = new String[1]; |
| doAnswer(invocation -> { |
| defaultDialer[0] = packageName; |
| mDefaultDialerObserver.accept(currentUser); |
| return true; |
| }).when(mDefaultDialerCache).setDefaultDialer(eq(packageName), eq(currentUser)); |
| doAnswer(invocation -> defaultDialer[0]).when(mDefaultDialerCache) |
| .getDefaultDialerApplication(eq(currentUser)); |
| |
| mTSIBinder.setDefaultDialer(packageName); |
| |
| verify(mDefaultDialerCache).setDefaultDialer(eq(packageName), eq(currentUser)); |
| ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); |
| verify(mContext).sendBroadcastAsUser(intentCaptor.capture(), any(UserHandle.class)); |
| Intent capturedIntent = intentCaptor.getValue(); |
| assertEquals(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED, capturedIntent.getAction()); |
| String packageNameExtra = capturedIntent.getStringExtra( |
| TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME); |
| assertEquals(packageName, packageNameExtra); |
| } |
| |
| @SmallTest |
| @Test |
| public void testSetDefaultDialerNoModifyPhoneStatePermission() throws Exception { |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( |
| eq(MODIFY_PHONE_STATE), nullable(String.class)); |
| setDefaultDialerFailureTestHelper(); |
| } |
| |
| @SmallTest |
| @Test |
| public void testSetDefaultDialerNoWriteSecureSettingsPermission() throws Exception { |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( |
| eq(WRITE_SECURE_SETTINGS), nullable(String.class)); |
| setDefaultDialerFailureTestHelper(); |
| } |
| |
| private void setDefaultDialerFailureTestHelper() throws Exception { |
| boolean exceptionThrown = false; |
| try { |
| mTSIBinder.setDefaultDialer(DEFAULT_DIALER_PACKAGE); |
| } catch (SecurityException e) { |
| exceptionThrown = true; |
| } |
| assertTrue(exceptionThrown); |
| verify(mDefaultDialerCache, never()).setDefaultDialer(anyString(), anyInt()); |
| verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testIsVoicemailNumber() throws Exception { |
| String vmNumber = "010"; |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_CURRENT); |
| |
| doReturn(true).when(mFakePhoneAccountRegistrar).isVoiceMailNumber(TEL_PA_HANDLE_CURRENT, |
| vmNumber); |
| assertTrue(mTSIBinder.isVoiceMailNumber(TEL_PA_HANDLE_CURRENT, |
| vmNumber, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testIsVoicemailNumberAccountNotVisibleFailure() throws Exception { |
| String vmNumber = "010"; |
| |
| doReturn(true).when(mFakePhoneAccountRegistrar).isVoiceMailNumber(TEL_PA_HANDLE_CURRENT, |
| vmNumber); |
| |
| when(mFakePhoneAccountRegistrar.getPhoneAccount(TEL_PA_HANDLE_CURRENT, |
| Binder.getCallingUserHandle())).thenReturn(null); |
| assertFalse(mTSIBinder |
| .isVoiceMailNumber(TEL_PA_HANDLE_CURRENT, vmNumber, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetVoicemailNumberWithNullAccountHandle() throws Exception { |
| when(mFakePhoneAccountRegistrar.getPhoneAccount(isNull(PhoneAccountHandle.class), |
| eq(Binder.getCallingUserHandle()))) |
| .thenReturn(makePhoneAccount(TEL_PA_HANDLE_CURRENT).build()); |
| int subId = 58374; |
| String vmNumber = "543"; |
| doReturn(subId).when(mSubscriptionManagerAdapter).getDefaultVoiceSubId(); |
| |
| TelephonyManager mockTelephonyManager = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| when(mockTelephonyManager.getVoiceMailNumber()).thenReturn(vmNumber); |
| |
| assertEquals(vmNumber, mTSIBinder.getVoiceMailNumber(null, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetVoicemailNumberWithNonNullAccountHandle() throws Exception { |
| when(mFakePhoneAccountRegistrar.getPhoneAccount(eq(TEL_PA_HANDLE_CURRENT), |
| eq(Binder.getCallingUserHandle()))) |
| .thenReturn(makePhoneAccount(TEL_PA_HANDLE_CURRENT).build()); |
| int subId = 58374; |
| String vmNumber = "543"; |
| |
| TelephonyManager mockTelephonyManager = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| when(mockTelephonyManager.getVoiceMailNumber()).thenReturn(vmNumber); |
| when(mFakePhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(TEL_PA_HANDLE_CURRENT)) |
| .thenReturn(subId); |
| |
| assertEquals(vmNumber, |
| mTSIBinder.getVoiceMailNumber(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithNoPermissionTargetPreR() throws Exception { |
| setupGetLine1NumberTest(); |
| setTargetSdkVersion(Build.VERSION_CODES.Q); |
| |
| try { |
| String line1Number = mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, |
| DEFAULT_DIALER_PACKAGE, null); |
| fail("Should have thrown a SecurityException when invoking getLine1Number without " |
| + "permission, received " |
| + line1Number); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithNoPermissionTargetR() throws Exception { |
| setupGetLine1NumberTest(); |
| |
| try { |
| String line1Number = mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, |
| DEFAULT_DIALER_PACKAGE, null); |
| fail("Should have thrown a SecurityException when invoking getLine1Number without " |
| + "permission, received " |
| + line1Number); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithReadPhoneStateTargetPreR() throws Exception { |
| String line1Number = setupGetLine1NumberTest(); |
| setTargetSdkVersion(Build.VERSION_CODES.Q); |
| grantPermissionAndAppOp(READ_PHONE_STATE, AppOpsManager.OPSTR_READ_PHONE_STATE); |
| |
| assertEquals(line1Number, |
| mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithReadPhoneStateTargetR() throws Exception { |
| setupGetLine1NumberTest(); |
| grantPermissionAndAppOp(READ_PHONE_STATE, AppOpsManager.OPSTR_READ_PHONE_STATE); |
| |
| try { |
| String line1Number = mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, |
| DEFAULT_DIALER_PACKAGE, null); |
| fail("Should have thrown a SecurityException when invoking getLine1Number on target R" |
| + " with READ_PHONE_STATE permission, received " |
| + line1Number); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithReadPhoneNumbersTargetR() throws Exception { |
| String line1Number = setupGetLine1NumberTest(); |
| grantPermissionAndAppOp(READ_PHONE_NUMBERS, AppOpsManager.OPSTR_READ_PHONE_NUMBERS); |
| |
| assertEquals(line1Number, |
| mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithReadSmsTargetR() throws Exception { |
| String line1Number = setupGetLine1NumberTest(); |
| grantPermissionAndAppOp(READ_SMS, AppOpsManager.OPSTR_READ_SMS); |
| |
| assertEquals(line1Number, |
| mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberWithWriteSmsTargetR() throws Exception { |
| String line1Number = setupGetLine1NumberTest(); |
| doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOpNoThrow( |
| eq(AppOpsManager.OPSTR_WRITE_SMS), anyInt(), eq(DEFAULT_DIALER_PACKAGE), any(), |
| any()); |
| |
| assertEquals(line1Number, |
| mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| |
| @SmallTest |
| @Test |
| public void testGetLine1NumberAsDefaultDialer() throws Exception { |
| String line1Number = setupGetLine1NumberTest(); |
| doReturn(true).when(mDefaultDialerCache).isDefaultOrSystemDialer( |
| eq(DEFAULT_DIALER_PACKAGE), anyInt()); |
| |
| assertEquals(line1Number, |
| mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| private String setupGetLine1NumberTest() throws Exception { |
| int subId = 58374; |
| String line1Number = "9482752023479"; |
| |
| setTargetSdkVersion(Build.VERSION_CODES.R); |
| doReturn(AppOpsManager.MODE_DEFAULT).when(mAppOpsManager).noteOpNoThrow(anyString(), |
| anyInt(), eq(DEFAULT_DIALER_PACKAGE), any(), any()); |
| makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_CURRENT); |
| when(mFakePhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(TEL_PA_HANDLE_CURRENT)) |
| .thenReturn(subId); |
| TelephonyManager mockTelephonyManager = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| when(mockTelephonyManager.getLine1Number()).thenReturn(line1Number); |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(anyString(), |
| anyString()); |
| doReturn(PackageManager.PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission( |
| anyString()); |
| doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer( |
| eq(DEFAULT_DIALER_PACKAGE), anyInt()); |
| return line1Number; |
| } |
| |
| private void grantPermissionAndAppOp(String permission, String appop) { |
| doReturn(PackageManager.PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission( |
| eq(permission)); |
| doNothing().when(mContext).enforceCallingOrSelfPermission(eq(permission), anyString()); |
| doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(eq(appop), anyInt(), |
| eq(DEFAULT_DIALER_PACKAGE), any(), any()); |
| doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOpNoThrow(eq(appop), anyInt(), |
| eq(DEFAULT_DIALER_PACKAGE), any(), any()); |
| } |
| |
| private void setTargetSdkVersion(int targetSdkVersion) throws Exception { |
| mApplicationInfo.targetSdkVersion = targetSdkVersion; |
| doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfoAsUser( |
| eq(DEFAULT_DIALER_PACKAGE), anyInt(), any()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testEndCallWithRingingForegroundCall() throws Exception { |
| Call call = mock(Call.class); |
| when(call.getState()).thenReturn(CallState.RINGING); |
| when(mFakeCallsManager.getForegroundCall()).thenReturn(call); |
| assertTrue(mTSIBinder.endCall(TEST_PACKAGE)); |
| verify(mFakeCallsManager).rejectCall(eq(call), eq(false), isNull()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testEndCallWithSimulatedRingingForegroundCall() throws Exception { |
| Call call = mock(Call.class); |
| when(call.getState()).thenReturn(CallState.SIMULATED_RINGING); |
| when(mFakeCallsManager.getForegroundCall()).thenReturn(call); |
| assertTrue(mTSIBinder.endCall(TEST_PACKAGE)); |
| verify(mFakeCallsManager).rejectCall(eq(call), eq(false), isNull()); |
| } |
| |
| @SmallTest |
| @Test |
| public void testEndCallWithNonRingingForegroundCall() throws Exception { |
| Call call = mock(Call.class); |
| when(call.getState()).thenReturn(CallState.ACTIVE); |
| when(mFakeCallsManager.getForegroundCall()).thenReturn(call); |
| assertTrue(mTSIBinder.endCall(TEST_PACKAGE)); |
| verify(mFakeCallsManager).disconnectCall(eq(call)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testEndCallWithNoForegroundCall() throws Exception { |
| Call call = mock(Call.class); |
| when(call.getState()).thenReturn(CallState.ACTIVE); |
| when(mFakeCallsManager.getFirstCallWithState(any())) |
| .thenReturn(call); |
| assertTrue(mTSIBinder.endCall(TEST_PACKAGE)); |
| verify(mFakeCallsManager).disconnectCall(eq(call)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testEndCallWithNoCalls() throws Exception { |
| assertFalse(mTSIBinder.endCall(null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testAcceptRingingCall() throws Exception { |
| Call call = mock(Call.class); |
| when(mFakeCallsManager.getFirstCallWithState(anyInt(), anyInt())).thenReturn(call); |
| // Not intended to be a real video state. Here to ensure that the call will be answered |
| // with whatever video state it's currently in. |
| int fakeVideoState = 29578215; |
| when(call.getVideoState()).thenReturn(fakeVideoState); |
| mTSIBinder.acceptRingingCall(""); |
| verify(mFakeCallsManager).answerCall(eq(call), eq(fakeVideoState)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testAcceptRingingCallWithValidVideoState() throws Exception { |
| Call call = mock(Call.class); |
| when(mFakeCallsManager.getFirstCallWithState(anyInt(), anyInt())).thenReturn(call); |
| // Not intended to be a real video state. Here to ensure that the call will be answered |
| // with the video state passed in to acceptRingingCallWithVideoState |
| int fakeVideoState = 29578215; |
| int realVideoState = VideoProfile.STATE_RX_ENABLED | VideoProfile.STATE_TX_ENABLED; |
| when(call.getVideoState()).thenReturn(fakeVideoState); |
| mTSIBinder.acceptRingingCallWithVideoState("", realVideoState); |
| verify(mFakeCallsManager).answerCall(eq(call), eq(realVideoState)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testIsInCall() throws Exception { |
| when(mFakeCallsManager.hasOngoingCalls()).thenReturn(true); |
| assertTrue(mTSIBinder.isInCall(DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testNotIsInCall() throws Exception { |
| when(mFakeCallsManager.hasOngoingCalls()).thenReturn(false); |
| assertFalse(mTSIBinder.isInCall(DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testIsInCallFail() throws Exception { |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( |
| anyString(), any()); |
| try { |
| mTSIBinder.isInCall("blah", null); |
| fail(); |
| } catch (SecurityException e) { |
| // desired result |
| } |
| verify(mFakeCallsManager, never()).hasOngoingCalls(); |
| } |
| |
| @SmallTest |
| @Test |
| public void testIsInManagedCall() throws Exception { |
| when(mFakeCallsManager.hasOngoingManagedCalls()).thenReturn(true); |
| assertTrue(mTSIBinder.isInManagedCall(DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testNotIsInManagedCall() throws Exception { |
| when(mFakeCallsManager.hasOngoingManagedCalls()).thenReturn(false); |
| assertFalse(mTSIBinder.isInManagedCall(DEFAULT_DIALER_PACKAGE, null)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testIsInManagedCallFail() throws Exception { |
| doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( |
| anyString(), any()); |
| try { |
| mTSIBinder.isInManagedCall("blah", null); |
| fail(); |
| } catch (SecurityException e) { |
| // desired result |
| } |
| verify(mFakeCallsManager, never()).hasOngoingCalls(); |
| } |
| |
| /** |
| * Ensure self-managed calls cannot be ended using {@link TelecomManager#endCall()}. |
| * @throws Exception |
| */ |
| @SmallTest |
| @Test |
| public void testCannotEndSelfManagedCall() throws Exception { |
| Call call = mock(Call.class); |
| when(call.isSelfManaged()).thenReturn(true); |
| when(call.getState()).thenReturn(CallState.ACTIVE); |
| when(mFakeCallsManager.getFirstCallWithState(any())) |
| .thenReturn(call); |
| assertFalse(mTSIBinder.endCall(TEST_PACKAGE)); |
| verify(mFakeCallsManager, never()).disconnectCall(eq(call)); |
| } |
| |
| /** |
| * Ensure self-managed calls cannot be answered using {@link TelecomManager#acceptRingingCall()} |
| * or {@link TelecomManager#acceptRingingCall(int)}. |
| * @throws Exception |
| */ |
| @SmallTest |
| @Test |
| public void testCannotAnswerSelfManagedCall() throws Exception { |
| Call call = mock(Call.class); |
| when(call.isSelfManaged()).thenReturn(true); |
| when(call.getState()).thenReturn(CallState.ACTIVE); |
| when(mFakeCallsManager.getFirstCallWithState(any())) |
| .thenReturn(call); |
| mTSIBinder.acceptRingingCall(TEST_PACKAGE); |
| verify(mFakeCallsManager, never()).answerCall(eq(call), anyInt()); |
| } |
| |
| /** |
| * Register phone accounts for the supplied PhoneAccountHandles to make them |
| * visible to all users (via the isVisibleToCaller method in TelecomServiceImpl. |
| * @param handles the handles for which phone accounts should be created for. |
| */ |
| private void makeAccountsVisibleToAllUsers(PhoneAccountHandle... handles) { |
| for (PhoneAccountHandle ph : handles) { |
| when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(eq(ph))).thenReturn( |
| makeMultiUserPhoneAccount(ph).build()); |
| when(mFakePhoneAccountRegistrar |
| .getPhoneAccount(eq(ph), nullable(UserHandle.class), anyBoolean())) |
| .thenReturn(makeMultiUserPhoneAccount(ph).build()); |
| when(mFakePhoneAccountRegistrar |
| .getPhoneAccount(eq(ph), nullable(UserHandle.class))) |
| .thenReturn(makeMultiUserPhoneAccount(ph).build()); |
| } |
| } |
| |
| private PhoneAccount.Builder makeMultiUserPhoneAccount(PhoneAccountHandle paHandle) { |
| PhoneAccount.Builder paBuilder = makePhoneAccount(paHandle); |
| paBuilder.setCapabilities(PhoneAccount.CAPABILITY_MULTI_USER); |
| return paBuilder; |
| } |
| |
| private PhoneAccount.Builder makePhoneAccount(PhoneAccountHandle paHandle) { |
| return new PhoneAccount.Builder(paHandle, "testLabel"); |
| } |
| |
| private Bundle createSampleExtras() { |
| Bundle extras = new Bundle(); |
| extras.putString("test_key", "test_value"); |
| return extras; |
| } |
| |
| private static boolean areBundlesEqual(Bundle b1, Bundle b2) { |
| for (String key1 : b1.keySet()) { |
| if (!b1.get(key1).equals(b2.get(key1))) { |
| return false; |
| } |
| } |
| |
| for (String key2 : b2.keySet()) { |
| if (!b2.get(key2).equals(b1.get(key2))) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |