Merge "Self-managed CS implementation continued."
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 15a4f58..c9569d7 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -146,11 +146,13 @@
         // 2) It is a conference call
         // 3) Call was not explicitly canceled
         // 4) Call is not an external call
+        // 5) Call is not a self-managed call
         if (isNewlyDisconnected &&
                 (oldState != CallState.SELECT_PHONE_ACCOUNT &&
                  !call.isConference() &&
                  !isCallCanceled) &&
-                !call.isExternalCall()) {
+                !call.isExternalCall() &&
+                !call.isSelfManaged()) {
             int type;
             if (!call.isIncoming()) {
                 type = Calls.OUTGOING_TYPE;
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 356666f..9e6ea16 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -81,6 +81,8 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
@@ -121,6 +123,7 @@
 
     private static final String TAG = "CallsManager";
 
+    private static final int HANDLER_WAIT_TIMEOUT = 10000;
     private static final int MAXIMUM_LIVE_CALLS = 1;
     private static final int MAXIMUM_HOLD_CALLS = 1;
     private static final int MAXIMUM_RINGING_CALLS = 1;
@@ -2326,6 +2329,28 @@
     }
 
     /**
+     * Blocks execution until all Telecom handlers have completed their current work.
+     */
+    public void waitOnHandlers() {
+        CountDownLatch mainHandlerLatch = new CountDownLatch(3);
+        mHandler.post(() -> {
+            mainHandlerLatch.countDown();
+        });
+        mCallAudioManager.getCallAudioModeStateMachine().getHandler().post(() -> {
+            mainHandlerLatch.countDown();
+        });
+        mCallAudioManager.getCallAudioRouteStateMachine().getHandler().post(() -> {
+            mainHandlerLatch.countDown();
+        });
+
+        try {
+            mainHandlerLatch.await(HANDLER_WAIT_TIMEOUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            Log.w(this, "waitOnHandlers: interrupted %s", e);
+        }
+    }
+
+    /**
      * Dumps the state of the {@link CallsManager}.
      *
      * @param pw The {@code IndentingPrintWriter} to write the state to.
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 4e5002c..51f11d7 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -354,6 +354,15 @@
                                 account.getAccountHandle().getComponentName().getPackageName());
                         if (account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
                             enforceRegisterSelfManaged();
+                            if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) ||
+                                    account.hasCapabilities(
+                                            PhoneAccount.CAPABILITY_CONNECTION_MANAGER) ||
+                                    account.hasCapabilities(
+                                            PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+                                throw new SecurityException("Self-managed ConnectionServices " +
+                                        "cannot also be call capable, connection managers, or " +
+                                        "SIM accounts.");
+                            }
                         }
                         if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
                             enforceRegisterSimSubscriptionPermission();
@@ -1243,6 +1252,30 @@
                 Log.endSession();
             }
         }
+
+        /**
+         * Blocks until all Telecom handlers have completed their current work.
+         *
+         * See {@link com.android.commands.telecom.Telecom}.
+         */
+        @Override
+        public void waitOnHandlers() {
+            try {
+                Log.startSession("TSI.wOH");
+                enforceModifyPermission();
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        Log.i(this, "waitOnHandlers");
+                        mCallsManager.waitOnHandlers();
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
     };
 
     private Context mContext;
@@ -1474,7 +1507,7 @@
         if (phoneAccountHandle != null) {
                 PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
                         phoneAccountHandle);
-                return phoneAccount.isSelfManaged();
+                return phoneAccount != null && phoneAccount.isSelfManaged();
         }
         return false;
     }