Merge "Add ability to add sim-initiated MO call to UI (3/4)" into lmp-dev
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index ca72ec8..9b6ece1 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -70,6 +70,8 @@
void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause);
void onSuccessfulIncomingCall(Call call);
void onFailedIncomingCall(Call call);
+ void onSuccessfulUnknownCall(Call call, int callState);
+ void onFailedUnknownCall(Call call);
void onRingbackRequested(Call call, boolean ringbackRequested);
void onPostDialWait(Call call, String remaining);
void onCallCapabilitiesChanged(Call call);
@@ -99,6 +101,10 @@
@Override
public void onFailedIncomingCall(Call call) {}
@Override
+ public void onSuccessfulUnknownCall(Call call, int callState) {}
+ @Override
+ public void onFailedUnknownCall(Call call) {}
+ @Override
public void onRingbackRequested(Call call, boolean ringbackRequested) {}
@Override
public void onPostDialWait(Call call, String remaining) {}
@@ -167,6 +173,11 @@
/** True if this is an incoming call. */
private final boolean mIsIncoming;
+ /** True if this is a currently unknown call that was not previously tracked by CallsManager,
+ * and did not originate via the regular incoming/outgoing call code paths.
+ */
+ private boolean mIsUnknown;
+
/**
* The time this call was created. Beyond logging and such, may also be used for bookkeeping
* and specifically for marking certain call attempts as failed attempts.
@@ -660,7 +671,11 @@
mConferenceableCalls.add(idMapper.getCall(id));
}
- if (mIsIncoming) {
+ if (mIsUnknown) {
+ for (Listener l : mListeners) {
+ l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection.getState()));
+ }
+ } else if (mIsIncoming) {
// We do not handle incoming calls immediately when they are verified by the connection
// service. We allow the caller-info-query code to execute first so that we can read the
// direct-to-voicemail property before deciding if we want to show the incoming call to
@@ -686,7 +701,11 @@
setDisconnectCause(disconnectCause);
CallsManager.getInstance().markCallAsDisconnected(this, disconnectCause);
- if (mIsIncoming) {
+ if (mIsUnknown) {
+ for (Listener listener : mListeners) {
+ listener.onFailedUnknownCall(this);
+ }
+ } else if (mIsIncoming) {
for (Listener listener : mListeners) {
listener.onFailedIncomingCall(this);
}
@@ -1255,6 +1274,14 @@
}
}
+ public boolean isUnknown() {
+ return mIsUnknown;
+ }
+
+ public void setIsUnknown(boolean isUnknown) {
+ mIsUnknown = isUnknown;
+ }
+
static int getStateFromConnectionState(int state) {
switch (state) {
case Connection.STATE_INITIALIZING:
diff --git a/src/com/android/server/telecom/CallReceiver.java b/src/com/android/server/telecom/CallReceiver.java
index c8fdeb4..17ca3e5 100644
--- a/src/com/android/server/telecom/CallReceiver.java
+++ b/src/com/android/server/telecom/CallReceiver.java
@@ -21,16 +21,21 @@
public class CallReceiver extends BroadcastReceiver {
private static final String TAG = CallReceiver.class.getName();
+ static final String KEY_IS_UNKNOWN_CALL = "is_unknown_call";
static final String KEY_IS_INCOMING_CALL = "is_incoming_call";
static final String KEY_IS_DEFAULT_DIALER =
"is_default_dialer";
@Override
public void onReceive(Context context, Intent intent) {
+ final boolean isUnknownCall = intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL, false);
final boolean isIncomingCall = intent.getBooleanExtra(KEY_IS_INCOMING_CALL, false);
- Log.i(TAG, "onReceive - isIncomingCall: %s", isIncomingCall);
+ Log.i(this, "onReceive - isIncomingCall: %s isUnknownCall: %s", isIncomingCall,
+ isUnknownCall);
- if (isIncomingCall) {
+ if (isUnknownCall) {
+ processUnknownCallIntent(intent);
+ } else if (isIncomingCall) {
processIncomingCallIntent(intent);
} else {
processOutgoingCallIntent(context, intent);
@@ -111,6 +116,22 @@
getCallsManager().processIncomingCallIntent(phoneAccountHandle, clientExtras);
}
+ private void processUnknownCallIntent(Intent intent) {
+ PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
+ TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
+
+ if (phoneAccountHandle == null) {
+ Log.w(this, "Rejecting unknown call due to null phone account");
+ return;
+ }
+ if (phoneAccountHandle.getComponentName() == null) {
+ Log.w(this, "Rejecting unknown call due to null component name");
+ return;
+ }
+
+ getCallsManager().addNewUnknownCall(phoneAccountHandle, intent.getExtras());
+ }
+
static CallsManager getCallsManager() {
return CallsManager.getInstance();
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 1b0a9e3..52c0b44 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -32,6 +32,7 @@
import android.telephony.TelephonyManager;
import com.android.internal.util.IndentingPrintWriter;
+
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
@@ -226,6 +227,20 @@
}
@Override
+ public void onSuccessfulUnknownCall(Call call, int callState) {
+ setCallState(call, callState);
+ Log.i(this, "onSuccessfulUnknownCall for call %s", call);
+ addCall(call);
+ }
+
+ @Override
+ public void onFailedUnknownCall(Call call) {
+ Log.i(this, "onFailedUnknownCall for call %s", call);
+ setCallState(call, CallState.DISCONNECTED);
+ call.removeListener(this);
+ }
+
+ @Override
public void onRingbackRequested(Call call, boolean ringback) {
for (CallsManagerListener listener : mListeners) {
listener.onRingbackRequested(call, ringback);
@@ -336,6 +351,27 @@
call.startCreateConnection(mPhoneAccountRegistrar);
}
+ void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
+ Uri handle = extras.getParcelable(TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE);
+ Log.i(this, "addNewUnknownCall with handle: %s", Log.pii(handle));
+ Call call = new Call(
+ mContext,
+ mConnectionServiceRepository,
+ handle,
+ null /* gatewayInfo */,
+ null /* connectionManagerPhoneAccount */,
+ phoneAccountHandle,
+ // Use onCreateIncomingConnection in TelephonyConnectionService, so that we attach
+ // to the existing connection instead of trying to create a new one.
+ true /* isIncoming */,
+ false /* isConference */);
+ call.setConnectTimeMillis(System.currentTimeMillis());
+ call.setIsUnknown(true);
+ call.setExtras(extras);
+ call.addListener(this);
+ call.startCreateConnection(mPhoneAccountRegistrar);
+ }
+
/**
* Kicks off the first steps to creating an outgoing call so that InCallUI can launch.
*
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index cacdc81..32c6107 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -643,7 +643,8 @@
call.getHandle(),
extras,
call.getVideoState()),
- call.isIncoming());
+ call.isIncoming(),
+ call.isUnknown());
} catch (RemoteException e) {
Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
mPendingResponses.remove(callId).handleCreateConnectionFailure(
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 6aae49b..0c6e25d 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -31,7 +31,7 @@
import java.util.Objects;
/**
- * This class creates connections to place new outgoing calls to attached to an existing incoming
+ * This class creates connections to place new outgoing calls or to attach to an existing incoming
* call. In either case, this class cycles through a set of connection services until:
* - a connection service returns a newly created connection in which case the call is displayed
* to the user
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 299ca24..fbbe1c9 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -37,6 +37,7 @@
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
+
// TODO: Needed for move to system service: import com.android.internal.R;
import com.android.internal.telecom.ITelecomService;
import com.android.internal.util.IndentingPrintWriter;
@@ -472,6 +473,29 @@
}
}
+ /**
+ * @see android.telecom.TelecomManager#addNewUnknownCall
+ */
+ @Override
+ public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
+ if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null &&
+ TelephonyUtil.isPstnComponentName(phoneAccountHandle.getComponentName())) {
+ mAppOpsManager.checkPackage(
+ Binder.getCallingUid(), phoneAccountHandle.getComponentName().getPackageName());
+
+ Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
+ intent.setClass(mContext, CallReceiver.class);
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtras(extras);
+ intent.putExtra(CallReceiver.KEY_IS_UNKNOWN_CALL, true);
+ intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
+ mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
+ } else {
+ Log.i(this, "Null phoneAccountHandle or not initiated by Telephony. Ignoring request"
+ + " to add new unknown call.");
+ }
+ }
+
//
// Supporting methods for the ITelecomService interface implementation.
//
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index cd9b77f..9c09a40 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -69,6 +69,7 @@
</intent-filter>
<intent-filter>
<action android:name="android.telecom.testapps.ACTION_START_INCOMING_CALL" />
+ <action android:name="android.telecom.testapps.ACTION_NEW_UNKNOWN_CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
diff --git a/tests/src/com/android/server/telecom/testapps/CallNotificationReceiver.java b/tests/src/com/android/server/telecom/testapps/CallNotificationReceiver.java
index 6105f3e..a835bf1 100644
--- a/tests/src/com/android/server/telecom/testapps/CallNotificationReceiver.java
+++ b/tests/src/com/android/server/telecom/testapps/CallNotificationReceiver.java
@@ -22,14 +22,18 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.telecom.CallState;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
+import android.util.Log;
/**
* This class receives the notification callback intents used to update call states for
* {@link TestConnectionService}.
*/
public class CallNotificationReceiver extends BroadcastReceiver {
+
+ static final String TAG = CallNotificationReceiver.class.getSimpleName();
/**
* Exit intent action is sent when the user clicks the "exit" action of the
* TestConnectionService notification. Used to cancel (remove) the notification.
@@ -83,4 +87,22 @@
TelecomManager.from(context).addNewIncomingCall(phoneAccount, extras);
}
+
+ public static void addNewUnknownCall(Context context, Uri handle, Bundle extras) {
+ Log.i(TAG, "Adding new unknown call with handle " + handle);
+ PhoneAccountHandle phoneAccount = new PhoneAccountHandle(
+ new ComponentName(context, TestConnectionService.class),
+ CallServiceNotifier.SIM_SUBSCRIPTION_ID);
+
+ if (extras == null) {
+ extras = new Bundle();
+ }
+
+ if (handle != null) {
+ extras.putParcelable(TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE, handle);
+ extras.putParcelable(TestConnectionService.EXTRA_HANDLE, handle);
+ }
+
+ TelecomManager.from(context).addNewUnknownCall(phoneAccount, extras);
+ }
}
diff --git a/tests/src/com/android/server/telecom/testapps/TestCallActivity.java b/tests/src/com/android/server/telecom/testapps/TestCallActivity.java
index f5e24ec..9c9a40b 100644
--- a/tests/src/com/android/server/telecom/testapps/TestCallActivity.java
+++ b/tests/src/com/android/server/telecom/testapps/TestCallActivity.java
@@ -36,21 +36,25 @@
public static final String ACTION_NEW_INCOMING_CALL =
"android.telecom.testapps.ACTION_START_INCOMING_CALL";
+ /*
+ * Action to exercise TelecomManager.addNewUnknownCall().
+ */
+ public static final String ACTION_NEW_UNKNOWN_CALL =
+ "android.telecom.testapps.ACTION_NEW_UNKNOWN_CALL";
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Intent intent = getIntent();
- if (intent != null && intent.getData() != null) {
- startIncomingCallBroadcast(intent.getData());
+ final String action = intent != null ? intent.getAction() : null;
+ final Uri data = intent != null ? intent.getData() : null;
+ if (ACTION_NEW_INCOMING_CALL.equals(action) && data != null) {
+ CallNotificationReceiver.sendIncomingCallIntent(this, data, false);
+ } if (ACTION_NEW_UNKNOWN_CALL.equals(action) && data != null) {
+ CallNotificationReceiver.addNewUnknownCall(this, data, intent.getExtras());
+ } else {
+ CallServiceNotifier.getInstance().updateNotification(this);
}
- CallServiceNotifier.getInstance().updateNotification(this);
finish();
}
-
- /**
- * Bypass the notification and start the test incoming call directly.
- */
- private void startIncomingCallBroadcast(Uri handle) {
- CallNotificationReceiver.sendIncomingCallIntent(this, handle, false);
- }
}
diff --git a/tests/src/com/android/server/telecom/testapps/TestConnectionService.java b/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
index b327462..389373f 100644
--- a/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -267,6 +267,7 @@
originalHandle + "]");
final TestConnection connection = new TestConnection(false /* isIncoming */);
+ connection.setAddress(handle, TelecomManager.PRESENTATION_ALLOWED);
// If the number starts with 555, then we handle it ourselves. If not, then we
// use a remote connection service.
@@ -341,6 +342,31 @@
}
}
+ @Override
+ public Connection onCreateUnknownConnection(PhoneAccountHandle connectionManagerPhoneAccount,
+ final ConnectionRequest request) {
+ PhoneAccountHandle accountHandle = request.getAccountHandle();
+ ComponentName componentName = new ComponentName(this, TestConnectionService.class);
+ if (accountHandle != null && componentName.equals(accountHandle.getComponentName())) {
+ final TestConnection connection = new TestConnection(false);
+ final Bundle extras = request.getExtras();
+ final Uri providedHandle = extras.getParcelable(EXTRA_HANDLE);
+
+ Uri handle = providedHandle == null ?
+ Uri.fromParts(PhoneAccount.SCHEME_TEL, getDummyNumber(false), null)
+ : providedHandle;
+
+ connection.setAddress(handle, TelecomManager.PRESENTATION_ALLOWED);
+ connection.setDialing();
+
+ addCall(connection);
+ return connection;
+ } else {
+ return Connection.createFailedConnection(new DisconnectCause(DisconnectCause.ERROR,
+ "Invalid inputs: " + accountHandle + " " + componentName));
+ }
+ }
+
private void activateCall(TestConnection connection) {
if (mMediaPlayer == null) {
mMediaPlayer = createMediaPlayer();