Merge "Exempt tests from hidden API checks." into pi-dev
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 6f1693a..b5e2958 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1172,6 +1172,12 @@
return false;
}
+ if (!PhoneAccount.SCHEME_SIP.equals(getHandle().getScheme()) &&
+ !PhoneAccount.SCHEME_TEL.equals(getHandle().getScheme())) {
+ // Can't log schemes other than SIP or TEL for now.
+ return false;
+ }
+
return phoneAccount.getExtras() != null && phoneAccount.getExtras().getBoolean(
PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, false);
}
diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java
index d90cba4..ff3b7b2 100644
--- a/src/com/android/server/telecom/CallIntentProcessor.java
+++ b/src/com/android/server/telecom/CallIntentProcessor.java
@@ -101,9 +101,9 @@
String scheme = handle.getScheme();
String uriString = handle.getSchemeSpecificPart();
- if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
- handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ?
- PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null);
+ // Ensure sip URIs dialed using TEL scheme get converted to SIP scheme.
+ if (PhoneAccount.SCHEME_TEL.equals(scheme) && PhoneNumberUtils.isUriNumber(uriString)) {
+ handle = Uri.fromParts(PhoneAccount.SCHEME_SIP, uriString, null);
}
PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index f7953b1..099e6d3 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -516,6 +516,20 @@
return;
}
+ // Check DISALLOW_OUTGOING_CALLS restriction.
+ // Only ecbm calls are allowed through when users with the DISALLOW_OUTGOING_CALLS
+ // restriction are the current user.
+ final UserManager userManager = (UserManager) mContext.getSystemService(
+ Context.USER_SERVICE);
+ if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
+ mCurrentUserHandle)) {
+ Log.w(this, "Rejecting non-ecbm phone call due to DISALLOW_INCOMING_CALLS "
+ + "restriction");
+ incomingCall.reject(false, null);
+ mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE, false /* showNotification */);
+ return;
+ }
+
List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index 3357d9b..02692c5 100644
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -16,9 +16,12 @@
package com.android.server.telecom;
+import android.content.Context;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
@@ -32,14 +35,16 @@
* binding to it. This adapter can receive commands and updates until the in-call app is unbound.
*/
class InCallAdapter extends IInCallAdapter.Stub {
+ private final Context mContext;
private final CallsManager mCallsManager;
private final CallIdMapper mCallIdMapper;
private final TelecomSystem.SyncRoot mLock;
private final String mOwnerComponentName;
/** Persists the specified parameters. */
- public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper,
+ public InCallAdapter(Context context, CallsManager callsManager, CallIdMapper callIdMapper,
TelecomSystem.SyncRoot lock, String ownerComponentName) {
+ mContext = context;
mCallsManager = callsManager;
mCallIdMapper = callIdMapper;
mLock = lock;
@@ -96,6 +101,17 @@
public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
try {
Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
+ UserHandle callingUser = UserHandle.of(UserHandle.getUserId(Binder.getCallingUid()));
+ UserManager userManager = mContext.getSystemService(UserManager.class);
+
+ // Check to make sure the in-call app's user isn't restricted from sending SMS. If so,
+ // silently drop the outgoing message.
+ if (rejectWithMessage && userManager.hasUserRestriction(
+ UserManager.DISALLOW_SMS, callingUser)) {
+ rejectWithMessage = false;
+ textMessage = null;
+ }
+
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 9d20d4a..7aaa770 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -1309,6 +1309,7 @@
try {
inCallService.setInCallAdapter(
new InCallAdapter(
+ mContext,
mCallsManager,
mCallIdMapper,
mLock,
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index a7e21ad..3797c68 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -144,6 +144,9 @@
return;
}
+ // TODO: Remove the assumption that phone numbers are either SIP or TEL.
+ // This does not impact self-managed ConnectionServices as they do not use the
+ // NewOutgoingCallIntentBroadcaster.
Uri resultHandleUri = Uri.fromParts(
mPhoneNumberUtilsAdapter.isUriNumber(resultNumber) ?
PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL,
@@ -219,73 +222,88 @@
}
}
- String number = mPhoneNumberUtilsAdapter.getNumberFromIntent(intent, mContext);
- if (TextUtils.isEmpty(number)) {
- Log.w(this, "Empty number obtained from the call intent.");
- return DisconnectCause.NO_PHONE_NUMBER_SUPPLIED;
- }
-
- boolean isUriNumber = mPhoneNumberUtilsAdapter.isUriNumber(number);
- if (!isUriNumber) {
- number = mPhoneNumberUtilsAdapter.convertKeypadLettersToDigits(number);
- number = mPhoneNumberUtilsAdapter.stripSeparators(number);
- }
-
- final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
- Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
-
- rewriteCallIntentAction(intent, isPotentialEmergencyNumber);
- action = intent.getAction();
- // True for certain types of numbers that are not intended to be intercepted or modified
- // by third parties (e.g. emergency numbers).
- boolean callImmediately = false;
-
- if (Intent.ACTION_CALL.equals(action)) {
- if (isPotentialEmergencyNumber) {
- if (!mIsDefaultOrSystemPhoneApp) {
- Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
- + "unless caller is system or default dialer.", number, intent);
- launchSystemDialer(intent.getData());
- return DisconnectCause.OUTGOING_CANCELED;
- } else {
- callImmediately = true;
- }
- }
- } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
- if (!isPotentialEmergencyNumber) {
- Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
- + "Intent %s.", number, intent);
- return DisconnectCause.OUTGOING_CANCELED;
- }
- callImmediately = true;
- } else {
- Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
- return DisconnectCause.INVALID_NUMBER;
- }
-
- // True for all managed calls, false for self-managed calls.
- boolean sendNewOutgoingCallBroadcast = true;
PhoneAccountHandle targetPhoneAccount = mIntent.getParcelableExtra(
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
+ boolean isSelfManaged = false;
if (targetPhoneAccount != null) {
PhoneAccount phoneAccount =
mCallsManager.getPhoneAccountRegistrar().getPhoneAccountUnchecked(
targetPhoneAccount);
- if (phoneAccount != null && phoneAccount.isSelfManaged()) {
- callImmediately = true;
- sendNewOutgoingCallBroadcast = false;
- Log.i(this, "Skipping NewOutgoingCallBroadcast for self-managed call.");
+ if (phoneAccount != null) {
+ isSelfManaged = phoneAccount.isSelfManaged();
}
}
- if (callImmediately) {
+ String number = "";
+ // True for certain types of numbers that are not intended to be intercepted or modified
+ // by third parties (e.g. emergency numbers).
+ boolean callImmediately = false;
+ // True for all managed calls, false for self-managed calls.
+ boolean sendNewOutgoingCallBroadcast = true;
+ Uri callingAddress = handle;
+
+ if (!isSelfManaged) {
+ // Placing a managed call
+ number = mPhoneNumberUtilsAdapter.getNumberFromIntent(intent, mContext);
+ if (TextUtils.isEmpty(number)) {
+ Log.w(this, "Empty number obtained from the call intent.");
+ return DisconnectCause.NO_PHONE_NUMBER_SUPPLIED;
+ }
+
+ // TODO: Cleanup this dialing code; it makes the assumption that we're dialing with a
+ // SIP or TEL URI.
+ boolean isUriNumber = mPhoneNumberUtilsAdapter.isUriNumber(number);
+ if (!isUriNumber) {
+ number = mPhoneNumberUtilsAdapter.convertKeypadLettersToDigits(number);
+ number = mPhoneNumberUtilsAdapter.stripSeparators(number);
+ }
+
+ final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
+ Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
+
+ rewriteCallIntentAction(intent, isPotentialEmergencyNumber);
+ action = intent.getAction();
+
+ if (Intent.ACTION_CALL.equals(action)) {
+ if (isPotentialEmergencyNumber) {
+ if (!mIsDefaultOrSystemPhoneApp) {
+ Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
+ + "unless caller is system or default dialer.", number, intent);
+ launchSystemDialer(intent.getData());
+ return DisconnectCause.OUTGOING_CANCELED;
+ } else {
+ callImmediately = true;
+ }
+ }
+ } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
+ if (!isPotentialEmergencyNumber) {
+ Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
+ + "Intent %s.", number, intent);
+ return DisconnectCause.OUTGOING_CANCELED;
+ }
+ callImmediately = true;
+ } else {
+ Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
+ return DisconnectCause.INVALID_NUMBER;
+ }
+
+ // TODO: Support dialing using URIs instead of just assuming SIP or TEL.
String scheme = isUriNumber ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL;
+ callingAddress = Uri.fromParts(scheme, number, null);
+ } else {
+ // Self-managed call.
+ callImmediately = true;
+ sendNewOutgoingCallBroadcast = false;
+ Log.i(this, "Skipping NewOutgoingCallBroadcast for self-managed call.");
+ }
+
+ if (callImmediately) {
boolean speakerphoneOn = mIntent.getBooleanExtra(
TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
int videoState = mIntent.getIntExtra(
TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
VideoProfile.STATE_AUDIO_ONLY);
- placeOutgoingCallImmediately(mCall, Uri.fromParts(scheme, number, null), null,
+ placeOutgoingCallImmediately(mCall, callingAddress, null,
speakerphoneOn, videoState);
// Don't return but instead continue and send the ACTION_NEW_OUTGOING_CALL broadcast
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index c4f9b63..1d27f45 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -18,6 +18,7 @@
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.Person;
import android.content.Context;
import android.os.VibrationEffect;
import android.telecom.Log;
@@ -279,8 +280,8 @@
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
final Bundle peopleExtras = new Bundle();
if (contactUri != null) {
- ArrayList<Notification.Person> personList = new ArrayList<>();
- personList.add(new Notification.Person().setUri(contactUri.toString()));
+ ArrayList<Person> personList = new ArrayList<>();
+ personList.add(new Person.Builder().setUri(contactUri.toString()).build());
peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList);
}
return manager.matchesCallFilter(peopleExtras);
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index 38c14d7..1a76043 100644
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -103,9 +103,9 @@
String scheme = handle.getScheme();
String uriString = handle.getSchemeSpecificPart();
- if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
- handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ?
- PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null);
+ // Ensure sip URIs dialed using TEL scheme get converted to SIP scheme.
+ if (PhoneAccount.SCHEME_TEL.equals(scheme) && PhoneNumberUtils.isUriNumber(uriString)) {
+ handle = Uri.fromParts(PhoneAccount.SCHEME_SIP, uriString, null);
}
// Check DISALLOW_OUTGOING_CALLS restriction. Note: We are skipping this check in a managed
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index ec80911..7fee263 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -583,6 +583,7 @@
|| TextUtils.isEmpty(handleString)) {
handle = null;
} else {
+ // TODO: Remove the assumption that numbers are SIP or TEL only.
handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(handleString) ?
PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL,
handleString, null);
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java
index 8518adc..4b5fa57 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java
@@ -48,6 +48,7 @@
public static String SELF_MANAGED_ACCOUNT_2 = "2";
public static String SELF_MANAGED_NAME_1 = "SuperCall";
public static String SELF_MANAGED_NAME_2 = "Mega Call";
+ public static String CUSTOM_URI_SCHEME = "custom";
private static SelfManagedCallList sInstance;
private static ComponentName COMPONENT_NAME = new ComponentName(
@@ -112,6 +113,7 @@
PhoneAccount.Builder builder = PhoneAccount.builder(handle, name)
.addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
.addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
+ .addSupportedUriScheme(CUSTOM_URI_SCHEME)
.setAddress(address)
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_VIDEO_CALLING |
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 9cc2b87..01d312b 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -437,6 +437,7 @@
MockitoAnnotations.initMocks(this);
when(mResources.getConfiguration()).thenReturn(mResourceConfiguration);
when(mResources.getString(anyInt())).thenReturn("");
+ when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
mResourceConfiguration.setLocale(Locale.TAIWAN);
// TODO: Move into actual tests