Provide last known cell id for emergency call am: 8330df01a7

Original change: https://android-review.googlesource.com/c/platform/packages/services/Telecomm/+/1869707

Change-Id: Iea82cbf715f351d58762c4c82d8fe16da32fd467
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index ed6d223..36d2db7 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -85,6 +85,7 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  *  Encapsulates all aspects of a given phone call throughout its lifecycle, starting
@@ -3160,6 +3161,13 @@
     void setConferenceableCalls(List<Call> conferenceableCalls) {
         mConferenceableCalls.clear();
         mConferenceableCalls.addAll(conferenceableCalls);
+        String confCallIds = "";
+        if (!conferenceableCalls.isEmpty()) {
+            confCallIds = conferenceableCalls.stream()
+                    .map(c -> c.getId())
+                    .collect(Collectors.joining(","));
+        }
+        Log.addEvent(this, LogUtils.Events.CONF_CALLS_CHANGED, confCallIds);
 
         for (Listener l : mListeners) {
             l.onConferenceableCallsChanged(this);
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 6eae3e3..4018d54 100755
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -922,6 +922,45 @@
                         } else {
                             connectIdToCheck = callId;
                         }
+
+                        // Handle the case where an existing connection was added by Telephony via
+                        // a connection manager.  The remote connection service API does not include
+                        // the ability to specify a parent connection when adding an existing
+                        // connection, so we stash the desired parent in the connection extras.
+                        if (connectionExtras != null
+                                && connectionExtras.containsKey(
+                                        Connection.EXTRA_ADD_TO_CONFERENCE_ID)
+                                && connection.getParentCallId() == null) {
+                            String parentId = connectionExtras.getString(
+                                    Connection.EXTRA_ADD_TO_CONFERENCE_ID);
+                            Log.i(ConnectionServiceWrapper.this, "addExistingConnection: remote "
+                                    + "connection will auto-add to parent %s", parentId);
+                            // Replace parcelable connection instance, swapping the new desired
+                            // parent in.
+                            connection = new ParcelableConnection(
+                                    connection.getPhoneAccount(),
+                                    connection.getState(),
+                                    connection.getConnectionCapabilities(),
+                                    connection.getConnectionProperties(),
+                                    connection.getSupportedAudioRoutes(),
+                                    connection.getHandle(),
+                                    connection.getHandlePresentation(),
+                                    connection.getCallerDisplayName(),
+                                    connection.getCallerDisplayNamePresentation(),
+                                    connection.getVideoProvider(),
+                                    connection.getVideoState(),
+                                    connection.isRingbackRequested(),
+                                    connection.getIsVoipAudioMode(),
+                                    connection.getConnectTimeMillis(),
+                                    connection.getConnectElapsedTimeMillis(),
+                                    connection.getStatusHints(),
+                                    connection.getDisconnectCause(),
+                                    connection.getConferenceableConnectionIds(),
+                                    connection.getExtras(),
+                                    parentId,
+                                    connection.getCallDirection(),
+                                    connection.getCallerNumberVerificationStatus());
+                        }
                         // Check to see if this Connection has already been added.
                         Call alreadyAddedConnection = mCallsManager
                                 .getAlreadyAddedConnection(connectIdToCheck);
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 138e441..f53f239 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -138,6 +138,7 @@
         public static final String REMOVE_CHILD = "REMOVE_CHILD";
         public static final String SET_PARENT = "SET_PARENT";
         public static final String CONF_STATE_CHANGED = "CONF_STATE_CHANGED";
+        public static final String CONF_CALLS_CHANGED = "CONF_CALLS_CHANGED";
         public static final String CALL_DIRECTION_CHANGED = "CALL_DIRECTION_CHANGED";
         public static final String MUTE = "MUTE";
         public static final String UNMUTE = "UNMUTE";
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index e9b760a..8d6e324 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -852,6 +852,7 @@
         public boolean hasManageOngoingCallsPermission(String callingPackage) {
             try {
                 Log.startSession("TSI.hMOCP");
+                enforceCallingPackage(callingPackage);
                 return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
                         mContext, Manifest.permission.MANAGE_ONGOING_CALLS,
                         Binder.getCallingPid(),
@@ -1466,6 +1467,7 @@
                 enforceCallingPackage(callingPackage);
 
                 PhoneAccountHandle phoneAccountHandle = null;
+                boolean clearPhoneAccountHandleExtra = false;
                 if (extras != null) {
                     phoneAccountHandle = extras.getParcelable(
                             TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
@@ -1477,17 +1479,24 @@
                 boolean isSelfManaged = phoneAccountHandle != null &&
                         isSelfManagedConnectionService(phoneAccountHandle);
                 if (isSelfManaged) {
-                    mContext.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_OWN_CALLS,
-                            "Self-managed ConnectionServices require MANAGE_OWN_CALLS permission.");
+                    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;
+                    }
 
-                    if (!callingPackage.equals(
+                    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 we want to ensure that it
-                        // can only place calls through itself.
-                        throw new SecurityException("Self-managed ConnectionServices can only "
-                                + "place calls through their own ConnectionService.");
+                        // 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
@@ -1522,6 +1531,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);
                         }