Allow default and system dialers to make emergency calls via ACTION_CALL
Change-Id: I877b58e8f02f8e578e5f61456a99f24f5396714b
diff --git a/src/com/android/telecomm/CallActivity.java b/src/com/android/telecomm/CallActivity.java
index 2868216..3479001 100644
--- a/src/com/android/telecomm/CallActivity.java
+++ b/src/com/android/telecomm/CallActivity.java
@@ -17,18 +17,31 @@
package com.android.telecomm;
import android.app.Activity;
+import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.telecomm.CallServiceDescriptor;
+import android.telecomm.PhoneApplication;
import android.telecomm.TelecommConstants;
+import android.telecomm.TelecommManager;
+import android.text.TextUtils;
/**
* Activity that handles system CALL actions and forwards them to {@link CallsManager}.
* Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY.
+ *
+ * Pre-L, only the system dialer was allowed to make outgoing emergency calls via the
+ * CALL_PRIVILEGED action (which requires the system only CALL_PRIVILEGED permission).
+ *
+ * In L, the system dialer can continue to make outgoing emergency calls via CALL_PRIVILEGED.
+ * Also, the user-selected default dialer and the system dialer will be granted the ability to make
+ * emergency outgoing calls using the CALL action. In order to do this, they must call
+ * startActivityForResult on the CALL intent to allow their package name to be passed to
+ * {@link CallActivity}. Calling startActivity will continue to work on all non-emergency numbers
+ * just like it did pre-L.
*/
public class CallActivity extends Activity {
-
private CallsManager mCallsManager = CallsManager.getInstance();
/**
@@ -92,8 +105,10 @@
private void processOutgoingCallIntent(Intent intent) {
ContactInfo contactInfo = null;
NewOutgoingCallIntentBroadcaster broadcaster =
- new NewOutgoingCallIntentBroadcaster(mCallsManager, contactInfo, intent);
- broadcaster.processIntent();
+ new NewOutgoingCallIntentBroadcaster(mCallsManager, contactInfo, intent,
+ isDefaultOrSystemDialer());
+ final boolean success = broadcaster.processIntent();
+ setResult(success ? RESULT_OK : RESULT_CANCELED);
}
/**
@@ -118,4 +133,26 @@
Log.d(this, "Processing incoming call from call service [%s]", descriptor);
mCallsManager.processIncomingCallIntent(descriptor, clientExtras);
}
+
+ private boolean isDefaultOrSystemDialer() {
+ final String packageName = getCallingPackage();
+ if (TextUtils.isEmpty(packageName)) {
+ return false;
+ }
+
+ final ComponentName defaultPhoneApp = PhoneApplication.getDefaultPhoneApplication(this);
+ if (defaultPhoneApp != null) {
+ if (TextUtils.equals(defaultPhoneApp.getPackageName(), packageName)) {
+ return true;
+ }
+ }
+
+ TelecommManager telecommManager = (TelecommManager) getSystemService(TELECOMM_SERVICE);
+ final ComponentName systemPhoneApp = telecommManager.getSystemPhoneApplication();
+ if (systemPhoneApp != null) {
+ return TextUtils.equals(systemPhoneApp.getPackageName(), packageName);
+ } else {
+ return false;
+ }
+ }
}
diff --git a/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java b/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
index c40fde5..3ddeaf2 100644
--- a/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
@@ -84,12 +84,18 @@
private final CallsManager mCallsManager;
private final ContactInfo mContactInfo;
private final Intent mIntent;
+ /*
+ * Whether or not the outgoing call intent originated from the default phone application. If
+ * so, it will be allowed to make emergency calls, even with the ACTION_CALL intent.
+ */
+ private final boolean mIsDefaultOrSystemPhoneApp;
NewOutgoingCallIntentBroadcaster(CallsManager callsManager, ContactInfo contactInfo,
- Intent intent) {
+ Intent intent, boolean isDefaultPhoneApp) {
mCallsManager = callsManager;
mContactInfo = contactInfo;
mIntent = intent;
+ mIsDefaultOrSystemPhoneApp = isDefaultPhoneApp;
}
/**
@@ -147,8 +153,10 @@
* - CALL (intent launched by all third party dialers)
* - CALL_PRIVILEGED (intent launched by system apps e.g. system Dialer, voice Dialer)
* - CALL_EMERGENCY (intent launched by lock screen emergency dialer)
+ *
+ * @return whether or not the caller was allowed to start the outgoing call.
*/
- void processIntent() {
+ boolean processIntent() {
Log.v(this, "Processing call intent in OutgoingCallIntentBroadcaster.");
final Context context = TelecommApp.getInstance();
@@ -158,7 +166,7 @@
if (TextUtils.isEmpty(handle)) {
Log.w(this, "Empty handle obtained from the call intent.");
- return;
+ return false;
}
boolean isUriNumber = PhoneNumberUtils.isUriNumber(handle);
@@ -179,21 +187,25 @@
String action = intent.getAction();
if (Intent.ACTION_CALL.equals(action)) {
if (isPotentialEmergencyNumber) {
- Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s.",
- handle, intent);
- launchSystemDialer(context, intent.getData());
+ if (!mIsDefaultOrSystemPhoneApp) {
+ Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
+ + "unless caller is system or default dialer.", handle, intent);
+ launchSystemDialer(context, intent.getData());
+ return false;
+ } else {
+ callImmediately = true;
+ }
}
- callImmediately = false;
} 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.", handle, intent);
- return;
+ return false;
}
callImmediately = true;
} else {
Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
- return;
+ return false;
}
if (callImmediately) {
@@ -212,6 +224,7 @@
}
broadcastIntent(intent, handle, context, !callImmediately);
+ return true;
}
/**