Snap for 4778776 from 90d0828e960b44e0608b25ee641b21d01353265f to pi-release

Change-Id: Ifc51963f745193c126eea788d00205c363ce1b4c
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index d08ff39..8b1f67c 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1172,6 +1172,11 @@
             return false;
         }
 
+        if (getHandle() == null) {
+            // No point in logging a null-handle call. Some self-managed calls will have this.
+            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.
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index d57a4c7..497a3b0 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -993,7 +993,9 @@
                 final String handleScheme = handle.getSchemeSpecificPart();
                 Call fromCall = mCalls.stream()
                         .filter((c) -> mPhoneNumberUtilsAdapter.isSamePhoneNumber(
-                                c.getHandle().getSchemeSpecificPart(), handleScheme))
+                                (c.getHandle() == null
+                                        ? null : c.getHandle().getSchemeSpecificPart()),
+                                handleScheme))
                         .findFirst()
                         .orElse(null);
                 if (fromCall != null) {
@@ -1415,6 +1417,8 @@
                 com.android.internal.R.bool.config_requireCallCapableAccountForHandle);
         final boolean isOutgoingCallPermitted = isOutgoingCallPermitted(call,
                 call.getTargetPhoneAccount());
+        final String callHandleScheme =
+                call.getHandle() == null ? null : call.getHandle().getScheme();
         if (call.getTargetPhoneAccount() != null || call.isEmergencyCall()) {
             // If the account has been set, proceed to place the outgoing call.
             // Otherwise the connection will be initiated when the account is set by the user.
@@ -1429,7 +1433,7 @@
                 call.startCreateConnection(mPhoneAccountRegistrar);
             }
         } else if (mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
-                requireCallCapableAccountByHandle ? call.getHandle().getScheme() : null, false,
+                requireCallCapableAccountByHandle ? callHandleScheme : null, false,
                 call.getInitiatingUser()).isEmpty()) {
             // If there are no call capable accounts, disconnect the call.
             markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.CANCELED,
@@ -2848,11 +2852,13 @@
                 return false;
             }
 
-            // Disconnected the live call if the outgoing call is an emergency call.
-            if (isEmergency && !canHold(liveCall)) {
+            // If we have the max number of held managed calls and we're placing an emergency call,
+            // we'll disconnect the ongoing call if it cannot be held.
+            if (hasMaximumManagedHoldingCalls(call) && isEmergency && !canHold(liveCall)) {
                 call.getAnalytics().setCallIsAdditional(true);
                 liveCall.getAnalytics().setCallIsInterrupted(true);
-                liveCall.disconnect("emergency, can't hold");
+                liveCall.disconnect("disconnecting to make room for emergency call "
+                        + call.getId());
                 return true;
             }
 
@@ -3710,11 +3716,11 @@
     }
 
     public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
-
         final String handleScheme = srcAddr.getSchemeSpecificPart();
         Call fromCall = mCalls.stream()
                 .filter((c) -> mPhoneNumberUtilsAdapter.isSamePhoneNumber(
-                        c.getHandle().getSchemeSpecificPart(), handleScheme))
+                        (c.getHandle() == null ? null : c.getHandle().getSchemeSpecificPart()),
+                        handleScheme))
                 .findFirst()
                 .orElse(null);
 
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index bb011bf..6dd9a3a 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -89,6 +89,9 @@
                         }
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -109,6 +112,9 @@
                         // Log.w(this, "setActive, unknown call id: %s", msg.obj);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -129,6 +135,9 @@
                         // Log.w(this, "setRinging, unknown call id: %s", msg.obj);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -148,6 +157,9 @@
                         call.setVideoProvider(videoProvider);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -168,6 +180,9 @@
                         // Log.w(this, "setDialing, unknown call id: %s", msg.obj);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -175,7 +190,7 @@
         }
 
         @Override
-	    public void setPulling(String callId, Session.Info sessionInfo) {
+        public void setPulling(String callId, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, LogUtils.Sessions.CSW_SET_PULLING);
             long token = Binder.clearCallingIdentity();
             try {
@@ -186,6 +201,9 @@
                         mCallsManager.markCallAsPulling(call);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -208,6 +226,9 @@
                         // Log.w(this, "setDisconnected, unknown call id: %s", args.arg1);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -228,6 +249,9 @@
                         // Log.w(this, "setOnHold, unknown call id: %s", msg.obj);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -249,6 +273,9 @@
                         // Log.w(this, "setRingback, unknown call id: %s", args.arg1);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -272,6 +299,9 @@
                         }
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -294,6 +324,9 @@
                         // "setConnectionCapabilities, unknown call id: %s", msg.obj);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -313,6 +346,9 @@
                         call.setConnectionProperties(connectionProperties);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -340,6 +376,9 @@
                         // Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -363,6 +402,9 @@
                         Log.w(this, "setConferenceMergeFailed, unknown call id: %s", callId);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -451,6 +493,9 @@
                         }
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -472,6 +517,9 @@
                         // Log.w(this, "onPostDialWait, unknown call id: %s", args.arg1);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -493,6 +541,9 @@
                         // Log.w(this, "onPostDialChar, unknown call id: %s", args.arg1);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -511,6 +562,9 @@
                     ConnectionServiceWrapper.this
                             .queryRemoteConnectionServices(callingUserHandle, callback);
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -529,6 +583,9 @@
                         call.setVideoState(videoState);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -547,6 +604,9 @@
                         call.setIsVoipAudioMode(isVoip);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -564,6 +624,9 @@
                             CallAudioState.audioRouteToString(audioRoute));
                     mCallsManager.setAudioRoute(audioRoute, bluetoothAddress);
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -583,6 +646,9 @@
                         call.setStatusHints(statusHints);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -601,6 +667,9 @@
                         call.putExtras(Call.SOURCE_CONNECTION_SERVICE, extras);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -619,6 +688,9 @@
                         call.removeExtras(Call.SOURCE_CONNECTION_SERVICE, keys);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -638,6 +710,9 @@
                         call.setHandle(address, presentation);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -658,6 +733,9 @@
                         call.setCallerDisplayName(callerDisplayName, presentation);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -687,6 +765,9 @@
                         call.setConferenceableCalls(conferenceableCalls);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -694,8 +775,8 @@
         }
 
         @Override
-	public void addExistingConnection(String callId, ParcelableConnection connection,
-	        Session.Info sessionInfo) {
+        public void addExistingConnection(String callId, ParcelableConnection connection,
+                Session.Info sessionInfo) {
             Log.startSession(sessionInfo, "CSW.aEC");
             UserHandle userHandle = Binder.getCallingUserHandle();
             // Check that the Calling Package matches PhoneAccountHandle's Component Package
@@ -760,6 +841,9 @@
                                 "addExistingConnection.");
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -779,6 +863,9 @@
                         call.onConnectionEvent(event, extras);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -803,6 +890,9 @@
                         call.onRttConnectionFailure(reason);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -827,6 +917,9 @@
                         call.onRemoteRttRequest();
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -850,6 +943,9 @@
                         call.setTargetPhoneAccount(pHandle);
                     }
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
@@ -866,6 +962,9 @@
                     mConnSvrFocusListener.onConnectionServiceReleased(
                             ConnectionServiceWrapper.this);
                 }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
             } finally {
                 Binder.restoreCallingIdentity(token);
                 Log.endSession();
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index f5bcd7d..7eb3801 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -374,7 +374,8 @@
                         PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
                     CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle,
                             mPhoneAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
-                                    mCall.getHandle().getScheme()));
+                                    mCall.getHandle() == null
+                                            ? null : mCall.getHandle().getScheme()));
                     if (!mAttemptRecords.contains(callAttemptRecord)) {
                         Log.i(this, "Will try Connection Manager account %s for emergency",
                                 callManager);