Add ability to add sim-initiated MO call to UI (1/4)

Listen to new unknown calls in PstnIncomingCallNotifier, and add them to
Telecom when a new unknown connection is detected.

Bug: 16852844

Change-Id: I8c1e3fcd0724d22839e6af388b0bbed90d5f7c9a
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 0c8f8bc..654150c 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -17,7 +17,6 @@
 package com.android.services.telephony;
 
 import android.content.BroadcastReceiver;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -27,6 +26,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
+import android.telecom.CallState;
 import android.telecom.PhoneAccount;
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
@@ -39,6 +39,7 @@
 import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
+
 import com.google.common.base.Preconditions;
 
 import java.util.Objects;
@@ -51,6 +52,7 @@
     /** New ringing connection event code. */
     private static final int EVENT_NEW_RINGING_CONNECTION = 100;
     private static final int EVENT_CDMA_CALL_WAITING = 101;
+    private static final int EVENT_UNKNOWN_CONNECTION = 102;
 
     /** The phone proxy object to listen to. */
     private final PhoneProxy mPhoneProxy;
@@ -76,6 +78,9 @@
                 case EVENT_CDMA_CALL_WAITING:
                     handleCdmaCallWaiting((AsyncResult) msg.obj);
                     break;
+                case EVENT_UNKNOWN_CONNECTION:
+                    handleNewUnknownConnection((AsyncResult) msg.obj);
+                    break;
                 default:
                     break;
             }
@@ -142,6 +147,8 @@
                         mHandler, EVENT_NEW_RINGING_CONNECTION, null);
                 mPhoneBase.registerForCallWaiting(
                         mHandler, EVENT_CDMA_CALL_WAITING, null);
+                mPhoneBase.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION,
+                        null);
             }
         }
     }
@@ -151,6 +158,7 @@
             Log.i(this, "Unregistering: %s", mPhoneBase);
             mPhoneBase.unregisterForNewRingingConnection(mHandler);
             mPhoneBase.unregisterForCallWaiting(mHandler);
+            mPhoneBase.unregisterForUnknownConnection(mHandler);
         }
     }
 
@@ -187,6 +195,29 @@
         }
     }
 
+    private void handleNewUnknownConnection(AsyncResult asyncResult) {
+        Log.i(this, "handleNewUnknownConnection");
+        Connection connection = (Connection) asyncResult.result;
+        if (connection != null) {
+            Call call = connection.getCall();
+            if (call != null && call.getState().isAlive()) {
+                addNewUnknownCall(connection);
+            }
+        }
+    }
+
+    private void addNewUnknownCall(Connection connection) {
+        Bundle extras = null;
+        if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
+                !TextUtils.isEmpty(connection.getAddress())) {
+            extras = new Bundle();
+            Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
+            extras.putParcelable(TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE, uri);
+        }
+        TelecomManager.from(mPhoneProxy.getContext()).addNewUnknownCall(
+                TelecomAccountRegistry.makePstnPhoneAccountHandle(mPhoneProxy), extras);
+    }
+
     /**
      * Sends the incoming call intent to telecom.
      */
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 9e7589c..f7c6510 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -387,7 +387,7 @@
         setVideoProvider(mOriginalConnection.getVideoProvider());
         setAudioQuality(mOriginalConnection.getAudioQuality());
 
-        updateAddress();
+        updateState();
     }
 
     protected void hangup(int telephonyDisconnectCode) {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index cb7894c..e3b78d4 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -40,6 +40,8 @@
 import com.android.internal.telephony.cdma.CDMAPhone;
 import com.android.phone.MMIDialogActivity;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -238,6 +240,57 @@
     }
 
     @Override
+    public Connection onCreateUnknownConnection(PhoneAccountHandle connectionManagerPhoneAccount,
+            ConnectionRequest request) {
+        Log.i(this, "onCreateUnknownConnection, request: " + request);
+
+        Phone phone = getPhoneForAccount(request.getAccountHandle(), false);
+        if (phone == null) {
+            return Connection.createFailedConnection(
+                    DisconnectCauseUtil.toTelecomDisconnectCause(
+                            android.telephony.DisconnectCause.ERROR_UNSPECIFIED));
+        }
+
+        final List<com.android.internal.telephony.Connection> allConnections = new ArrayList<>();
+        final Call ringingCall = phone.getRingingCall();
+        if (ringingCall.hasConnections()) {
+            allConnections.addAll(ringingCall.getConnections());
+        }
+        final Call foregroundCall = phone.getForegroundCall();
+        if (foregroundCall.hasConnections()) {
+            allConnections.addAll(foregroundCall.getConnections());
+        }
+        final Call backgroundCall = phone.getBackgroundCall();
+        if (backgroundCall.hasConnections()) {
+            allConnections.addAll(phone.getBackgroundCall().getConnections());
+        }
+
+        com.android.internal.telephony.Connection unknownConnection = null;
+        for (com.android.internal.telephony.Connection telephonyConnection : allConnections) {
+            if (!isOriginalConnectionKnown(telephonyConnection)) {
+                unknownConnection = telephonyConnection;
+                break;
+            }
+        }
+
+        if (unknownConnection == null) {
+            Log.i(this, "onCreateUnknownConnection, did not find previously unknown connection.");
+            return Connection.createCanceledConnection();
+        }
+
+        Connection connection =
+                createConnectionFor(phone, unknownConnection,
+                        !unknownConnection.isIncoming() /* isOutgoing */);
+
+        if (connection == null) {
+            connection = Connection.createCanceledConnection();
+            return Connection.createCanceledConnection();
+        } else {
+            return connection;
+        }
+    }
+
+    @Override
     public void onConference(Connection connection1, Connection connection2) {
         if (connection1 instanceof TelephonyConnection &&
                 connection2 instanceof TelephonyConnection) {