Merge "Add new config to combine unavailable and unknown option"
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index beb19ee..145e9b4 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -50,6 +50,16 @@
import java.util.concurrent.LinkedBlockingDeque;
import java.util.stream.Collectors;
+import static android.provider.CallLog.Calls.AUTO_MISSED_EMERGENCY_CALL;
+import static android.provider.CallLog.Calls.AUTO_MISSED_MAXIMUM_DIALING;
+import static android.provider.CallLog.Calls.AUTO_MISSED_MAXIMUM_RINGING;
+import static android.provider.CallLog.Calls.USER_MISSED_CALL_FILTERS_TIMEOUT;
+import static android.provider.CallLog.Calls.USER_MISSED_CALL_SCREENING_SERVICE_SILENCED;
+import static android.provider.CallLog.Calls.USER_MISSED_DND_MODE;
+import static android.provider.CallLog.Calls.USER_MISSED_LOW_RING_VOLUME;
+import static android.provider.CallLog.Calls.USER_MISSED_NEVER_RANG;
+import static android.provider.CallLog.Calls.USER_MISSED_NO_VIBRATE;
+import static android.provider.CallLog.Calls.USER_MISSED_SHORT_RING;
import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent;
import static android.telecom.TelecomAnalytics.SessionTiming;
@@ -538,7 +548,30 @@
private String getMissedReasonString() {
//TODO: Implement this
- return null;
+ StringBuilder s = new StringBuilder();
+ s.append('[');
+ if ((missedReason & AUTO_MISSED_EMERGENCY_CALL) != 0) {
+ s.append("emergency]");
+ return s.toString();
+ } else if ((missedReason & AUTO_MISSED_MAXIMUM_DIALING) != 0) {
+ s.append("max_dialing]");
+ return s.toString();
+ } else if ((missedReason & AUTO_MISSED_MAXIMUM_RINGING) != 0) {
+ s.append("max_ringing]");
+ return s.toString();
+ }
+
+ // user missed
+ if ((missedReason & USER_MISSED_SHORT_RING) != 0) s.append("short_ring ");
+ if ((missedReason & USER_MISSED_DND_MODE) != 0) s.append("dnd ");
+ if ((missedReason & USER_MISSED_LOW_RING_VOLUME) != 0) s.append("low_volume ");
+ if ((missedReason & USER_MISSED_NO_VIBRATE) != 0) s.append("no_vibrate ");
+ if ((missedReason & USER_MISSED_CALL_SCREENING_SERVICE_SILENCED) != 0)
+ s.append("css_silenced ");
+ if ((missedReason & USER_MISSED_CALL_FILTERS_TIMEOUT) != 0) s.append("filter_timeout ");
+ if ((missedReason & USER_MISSED_NEVER_RANG) != 0) s.append("no_ring ");
+ s.append("]");
+ return s.toString();
}
private String getInCallServicesString() {
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 7b24a09..576a289 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -287,6 +287,12 @@
if (account != null) {
return defaultPhoneAccountHandle.phoneAccountHandle;
}
+
+ Log.v(this,
+ "getUserSelectedOutgoingPhoneAccount: defaultPhoneAccountHandle"
+ + ".phoneAccountHandle=[%s] is not registered or owned by %s"
+ , defaultPhoneAccountHandle.phoneAccountHandle, userHandle);
+
return null;
}
@@ -343,6 +349,15 @@
mState.defaultOutgoingAccountHandles.get(userHandle);
PhoneAccountHandle currentDefaultPhoneAccount = currentDefaultInfo == null ? null :
currentDefaultInfo.phoneAccountHandle;
+
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s", accountHandle);
+
+ if (Objects.equals(currentDefaultPhoneAccount, accountHandle)) {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: "
+ + "no change in default phoneAccountHandle. current is same as new.");
+ return;
+ }
+
boolean isSimAccount = false;
if (accountHandle == null) {
// Asking to clear the default outgoing is a valid request
@@ -371,24 +386,21 @@
.put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle,
account.getGroupId()));
}
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s", accountHandle);
// Potentially update the default voice subid in SubscriptionManager.
- if (!Objects.equals(currentDefaultPhoneAccount, accountHandle)) {
- int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID :
- getSubscriptionIdForPhoneAccount(accountHandle);
- if (isSimAccount || accountHandle == null) {
- int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
- if (newSubId != currentVoiceSubId) {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
- + "account=%s, subId=%d", accountHandle, newSubId);
- mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId);
- }
+ int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID :
+ getSubscriptionIdForPhoneAccount(accountHandle);
+ if (isSimAccount || accountHandle == null) {
+ int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
+ if (newSubId != currentVoiceSubId) {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
+ + "account=%s, subId=%d", accountHandle, newSubId);
+ mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId);
} else {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
}
} else {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
}
write();
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index bf678d2..c859fde 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -19,6 +19,7 @@
import static android.provider.CallLog.Calls.USER_MISSED_DND_MODE;
import static android.provider.CallLog.Calls.USER_MISSED_LOW_RING_VOLUME;
import static android.provider.CallLog.Calls.USER_MISSED_NO_VIBRATE;
+import static android.provider.Settings.Global.ZEN_MODE_OFF;
import android.app.Notification;
import android.app.NotificationManager;
@@ -507,10 +508,14 @@
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// Use AudioManager#getRingerMode for more accurate result, instead of
// AudioManager#getRingerModeInternal which only useful for volume controllers
+ NotificationManager notificationManager = context.getSystemService(
+ NotificationManager.class);
+ boolean zenModeOn = notificationManager != null
+ && notificationManager.getZenMode() != ZEN_MODE_OFF;
return mVibrator.hasVibrator()
&& mSystemSettingsUtil.isRingVibrationEnabled(context)
&& (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT
- || shouldRingForContact);
+ || (zenModeOn && shouldRingForContact));
}
private RingerAttributes getRingerAttributes(Call call, boolean isHfpDeviceAttached) {
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 5015099..ee7aba6 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -1520,6 +1520,7 @@
enforceCallingPackage(callingPackage, "placeCall");
PhoneAccountHandle phoneAccountHandle = null;
+ boolean clearPhoneAccountHandleExtra = false;
if (extras != null) {
phoneAccountHandle = extras.getParcelable(
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
@@ -1528,28 +1529,32 @@
extras.remove(TelecomManager.EXTRA_IS_HANDOVER);
}
}
- ComponentName componentName = phoneAccountHandle != null
- ? phoneAccountHandle.getComponentName() : null;
- String packageName = componentName != null
- ? componentName.getPackageName() : null;
+ boolean isSelfManaged = phoneAccountHandle != null &&
+ isSelfManagedConnectionService(phoneAccountHandle);
+ if (isSelfManaged) {
+ try {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_OWN_CALLS,
+ "Self-managed ConnectionServices require "
+ + "MANAGE_OWN_CALLS permission.");
+ } catch (SecurityException e) {
+ // Fallback to use mobile network to avoid disclosing phone account handle
+ // package information
+ clearPhoneAccountHandleExtra = true;
+ }
- // Two cases here: the app calling this API is trying to place a call on another
- // ConnectionService or the app calling this API implements a self-managed
- // ConnectionService and is trying to place a call on their own ConnectionService.
- // Case 1: If the app does not implement the ConnectionService they are requesting
- // the call be placed on, ensure they have the correct CALL_PHONE permissions.
- if (!callingPackage.equals(packageName) && !canCallPhone(callingPackage,
- callingFeatureId, "CALL_PHONE permission required to place calls.")) {
- throw new SecurityException("CALL_PHONE permission required to place calls.");
+ if (!clearPhoneAccountHandleExtra && !callingPackage.equals(
+ phoneAccountHandle.getComponentName().getPackageName())
+ && !canCallPhone(callingPackage, callingFeatureId,
+ "CALL_PHONE permission required to place calls.")) {
+ // The caller is not allowed to place calls, so fallback to use mobile
+ // network.
+ clearPhoneAccountHandleExtra = true;
+ }
+ } else if (!canCallPhone(callingPackage, callingFeatureId, "placeCall")) {
+ throw new SecurityException("Package " + callingPackage
+ + " is not allowed to place phone calls");
}
- // Case 2: The package name of the caller matches the package name of the
- // PhoneAccountHandle, so ensure the app has MANAGE_OWN_CALLS permission.
- if (callingPackage.equals(packageName)) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_OWN_CALLS,
- "Self-managed ConnectionServices require MANAGE_OWN_CALLS permission.");
- }
-
- boolean isSelfManaged = isSelfManagedConnectionService(phoneAccountHandle);
// Note: we can still get here for the default/system dialer, even if the Phone
// permission is turned off. This is because the default/system dialer is always
@@ -1579,6 +1584,9 @@
final Intent intent = new Intent(hasCallPrivilegedPermission ?
Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, handle);
if (extras != null) {
+ if (clearPhoneAccountHandleExtra) {
+ extras.remove(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
+ }
extras.setDefusable(true);
intent.putExtras(extras);
}
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 1b0cd7e..473e7b9 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -188,6 +188,7 @@
private BluetoothLeAudio mBluetoothLeAudioService;
private boolean mLeAudioSetAsCommunicationDevice = false;
private String mLeAudioDevice;
+ private String mHearingAidDevice;
private boolean mHearingAidSetAsCommunicationDevice = false;
private BluetoothDevice mBluetoothHearingAidActiveDeviceCache;
private BluetoothAdapter mBluetoothAdapter;
@@ -444,10 +445,17 @@
}
public void clearHearingAidCommunicationDevice() {
+ Log.i(this, "clearHearingAidCommunicationDevice: mHearingAidSetAsCommunicationDevice = "
+ + mHearingAidSetAsCommunicationDevice);
if (!mHearingAidSetAsCommunicationDevice) {
return;
}
mHearingAidSetAsCommunicationDevice = false;
+ if (mHearingAidDevice != null) {
+ mBluetoothRouteManager.onAudioLost(mHearingAidDevice);
+ mHearingAidDevice = null;
+ }
+
if (mAudioManager == null) {
Log.i(this, "clearHearingAidCommunicationDevice: mAudioManager is null");
return;
@@ -551,6 +559,7 @@
Log.w(this, " Could not set hearingAid device");
} else {
Log.i(this, " hearingAid device set");
+ mHearingAidDevice = hearingAid.getAddress();
mHearingAidSetAsCommunicationDevice = true;
}
return result;
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
index 9711d49..7966f73 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
@@ -491,7 +491,8 @@
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession(((Session) args.arg1), "BRM.pM_" + msg.what);
- Log.i(LOG_TAG, "Message received: %s.", MESSAGE_CODE_TO_NAME.get(msg.what));
+ Log.i(LOG_TAG, "%s received message: %s.", this,
+ MESSAGE_CODE_TO_NAME.get(msg.what));
} else if (msg.what == RUN_RUNNABLE && msg.obj instanceof Runnable) {
Log.i(LOG_TAG, "Running runnable for testing");
} else {
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index ad6d559..c37d136 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -63,6 +63,8 @@
@RunWith(JUnit4.class)
public class BluetoothDeviceManagerTest extends TelecomTestCase {
+ private static final String DEVICE_ADDRESS_1 = "00:00:00:00:00:01";
+
@Mock BluetoothRouteManager mRouteManager;
@Mock BluetoothHeadset mBluetoothHeadset;
@Mock BluetoothAdapter mAdapter;
@@ -499,6 +501,7 @@
@Test
public void testClearHearingAidCommunicationDevice() {
AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class);
+ when(mockAudioDeviceInfo.getAddress()).thenReturn(DEVICE_ADDRESS_1);
when(mockAudioDeviceInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_HEARING_AID);
List<AudioDeviceInfo> devices = new ArrayList<>();
devices.add(mockAudioDeviceInfo);
@@ -511,6 +514,7 @@
mBluetoothDeviceManager.setHearingAidCommunicationDevice();
when(mockAudioManager.getCommunicationDevice()).thenReturn(mSpeakerInfo);
mBluetoothDeviceManager.clearHearingAidCommunicationDevice();
+ verify(mRouteManager).onAudioLost(eq(DEVICE_ADDRESS_1));
assertFalse(mBluetoothDeviceManager.isHearingAidSetAsCommunicationDevice());
}
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 639ac22..477ca9f 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -260,6 +260,8 @@
return Context.PERMISSION_CHECKER_SERVICE;
} else if (svcClass == SensorPrivacyManager.class) {
return Context.SENSOR_PRIVACY_SERVICE;
+ } else if (svcClass == NotificationManager.class) {
+ return Context.NOTIFICATION_SERVICE;
}
throw new UnsupportedOperationException();
}
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index fbc08ba..12420a8 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -16,6 +16,24 @@
package com.android.server.telecom.tests;
+import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.NotificationManager;
import android.content.Context;
import android.media.AudioAttributes;
@@ -48,21 +66,6 @@
import org.mockito.Mock;
import org.mockito.Spy;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -116,6 +119,7 @@
@Mock RingtoneFactory mockRingtoneFactory;
@Mock Vibrator mockVibrator;
@Mock InCallController mockInCallController;
+ @Mock NotificationManager mockNotificationManager;
@Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy;
@Mock InCallTonePlayer mockTonePlayer;
@@ -141,10 +145,10 @@
(AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mockSystemSettingsUtil.isHapticPlaybackSupported(any(Context.class))).thenReturn(true);
- NotificationManager notificationManager =
+ mockNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
when(mockTonePlayer.startTone()).thenReturn(true);
- when(notificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
+ when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
when(mockRingtoneFactory.hasHapticChannels(any(Ringtone.class))).thenReturn(false);
when(mockRingtonePlayer.play(any(RingtoneFactory.class), any(Call.class),
nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean()))
@@ -249,9 +253,7 @@
@Test
public void testCallWaitingButNoRingForSpecificContacts() {
mFuture.complete(false); // not using audio coupled haptics
- NotificationManager notificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- when(notificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);
+ when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);
// Start call waiting to make sure that it does stop when we start ringing
mRingerUnderTest.startCallWaiting(mockCall1);
verify(mockTonePlayer).startTone();
@@ -461,6 +463,7 @@
mRingerUnderTest.startCallWaiting(mockCall1);
Ringtone mockRingtone = mock(Ringtone.class);
when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
+ when(mockNotificationManager.getZenMode()).thenReturn(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_SILENT);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(100);
mFuture.complete(true); // using audio coupled haptics
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index 9e64aec..f6f2ae2 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -23,7 +23,6 @@
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;
@@ -748,139 +747,12 @@
}
}
-
- @SmallTest
- @Test
- public void testPlaceCallNoPermission_SelfManaged() 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
- }
- }
-
- @SmallTest
- @Test
- public void testPlaceCallNoCallPhonePermission_Managed() 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, so this app is not managing the
- //ConnectionService
- extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
-
- // Since the packages do not match, the caller needs CALL_PHONE permission
- doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
- eq(CALL_PHONE), anyString());
-
- try {
- mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
- fail("Expected SecurityException because CALL_PHONE is not set");
- } catch(SecurityException e) {
- // expected
- }
- }
-
- @SmallTest
- @Test
- public void testPlaceCallNoCallPhoneAppOp_Managed() 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, so this app is not managing the
- //ConnectionService
- extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);
-
- // Since the packages do not match, the caller needs CALL_PHONE app op
- 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, DEFAULT_DIALER_PACKAGE, null);
- fail("Expected SecurityException because CALL_PHONE is not set");
- } catch(SecurityException e) {
- // expected
- }
- }
-
- @SmallTest
- @Test
- public void testPlaceCallWithNonEmergencyPermission_SelfManaged() 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).checkCallingPermission(CALL_PHONE);
- doReturn(PackageManager.PERMISSION_DENIED)
- .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
-
- mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
- placeCallTestHelper(handle, extras, true);
- }
-
- @SmallTest
- @Test
- public void testPlaceCallWithNonEmergencyPermission_Managed() 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);
-
- 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 testPlaceCallWithNonEmergencyPermission() 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);
@@ -899,7 +771,6 @@
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_IGNORED);
@@ -918,7 +789,6 @@
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);
@@ -1405,12 +1275,6 @@
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");
}