Merge "Fix broken Telecom Unit test."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b17c6f3..17c9698 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -295,12 +295,6 @@
                 android:exported="false"
                 android:process=":ui" />
 
-        <receiver android:name=".components.PrimaryCallReceiver"
-                android:exported="true"
-                android:permission="android.permission.MODIFY_PHONE_STATE"
-                android:process="system">
-        </receiver>
-
         <service android:name=".components.BluetoothPhoneService"
                 android:singleUser="true"
                 android:process="system">
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index a413814..1ba23a5 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -716,11 +716,6 @@
     /** The in-call app implementations, see {@link IInCallService}. */
     private final Map<InCallServiceInfo, IInCallService> mInCallServices = new ArrayMap<>();
 
-    /**
-     * The {@link ComponentName} of the bound In-Call UI Service.
-     */
-    private ComponentName mInCallUIComponentName;
-
     private final CallIdMapper mCallIdMapper = new CallIdMapper(Call::getId);
 
     /** The {@link ComponentName} of the default InCall UI. */
@@ -1463,18 +1458,42 @@
         pw.decreaseIndent();
     }
 
+    /**
+     * @return The package name of the UI which is currently bound, or null if none.
+     */
+    private ComponentName getConnectedUi() {
+        InCallServiceInfo connectedUi = mInCallServices.keySet().stream().filter(
+                i -> i.getType() == IN_CALL_SERVICE_TYPE_DIALER_UI
+                        || i.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI)
+                .findAny()
+                .orElse(null);
+        if (connectedUi != null) {
+            return connectedUi.mComponentName;
+        }
+        return null;
+    }
+
     public boolean doesConnectedDialerSupportRinging() {
         String ringingPackage =  null;
-        if (mInCallUIComponentName != null) {
-            ringingPackage = mInCallUIComponentName.getPackageName().trim();
+
+        ComponentName connectedPackage = getConnectedUi();
+        if (connectedPackage != null) {
+            ringingPackage = connectedPackage.getPackageName().trim();
+            Log.d(this, "doesConnectedDialerSupportRinging: alreadyConnectedPackage=%s",
+                    ringingPackage);
         }
 
         if (TextUtils.isEmpty(ringingPackage)) {
             // The current in-call UI returned nothing, so lets use the default dialer.
-            ringingPackage = DefaultDialerManager.getDefaultDialerApplication(
-                    mContext, UserHandle.USER_CURRENT);
+            ringingPackage = mDefaultDialerCache.getDefaultDialerApplication(
+                    mCallsManager.getCurrentUserHandle().getIdentifier());
+            if (ringingPackage != null) {
+                Log.d(this, "doesConnectedDialerSupportRinging: notCurentlyConnectedPackage=%s",
+                        ringingPackage);
+            }
         }
         if (TextUtils.isEmpty(ringingPackage)) {
+            Log.w(this, "doesConnectedDialerSupportRinging: no default dialer found; oh no!");
             return false;
         }
 
@@ -1484,11 +1503,15 @@
                 intent, PackageManager.GET_META_DATA,
                 mCallsManager.getCurrentUserHandle().getIdentifier());
         if (entries.isEmpty()) {
+            Log.w(this, "doesConnectedDialerSupportRinging: couldn't find dialer's package info"
+                    + " <sad trombone>");
             return false;
         }
 
         ResolveInfo info = entries.get(0);
         if (info.serviceInfo == null || info.serviceInfo.metaData == null) {
+            Log.w(this, "doesConnectedDialerSupportRinging: couldn't find dialer's metadata"
+                    + " <even sadder trombone>");
             return false;
         }
 
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 602920c..ab36585 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -1472,6 +1472,33 @@
                 Log.endSession();
             }
         }
+
+        /**
+         * See {@link TelecomManager#handleCallIntent(Intent)} ()}
+         */
+        @Override
+        public void handleCallIntent(Intent intent) {
+            try {
+                Log.startSession("TSI.hCI");
+                synchronized (mLock) {
+                    int callingUid = Binder.getCallingUid();
+
+                    long token = Binder.clearCallingIdentity();
+                    if (callingUid != Process.myUid()) {
+                        throw new SecurityException("handleCallIntent is for Telecom only");
+                    }
+                    try {
+                        Log.i(this, "handleCallIntent: handling call intent");
+                        mCallIntentProcessorAdapter.processOutgoingCallIntent(mContext,
+                                mCallsManager, intent);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
     };
 
     /**
diff --git a/src/com/android/server/telecom/components/PrimaryCallReceiver.java b/src/com/android/server/telecom/components/PrimaryCallReceiver.java
deleted file mode 100644
index f19a243..0000000
--- a/src/com/android/server/telecom/components/PrimaryCallReceiver.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.android.server.telecom.components;
-
-import com.android.server.telecom.TelecomSystem;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.telecom.Log;
-
-/**
- * Single point of entry for all outgoing and incoming calls. {@link UserCallIntentProcessor} serves
- * as a trampoline that captures call intents for individual users and forwards it to
- * the {@link PrimaryCallReceiver} which interacts with the rest of Telecom, both of which run only as
- * the primary user.
- */
-public class PrimaryCallReceiver extends BroadcastReceiver implements TelecomSystem.Component {
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        Log.startSession("PCR.oR");
-        synchronized (getTelecomSystem().getLock()) {
-            getTelecomSystem().getCallIntentProcessor().processIntent(intent);
-        }
-        Log.endSession();
-    }
-
-    @Override
-    public TelecomSystem getTelecomSystem() {
-        return TelecomSystem.getInstance();
-    }
-}
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index 0c8525f..6a8f8c8 100644
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -189,14 +189,13 @@
     }
 
     /**
-     * Potentially trampolines the intent to the broadcast receiver that runs only as the primary
-     * user.  If the caller is local to the Telecom service, we send the intent to Telecom without
-     * rebroadcasting it.
+     * Potentially trampolines the intent to Telecom via TelecomServiceImpl.
+     * If the caller is local to the Telecom service, we send the intent to Telecom without
+     * sending it through TelecomServiceImpl.
      */
     private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation) {
         intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        intent.setClass(mContext, PrimaryCallReceiver.class);
         if (isLocalInvocation) {
             // We are invoking this from TelecomServiceImpl, so TelecomSystem is available.  Don't
             // bother trampolining the intent, just sent it directly to the call intent processor.
@@ -209,7 +208,8 @@
             // We're calling from the UserCallActivity, so the TelecomSystem is not in the same
             // process; we need to trampoline to TelecomSystem in the system server process.
             Log.i(this, "sendIntentToDestination: trampoline to Telecom.");
-            mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+            TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+            tm.handleCallIntent(intent);
         }
         return true;
     }
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index c7c5675..e863d27 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -1053,8 +1053,13 @@
                 mConnectionServiceFixtureA);
 
         // Should have reverted back to earpiece.
-        assertEquals(CallAudioState.ROUTE_EARPIECE,
-                mInCallServiceFixtureX.mCallAudioState.getRoute());
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void aVoid) {
+                return mInCallServiceFixtureX.mCallAudioState.getRoute()
+                        == CallAudioState.ROUTE_EARPIECE;
+            }
+        });
     }
 
     /**
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index ad00456..25110e8 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -682,11 +682,6 @@
         Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext();
         new UserCallIntentProcessor(localAppContext, userHandle).processIntent(
                 actionCallIntent, null, true /* hasCallAppOp*/, false /* isLocal */);
-        // UserCallIntentProcessor's mContext.sendBroadcastAsUser(...) will call to an empty method
-        // as to not actually try to send an intent to PrimaryCallReceiver. We verify that it was
-        // called correctly in order to continue.
-        verify(localAppContext).sendBroadcastAsUser(actionCallIntent, UserHandle.SYSTEM);
-        mTelecomSystem.getCallIntentProcessor().processIntent(actionCallIntent);
         // Wait for handler to start CallerInfo lookup.
         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         // Send the CallerInfo lookup reply.