blob: e9466ee23f356c258edb3be0b412a987a818d6fb [file] [log] [blame]
/*
* 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.MANAGE_OWN_CALLS;
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.Manifest;
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.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.telecom.CallAttributes;
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.ICallEventCallback;
import com.android.internal.telecom.ITelecomService;
import com.android.server.telecom.AnomalyReporterAdapter;
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.InCallController;
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 com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.voip.IncomingCallTransaction;
import com.android.server.telecom.voip.OutgoingCallTransaction;
import com.android.server.telecom.voip.TransactionManager;
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.lang.reflect.Method;
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.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
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.times;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.when;
@RunWith(JUnit4.class)
public class TelecomServiceImplTest extends TelecomTestCase {
private static final String CALLING_PACKAGE = TelecomServiceImplTest.class.getPackageName();
private static final String TEST_NAME = "Alan Turing";
private static final Uri TEST_URI = Uri.fromParts("tel", "abc", "123");
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, FeatureFlags flags) {
}
@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;
@Mock private ICallEventCallback mICallEventCallback;
@Mock private TransactionManager mTransactionManager;
@Mock private AnomalyReporterAdapter mAnomalyReporterAdapter;
@Mock private FeatureFlags mFeatureFlags;
@Mock private InCallController mInCallController;
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();
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt());
when(mFakeCallsManager.getInCallController()).thenReturn(mInCallController);
doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class),
anyString());
when(mContext.checkCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS))
.thenReturn(PackageManager.PERMISSION_GRANTED);
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,
mFeatureFlags,
mLock);
telecomServiceImpl.setTransactionManager(mTransactionManager);
telecomServiceImpl.setAnomalyReporterAdapter(mAnomalyReporterAdapter);
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());
when(mFeatureFlags.earlyBindingToIncallService()).thenReturn(true);
}
@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);
}
/**
* Clear the groupId from the PhoneAccount if a package does NOT have MODIFY_PHONE_STATE
*/
@SmallTest
@Test
public void testGroupIdIsClearedWhenPermissionIsMissing() throws RemoteException {
// GIVEN
PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT)
.setGroupId("testId")
.build();
// WHEN
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class), anyBoolean());
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingPermission(MODIFY_PHONE_STATE);
// THEN
PhoneAccount account =
mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_CURRENT, PACKAGE_NAME);
assertEquals("***", account.getGroupId());
}
/**
* Ensure groupId is not cleared if a package has MODIFY_PHONE_STATE
*/
@SmallTest
@Test
public void testGroupIdIsNotCleared() throws RemoteException {
// GIVEN
final String groupId = "testId";
PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT)
.setGroupId(groupId)
.build();
// WHEN
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class), anyBoolean());
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
doReturn(PackageManager.PERMISSION_GRANTED)
.when(mContext).checkCallingPermission(MODIFY_PHONE_STATE);
// THEN
PhoneAccount account =
mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE);
assertEquals(groupId, account.getGroupId());
}
@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));
}
@Test
public void testAddCallWithOutgoingCall() throws RemoteException {
// GIVEN
CallAttributes mOutgoingCallAttributes = new CallAttributes.Builder(TEL_PA_HANDLE_CURRENT,
CallAttributes.DIRECTION_OUTGOING, TEST_NAME, TEST_URI)
.setCallType(CallAttributes.AUDIO_CALL)
.setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE)
.build();
PhoneAccount phoneAccount = makeMultiUserPhoneAccount(TEL_PA_HANDLE_CURRENT).build();
phoneAccount.setIsEnabled(true);
// WHEN
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
phoneAccount);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class));
mTSIBinder.addCall(mOutgoingCallAttributes, mICallEventCallback, "1", CALLING_PACKAGE);
// THEN
verify(mTransactionManager, times(1))
.addTransaction(isA(OutgoingCallTransaction.class), isA(OutcomeReceiver.class));
}
@Test
public void testAddCallWithIncomingCall() throws RemoteException {
// GIVEN
CallAttributes mIncomingCallAttributes = new CallAttributes.Builder(TEL_PA_HANDLE_CURRENT,
CallAttributes.DIRECTION_INCOMING, TEST_NAME, TEST_URI)
.setCallType(CallAttributes.AUDIO_CALL)
.setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE)
.build();
PhoneAccount phoneAccount = makeMultiUserPhoneAccount(TEL_PA_HANDLE_CURRENT).build();
phoneAccount.setIsEnabled(true);
// WHEN
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
phoneAccount);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class));
mTSIBinder.addCall(mIncomingCallAttributes, mICallEventCallback, "1", CALLING_PACKAGE);
// THEN
verify(mTransactionManager, times(1))
.addTransaction(isA(IncomingCallTransaction.class), isA(OutcomeReceiver.class));
}
@Test
public void testAddCallWithManagedPhoneAccount() throws RemoteException {
// GIVEN
CallAttributes attributes = new CallAttributes.Builder(TEL_PA_HANDLE_CURRENT,
CallAttributes.DIRECTION_OUTGOING, TEST_NAME, TEST_URI).build();
PhoneAccount phoneAccount = makeMultiUserPhoneAccount(TEL_PA_HANDLE_CURRENT)
.setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
.build();
phoneAccount.setIsEnabled(true);
// WHEN
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
phoneAccount);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class));
// THEN
try {
mTSIBinder.addCall(attributes, mICallEventCallback, "1", CALLING_PACKAGE);
fail("should have thrown IllegalArgumentException");
} catch (IllegalArgumentException e) {
// pass
}
}
@SmallTest
@Test
public void testSetUserSelectedOutgoingPhoneAccountWithoutPermission() throws RemoteException {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
anyString(), nullable(String.class));
assertThrows(SecurityException.class,
() -> mTSIBinder.setUserSelectedOutgoingPhoneAccount(TEL_PA_HANDLE_16));
}
@SmallTest
@Test
public void testGetCallCapablePhoneAccounts() throws RemoteException {
List<PhoneAccountHandle> fullPHList = List.of(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
List<PhoneAccountHandle> smallPHList = List.of(SIP_PA_HANDLE_17);
// Returns all phone accounts when getCallCapablePhoneAccounts is called.
when(mFakePhoneAccountRegistrar
.getCallCapablePhoneAccounts(nullable(String.class), eq(true),
nullable(UserHandle.class), eq(true))).thenReturn(fullPHList);
// Returns only enabled phone accounts when getCallCapablePhoneAccounts is called.
when(mFakePhoneAccountRegistrar
.getCallCapablePhoneAccounts(nullable(String.class), eq(false),
nullable(UserHandle.class), eq(true))).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 testGetCallCapablePhoneAccountsWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), anyString());
assertThrows(SecurityException.class,
() -> mTSIBinder.getCallCapablePhoneAccounts(true, "", null));
}
@SmallTest
@Test
public void testGetSelfManagedPhoneAccounts() throws RemoteException {
List<PhoneAccountHandle> accounts = List.of(TEL_PA_HANDLE_16);
when(mFakePhoneAccountRegistrar.getSelfManagedPhoneAccounts(nullable(UserHandle.class)))
.thenReturn(accounts);
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16);
assertEquals(accounts,
mTSIBinder.getSelfManagedPhoneAccounts(DEFAULT_DIALER_PACKAGE, null).getList());
}
@SmallTest
@Test
public void testGetSelfManagedPhoneAccountsWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), anyString());
assertThrows(SecurityException.class,
() -> mTSIBinder.getSelfManagedPhoneAccounts("", null));
}
@SmallTest
@Test
public void testGetOwnSelfManagedPhoneAccounts() throws RemoteException {
List<PhoneAccountHandle> accounts = List.of(TEL_PA_HANDLE_16);
when(mFakePhoneAccountRegistrar.getSelfManagedPhoneAccountsForPackage(
eq(DEFAULT_DIALER_PACKAGE), nullable(UserHandle.class)))
.thenReturn(accounts);
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16);
assertEquals(accounts,
mTSIBinder.getOwnSelfManagedPhoneAccounts(DEFAULT_DIALER_PACKAGE, null).getList());
}
@SmallTest
@Test
public void testGetOwnSelfManagedPhoneAccountsWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(MANAGE_OWN_CALLS);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), anyString());
assertThrows(SecurityException.class,
() -> mTSIBinder.getOwnSelfManagedPhoneAccounts("", null));
}
@SmallTest
@Test
public void testGetPhoneAccountsSupportingScheme() throws RemoteException {
List<PhoneAccountHandle> sipPHList = List.of(SIP_PA_HANDLE_17);
List<PhoneAccountHandle> telPHList = List.of(TEL_PA_HANDLE_16);
when(mFakePhoneAccountRegistrar
.getCallCapablePhoneAccounts(eq("tel"), anyBoolean(),
any(UserHandle.class), anyBoolean()))
.thenReturn(telPHList);
when(mFakePhoneAccountRegistrar
.getCallCapablePhoneAccounts(eq("sip"), anyBoolean(),
any(UserHandle.class), anyBoolean()))
.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 testGetPhoneAccountsSupportingSchemeWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(MODIFY_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), anyString());
assertTrue(mTSIBinder.getPhoneAccountsSupportingScheme("any", "").getList().isEmpty());
}
@SmallTest
@Test
public void testGetPhoneAccountsForPackage() throws RemoteException {
List<PhoneAccountHandle> phoneAccountHandleList = List.of(
TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
when(mFakePhoneAccountRegistrar
.getAllPhoneAccountHandlesForPackage(any(UserHandle.class), anyString()))
.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 testGetPhoneAccountsForPackageWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(READ_PRIVILEGED_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), any());
assertThrows(SecurityException.class,
() -> mTSIBinder.getPhoneAccountsForPackage(""));
}
@SmallTest
@Test
public void testGetPhoneAccount() throws Exception {
doReturn(PackageManager.PERMISSION_GRANTED)
.when(mContext).checkCallingPermission(MODIFY_PHONE_STATE);
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 testGetAllPhoneAccountsCount() throws RemoteException {
List<PhoneAccount> phoneAccountList = List.of(
makePhoneAccount(TEL_PA_HANDLE_16).build(),
makePhoneAccount(SIP_PA_HANDLE_17).build());
when(mFakePhoneAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class), anyBoolean()))
.thenReturn(phoneAccountList);
assertEquals(phoneAccountList.size(), mTSIBinder.getAllPhoneAccountsCount());
}
@SmallTest
@Test
public void testGetAllPhoneAccountsCountWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(MODIFY_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), any());
assertThrows(SecurityException.class,
() -> mTSIBinder.getAllPhoneAccountsCount());
}
@SmallTest
@Test
public void testGetAllPhoneAccounts() throws RemoteException {
List<PhoneAccount> phoneAccountList = List.of(
makePhoneAccount(TEL_PA_HANDLE_16).build(),
makePhoneAccount(SIP_PA_HANDLE_17).build());
when(mFakePhoneAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class), anyBoolean()))
.thenReturn(phoneAccountList);
assertEquals(phoneAccountList.size(), mTSIBinder.getAllPhoneAccounts().getList().size());
}
@SmallTest
@Test
public void testGetAllPhoneAccountsWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(MODIFY_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), any());
assertThrows(SecurityException.class,
() -> mTSIBinder.getAllPhoneAccounts());
}
@SmallTest
@Test
public void testGetAllPhoneAccountHandles() throws RemoteException {
List<PhoneAccountHandle> handles = List.of(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
when(mFakePhoneAccountRegistrar.getAllPhoneAccountHandles(
any(UserHandle.class), anyBoolean())).thenReturn(handles);
assertEquals(handles, mTSIBinder.getAllPhoneAccountHandles().getList());
}
@SmallTest
@Test
public void testGetAllPhoneAccountHandlesWithoutPermission() throws RemoteException {
List<String> enforcedPermissions = List.of(MODIFY_PHONE_STATE);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), any());
assertThrows(SecurityException.class,
() -> mTSIBinder.getAllPhoneAccountHandles());
}
@SmallTest
@Test
public void testGetSimCallManager() throws RemoteException {
final PhoneAccountHandle handle = TEL_PA_HANDLE_16;
final int subId = 1;
when(mFakePhoneAccountRegistrar.getSimCallManager(eq(subId), any(UserHandle.class)))
.thenReturn(handle);
assertEquals(handle, mTSIBinder.getSimCallManager(subId, "any"));
}
@SmallTest
@Test
public void testGetSimCallManagerForUser() throws RemoteException {
final PhoneAccountHandle handle = TEL_PA_HANDLE_16;
final int user = 1;
when(mFakePhoneAccountRegistrar.getSimCallManager(
argThat(userHandle -> {
return userHandle.getIdentifier() == user;
})))
.thenReturn(handle);
assertEquals(handle, mTSIBinder.getSimCallManagerForUser(user, "any"));
}
@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 testRegisterPhoneAccountWithoutPermissionAnomalyReported() throws RemoteException {
PhoneAccountHandle handle = new PhoneAccountHandle(
new ComponentName("package", "cs"), "test", Binder.getCallingUserHandle());
PhoneAccount account = makeSelfManagedPhoneAccount(handle).build();
List<String> enforcedPermissions = List.of(MANAGE_OWN_CALLS);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), any());
registerPhoneAccountTestHelper(account, false);
verify(mAnomalyReporterAdapter).reportAnomaly(
TelecomServiceImpl.REGISTER_PHONE_ACCOUNT_ERROR_UUID,
TelecomServiceImpl.REGISTER_PHONE_ACCOUNT_ERROR_MSG);
}
@SmallTest
@Test
public void testRegisterPhoneAccountSelfManagedWithoutPermission() throws RemoteException {
PhoneAccountHandle handle = new PhoneAccountHandle(
new ComponentName("package", "cs"), "test", Binder.getCallingUserHandle());
PhoneAccount account = makeSelfManagedPhoneAccount(handle).build();
List<String> enforcedPermissions = List.of(MANAGE_OWN_CALLS);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
argThat(new AnyStringIn(enforcedPermissions)), any());
registerPhoneAccountTestHelper(account, false);
}
@SmallTest
@Test
public void testRegisterPhoneAccountSelfManagedInvalidCapabilities() throws RemoteException {
PhoneAccountHandle handle = new PhoneAccountHandle(
new ComponentName("package", "cs"), "test", Binder.getCallingUserHandle());
PhoneAccount selfManagedCallProviderAccount = makePhoneAccount(handle)
.setCapabilities(
PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build();
registerPhoneAccountTestHelper(selfManagedCallProviderAccount, false);
PhoneAccount selfManagedConnectionManagerAccount = makePhoneAccount(handle)
.setCapabilities(
PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
.build();
registerPhoneAccountTestHelper(selfManagedConnectionManagerAccount, false);
PhoneAccount selfManagedSimSubscriptionAccount = makePhoneAccount(handle)
.setCapabilities(
PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
.build();
registerPhoneAccountTestHelper(selfManagedSimSubscriptionAccount, false);
}
@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_TELECOM)).thenReturn(true);
registerPhoneAccountTestHelper(phoneAccount, true);
}
@SmallTest
@Test
public void testRegisterPhoneAccountWithOldFeatureFlag() 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_TELECOM)).thenReturn(false);
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_TELECOM)).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, CALLING_PACKAGE);
} 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 testRegisterPhoneAccountImageIconCrossUser() throws RemoteException {
String packageNameToUse = "com.android.officialpackage";
PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName(
packageNameToUse, "cs"), "test", Binder.getCallingUserHandle());
Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
PhoneAccount phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build();
doReturn(PackageManager.PERMISSION_GRANTED)
.when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
// This should fail; security exception will be thrown.
registerPhoneAccountTestHelper(phoneAccount, false);
icon = Icon.createWithContentUri("content://0@media/external/images/media/");
phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build();
// This should succeed.
registerPhoneAccountTestHelper(phoneAccount, true);
}
@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, CALLING_PACKAGE);
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_TELECOM)).thenReturn(false);
try {
mTSIBinder.unregisterPhoneAccount(phHandle, CALLING_PACKAGE);
} 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 testClearAccounts() throws RemoteException {
mTSIBinder.clearAccounts(CALLING_PACKAGE);
verify(mFakePhoneAccountRegistrar)
.clearAccounts(CALLING_PACKAGE, mTSIBinder.getCallingUserHandle());
}
@SmallTest
@Test
public void testClearAccountsWithoutPermission() throws RemoteException {
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
assertThrows(UnsupportedOperationException.class,
() -> mTSIBinder.clearAccounts(CALLING_PACKAGE));
}
@SmallTest
@Test
public void testAddNewIncomingCall() throws Exception {
PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_16).build();
phoneAccount.setIsEnabled(true);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_16), any(UserHandle.class));
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
Bundle extras = createSampleExtras();
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
verify(mFakePhoneAccountRegistrar).getPhoneAccount(
TEL_PA_HANDLE_16, TEL_PA_HANDLE_16.getUserHandle());
verify(mInCallController, never()).bindToServices(any());
addCallTestHelper(TelecomManager.ACTION_INCOMING_CALL,
CallIntentProcessor.KEY_IS_INCOMING_CALL, extras,
TEL_PA_HANDLE_16, false);
}
@SmallTest
@Test
public void testAddNewIncomingFlagDisabledNoEarlyBinding() throws Exception {
when(mFeatureFlags.earlyBindingToIncallService()).thenReturn(false);
PhoneAccount phoneAccount = makeSkipCallFilteringPhoneAccount(TEL_PA_HANDLE_16).build();
phoneAccount.setIsEnabled(true);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_16), any(UserHandle.class));
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked(
eq(TEL_PA_HANDLE_16));
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true);
Bundle extras = createSampleExtras();
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
verify(mInCallController, never()).bindToServices(null);
}
@SmallTest
@Test
public void testAddNewIncomingCallEarlyBindingForNoCallFilterCalls() throws Exception {
PhoneAccount phoneAccount = makeSkipCallFilteringPhoneAccount(TEL_PA_HANDLE_16).build();
phoneAccount.setIsEnabled(true);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_16), any(UserHandle.class));
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked(
eq(TEL_PA_HANDLE_16));
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true);
Bundle extras = createSampleExtras();
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
verify(mInCallController).bindToServices(null);
}
@SmallTest
@Test
public void testAddNewIncomingCallEarlyBindingNotEnableForNonWatchDevices() throws Exception {
PhoneAccount phoneAccount = makeSkipCallFilteringPhoneAccount(TEL_PA_HANDLE_16).build();
phoneAccount.setIsEnabled(true);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_16), any(UserHandle.class));
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked(
eq(TEL_PA_HANDLE_16));
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false);
Bundle extras = createSampleExtras();
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
verify(mInCallController, never()).bindToServices(null);
}
@SmallTest
@Test
public void testAddNewIncomingCallEarlyBindingNotEnableForPhoneAccountHasCallFilters()
throws Exception {
PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_16).build();
phoneAccount.setIsEnabled(true);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
eq(TEL_PA_HANDLE_16), any(UserHandle.class));
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccountUnchecked(
eq(TEL_PA_HANDLE_16));
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true);
Bundle extras = createSampleExtras();
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
verify(mInCallController, never()).bindToServices(null);
}
@SmallTest
@Test
public void testAddNewIncomingCallFailure() throws Exception {
try {
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, null, CALLING_PACKAGE);
} catch (SecurityException e) {
// expected
}
doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
try {
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_CURRENT, null, CALLING_PACKAGE);
} 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, TEL_PA_HANDLE_CURRENT, 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, PhoneAccountHandle expectedPhoneAccountHandle,
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(expectedPhoneAccountHandle,
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)));
}
}
/**
* Place a managed call with no PhoneAccount specified and ensure no security exception is
* thrown.
*/
@SmallTest
@Test
public void testPlaceCallWithNonEmergencyPermission() throws Exception {
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// We have passed in the DEFAULT_DIALER_PACKAGE for this test, so canCallPhone is always
// true.
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).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
/*shouldNonEmergencyBeAllowed*/ true);
}
/**
* Ensure that we get a SecurityException if the UID of the caller doesn't match the UID of the
* UID of the package name passed in.
*/
@SmallTest
@Test
public void testPlaceCall_enforceCallingPackageFailure() throws Exception {
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage matches the PhoneAccountHandle, so this is an app with a self-managed
// ConnectionService.
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// Return a non-matching UID for testing purposes.
when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(-1);
try {
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
fail("Expected SecurityException because calling package doesn't match");
} catch(SecurityException e) {
// expected
}
}
/**
* In the case that there is a self-managed call request and MANAGE_OWN_CALLS is granted, ensure
* that placeCall does not generate a SecurityException.
*/
@SmallTest
@Test
public void testPlaceCall_selfManaged_permissionGranted() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage matches the PhoneAccountHandle, so this is an app with a self-managed
// ConnectionService.
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// pass MANAGE_OWN_CALLS check, but do not have CALL_PHONE
doNothing().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
try {
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ true,
/*shouldNonEmergencyBeAllowed*/ false);
} catch(SecurityException e) {
fail("Unexpected SecurityException - MANAGE_OWN_CALLS is set");
}
}
/**
* In the case that the placeCall API is being used place a self-managed call
* (phone account is marked self-managed and the calling application owns that PhoneAccount),
* ensure that the call gets placed as not self-managed as to not disclose PA info.
*/
@SmallTest
@Test
public void testPlaceCall_selfManaged_noPermission() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage matches the PhoneAccountHandle, so this is an app with a self-managed
// ConnectionService.
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
try {
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
fail("Expected SecurityException because MANAGE_OWN_CALLS is not set");
} catch(SecurityException e) {
// expected
}
}
/**
* In the case that there is a self-managed call request and the app doesn't own that
* PhoneAccount, we will need to check CALL_PHONE. If they do not have CALL_PHONE permission,
* we need to throw a security exception.
*/
@SmallTest
@Test
public void testPlaceCall_selfManaged_permissionFail() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage doesn't match the PhoneAccountHandle package
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// pass MANAGE_OWN_CALLS check, but do not have CALL PHONE
doNothing().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
doThrow(new SecurityException())
.when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
try {
// Calling package is received and is not the same as PACKAGE_NAME
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME + "2", null);
fail("Expected a SecurityException - CALL_PHONE was not granted");
} catch(SecurityException e) {
// expected
}
}
/**
* In the case that there is a self-managed call request and the app doesn't own that
* PhoneAccount, we will need to check CALL_PHONE. If they have the CALL_PHONE permission, but
* the app op has been denied, this should throw a security exception.
*/
@SmallTest
@Test
public void testPlaceCall_selfManaged_appOpPermissionFail() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage doesn't match the PhoneAccountHandle package.
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// pass MANAGE_OWN_CALLS check, but do not have CALL PHONE
doNothing().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
nullable(String.class), nullable(String.class)))
.thenReturn(AppOpsManager.MODE_ERRORED);
try {
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME + "2", null);
fail("Expected a SecurityException - CALL_PHONE app op is denied");
} catch(SecurityException e) {
// expected
}
}
/**
* In the case that there is a self-managed call request and the app doesn't own that
* PhoneAccount, we will need to check CALL_PHONE. If they have the correct permissions, the
* call will go through, however we will have removed the self-managed PhoneAccountHandle. The
* call will go through as a normal managed call request with no PhoneAccountHandle.
*/
@SmallTest
@Test
public void testPlaceCall_selfManaged_differentCallingPackage() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage doesn't match the PhoneAccountHandle package
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// simulate default dialer so CALL_PHONE is granted.
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).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
// We expect the call to go through with no PhoneAccount specified, since the request
// contained a self-managed PhoneAccountHandle that didn't belong to this app.
Bundle expectedExtras = extras.deepCopy();
expectedExtras.remove(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
try {
mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
} catch (SecurityException e) {
fail("Unexpected SecurityException - CTS is default dialer and MANAGE_OWN_CALLS is not"
+ " required. Exception: " + e);
}
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
/*shouldNonEmergencyBeAllowed*/ true);
}
/**
* In the case that there is a managed call request and the app owns that
* PhoneAccount (but is not a self-managed), we will still need to check CALL_PHONE.
*/
@SmallTest
@Test
public void testPlaceCall_samePackage_managedPhoneAccount_permissionFail() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makePhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage doesn't match the PhoneAccountHandle package
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// CALL_PHONE is not granted to the device.
doThrow(new SecurityException())
.when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
doThrow(new SecurityException())
.when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
try {
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME + "2", null);
fail("Expected a SecurityException - CALL_PHONE is not granted");
} catch(SecurityException e) {
// expected
}
}
/**
* In the case that there is a managed call request and the app owns that
* PhoneAccount (but is not a self-managed), we will still need to check CALL_PHONE.
*/
@SmallTest
@Test
public void testPlaceCall_samePackage_managedPhoneAccount_AppOpFail() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makePhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage matches the PhoneAccountHandle, but this is not a self managed phone
// account.
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// CALL_PHONE is granted, but the app op is not
doThrow(new SecurityException())
.when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
nullable(String.class), nullable(String.class)))
.thenReturn(AppOpsManager.MODE_ERRORED);
try {
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME + "2", null);
fail("Expected a SecurityException - CALL_PHONE app op is denied");
} catch(SecurityException e) {
// expected
}
}
/**
* Since this is a self-managed call being requested, so ensure we report the call as
* self-managed and without non-emergency permissions.
*/
@SmallTest
@Test
public void testPlaceCall_selfManaged_nonEmergencyPermission() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage matches the PhoneAccountHandle, so this is an app with a self-managed
// ConnectionService.
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// enforceCallingOrSelfPermission is implicitly granted for MANAGE_OWN_CALLS here and
// CALL_PHONE is not required.
when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
nullable(String.class), nullable(String.class)))
.thenReturn(AppOpsManager.MODE_IGNORED);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ true,
/*shouldNonEmergencyBeAllowed*/ false);
}
/**
* Default dialer is calling placeCall and has CALL_PHONE granted, so non-emergency calls
* are allowed.
*/
@SmallTest
@Test
public void testPlaceCall_managed_nonEmergencyGranted() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// callingPackage doesn't match the PhoneAccountHandle, so this app does not have a
// self-managed ConnectionService
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
// CALL_PHONE granted
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).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
/*shouldNonEmergencyBeAllowed*/ true);
}
/**
* In the case that there is a managed normal call request and the app has CALL_PRIVILEGED
* permission, place call should complete successfully.
*/
@SmallTest
@Test
public void testPlaceCallPrivileged() throws Exception {
doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
eq(DEFAULT_DIALER_PACKAGE), anyInt());
Uri handle = Uri.parse("tel:6505551234");
// CALL_PHONE is not granted, but CALL_PRIVILEGED is
doThrow(new SecurityException())
.when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
doReturn(PackageManager.PERMISSION_GRANTED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(CALL_PHONE), anyString());
when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
nullable(String.class), nullable(String.class)))
.thenReturn(AppOpsManager.MODE_ERRORED);
try {
mTSIBinder.placeCall(handle, null, PACKAGE_NAME + "2", null);
} catch(SecurityException e) {
fail("Expected no SecurityException - CALL_PRIVILEGED is granted");
}
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mUserCallIntentProcessor).processIntent(intentCaptor.capture(), anyString(),
eq(false), eq(true), eq(true));
Intent capturedIntent = intentCaptor.getValue();
assertEquals(Intent.ACTION_CALL_PRIVILEGED, capturedIntent.getAction());
assertEquals(handle, capturedIntent.getData());
}
/**
* The default dialer is requesting to place a call and CALL_PHONE is granted, however
* OP_CALL_PHONE app op is denied to that app, so non-emergency calls will be denied.
*/
@SmallTest
@Test
public void testPlaceCallWithAppOpsOff() throws Exception {
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// We have passed in the DEFAULT_DIALER_PACKAGE for this test, so canCallPhone is always
// true.
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).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
/*shouldNonEmergencyBeAllowed*/ false);
}
/**
* The default dialer is requesting to place a call, however CALL_PHONE is denied to that app,
* so non-emergency calls will be denied.
*/
@SmallTest
@Test
public void testPlaceCallWithNoCallingPermission() throws Exception {
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// We are assumed to be default dialer in this test, so canCallPhone is always true.
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).checkCallingOrSelfPermission(CALL_PHONE);
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
/*shouldNonEmergencyBeAllowed*/ false);
}
/**
* Ensure the expected handle, extras, and non-emergency call permission checks have been
* correctly included in the ACTION_CALL intent as part of the
* {@link UserCallIntentProcessor#processIntent} method called during the placeCall procedure.
* @param expectedHandle Expected outgoing number handle
* @param expectedExtras Expected extras in the ACTION_CALL intent.
* @param shouldNonEmergencyBeAllowed true if non-emergency calls should be allowed, false if
* permission checks failed for non-emergency.
*/
private void placeCallTestHelper(Uri expectedHandle, Bundle expectedExtras,
boolean isSelfManagedExpected, boolean shouldNonEmergencyBeAllowed) {
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mUserCallIntentProcessor).processIntent(intentCaptor.capture(), anyString(),
eq(isSelfManagedExpected), eq(shouldNonEmergencyBeAllowed), eq(true));
Intent capturedIntent = intentCaptor.getValue();
assertEquals(Intent.ACTION_CALL, capturedIntent.getAction());
assertEquals(expectedHandle, capturedIntent.getData());
assertTrue(areBundlesEqual(expectedExtras, capturedIntent.getExtras()));
}
/**
* Ensure that if the caller was never granted CALL_PHONE (and is not the default dialer), a
* SecurityException is thrown.
*/
@SmallTest
@Test
public void testPlaceCallFailure() throws Exception {
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// The app is not considered a privileged dialer and does not have the CALL_PHONE
// permission.
doThrow(new SecurityException())
.when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
try {
mTSIBinder.placeCall(handle, extras, "arbitrary_package_name", null);
fail("Expected SecurityException because CALL_PHONE was not granted to caller");
} catch (SecurityException e) {
// expected
}
verify(mUserCallIntentProcessor, never())
.processIntent(any(Intent.class), anyString(), eq(false), anyBoolean(), eq(true));
}
/**
* Ensure that if the caller was granted CALL_PHONE, but did not get the OP_CALL_PHONE app op
* (and is not the default dialer), a SecurityException is thrown.
*/
@SmallTest
@Test
public void testPlaceCallAppOpFailure() throws Exception {
Uri handle = Uri.parse("tel:6505551234");
Bundle extras = createSampleExtras();
// The app is not considered a privileged dialer and does not have the OP_CALL_PHONE
// app op.
doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
nullable(String.class), nullable(String.class)))
.thenReturn(AppOpsManager.MODE_IGNORED);
try {
mTSIBinder.placeCall(handle, extras, "arbitrary_package_name", null);
fail("Expected SecurityException because CALL_PHONE was not granted to caller");
} catch (SecurityException e) {
// expected
}
verify(mUserCallIntentProcessor, never())
.processIntent(any(Intent.class), anyString(), eq(false), 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));
}
/**
* FeatureFlags is autogenerated code, so there could be a situation where something changes
* outside of Telecom control that breaks reflection. This test attempts to ensure that changes
* to auto-generated FeatureFlags code that breaks reflection are caught early.
*/
@SmallTest
@Test
public void testFlagConfigReflectionWorks() {
try {
Method[] methods = FeatureFlags.class.getMethods();
for (Method m : methods) {
// test getting the name and invoking the flag code
String name = m.getName();
Object val = m.invoke(mFeatureFlags);
assertNotNull(name);
assertNotNull(val);
}
} catch (Exception e) {
fail("Reflection failed for FeatureFlags with error: " + e);
}
}
@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 testGetDefaultDialerPackageForUser() throws Exception {
final int userId = 1;
final String packageName = "some.package";
when(mDefaultDialerCache.getDefaultDialerApplication(userId))
.thenReturn(packageName);
assertEquals(packageName, mTSIBinder.getDefaultDialerPackageForUser(userId));
}
@SmallTest
@Test
public void testGetSystemDialerPackage() throws Exception {
final String packageName = "some.package";
when(mDefaultDialerCache.getSystemDialerApplication())
.thenReturn(packageName);
assertEquals(packageName, mTSIBinder.getSystemDialerPackage(CALLING_PACKAGE));
}
@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(any(UserHandle.class), anyBoolean()))
.thenReturn(true);
assertTrue(mTSIBinder.isInCall(DEFAULT_DIALER_PACKAGE, null));
}
@SmallTest
@Test
public void testNotIsInCall() throws Exception {
when(mFakeCallsManager.hasOngoingCalls(any(UserHandle.class), anyBoolean()))
.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(any(UserHandle.class), anyBoolean());
}
@SmallTest
@Test
public void testIsInManagedCall() throws Exception {
when(mFakeCallsManager.hasOngoingManagedCalls(any(UserHandle.class), anyBoolean()))
.thenReturn(true);
assertTrue(mTSIBinder.isInManagedCall(DEFAULT_DIALER_PACKAGE, null));
}
@SmallTest
@Test
public void testNotIsInManagedCall() throws Exception {
when(mFakeCallsManager.hasOngoingManagedCalls(any(UserHandle.class), anyBoolean()))
.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(any(UserHandle.class), anyBoolean());
}
/**
* 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());
}
@SmallTest
@Test
public void testGetAdnUriForPhoneAccount() throws Exception {
final int subId = 1;
final Uri adnUri = Uri.parse("content://icc/adn/subId/" + subId);
PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build();
when(mFakePhoneAccountRegistrar.getPhoneAccount(
eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class)))
.thenReturn(phoneAccount);
when(mFakePhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(TEL_PA_HANDLE_CURRENT))
.thenReturn(subId);
assertEquals(adnUri,
mTSIBinder.getAdnUriForPhoneAccount(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE));
}
/**
* 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 makeSelfManagedPhoneAccount(PhoneAccountHandle paHandle) {
PhoneAccount.Builder paBuilder = makePhoneAccount(paHandle);
paBuilder.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED);
return paBuilder;
}
private PhoneAccount.Builder makePhoneAccount(PhoneAccountHandle paHandle) {
return new PhoneAccount.Builder(paHandle, "testLabel");
}
private PhoneAccount.Builder makeSkipCallFilteringPhoneAccount(PhoneAccountHandle paHandle) {
Bundle extras = new Bundle();
extras.putBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING, true);
return new PhoneAccount.Builder(paHandle, "testLabel").setExtras(extras);
}
private Bundle createSampleExtras() {
Bundle extras = new Bundle();
extras.putString("test_key", "test_value");
return extras;
}
private static boolean areBundlesEqual(Bundle b1, Bundle b2) {
if (b1.keySet().size() != b2.keySet().size()) return false;
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;
}
}