Merge "DO NOT MERGE - Merge pie-platform-release (PPRL.181205.001) into master"
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 6130bb5..5e46e5a 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -266,6 +266,8 @@
     // Instance variables for testing -- we keep the latest copy of the outgoing call futures
     // here so that we can wait on them in tests
     private CompletableFuture<Call> mLatestPostSelectionProcessingFuture;
+    private CompletableFuture<Pair<Call, List<PhoneAccountSuggestion>>>
+            mLatestPreAccountSelectionFuture;
 
     /**
      * The current telecom call ID.  Used when creating new instances of {@link Call}.  Should
@@ -1374,6 +1376,7 @@
         // the account suggestion stage and the make room for call stage.
         CompletableFuture<Pair<Call, List<PhoneAccountSuggestion>>> preSelectStage =
                 makeRoomForCall.thenCombine(suggestionFuture, Pair::create);
+        mLatestPreAccountSelectionFuture = preSelectStage;
 
         // This future takes the list of suggested accounts and the call and determines if more
         // user interaction in the form of a phone account selection screen is needed. If so, it
@@ -1529,6 +1532,9 @@
                 return CompletableFuture.completedFuture(Arrays.asList(targetPhoneAccountHandle));
             }
         }
+        if (accounts.isEmpty() || accounts.size() == 1) {
+            return CompletableFuture.completedFuture(accounts);
+        }
 
         // Do the query for whether there's a preferred contact
         final CompletableFuture<PhoneAccountHandle> userPreferredAccountForContact =
@@ -1538,8 +1544,17 @@
                 new CallerInfoLookupHelper.OnQueryCompleteListener() {
                     @Override
                     public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
-                        // TODO: construct the acct handle from caller info
-                        userPreferredAccountForContact.complete(null);
+                        if (info.preferredPhoneAccountComponent != null &&
+                                info.preferredPhoneAccountId != null &&
+                                !info.preferredPhoneAccountId.isEmpty()) {
+                            PhoneAccountHandle contactDefaultHandle = new PhoneAccountHandle(
+                                    info.preferredPhoneAccountComponent,
+                                    info.preferredPhoneAccountId,
+                                    initiatingUser);
+                            userPreferredAccountForContact.complete(contactDefaultHandle);
+                        } else {
+                            userPreferredAccountForContact.complete(null);
+                        }
                     }
 
                     @Override
@@ -1552,9 +1567,6 @@
             if (phoneAccountHandle != null) {
                 return Collections.singletonList(phoneAccountHandle);
             }
-            if (possibleAccounts.isEmpty() || possibleAccounts.size() == 1) {
-                return possibleAccounts;
-            }
             // No preset account, check if default exists that supports the URI scheme for the
             // handle and verify it can be used.
             PhoneAccountHandle defaultPhoneAccountHandle =
@@ -2455,6 +2467,11 @@
         return mLatestPostSelectionProcessingFuture;
     }
 
+    @VisibleForTesting
+    public CompletableFuture getLatestPreAccountSelectionFuture() {
+        return mLatestPreAccountSelectionFuture;
+    }
+
     /**
      * Returns the first call that it finds with the given states. The states are treated as having
      * priority order so that any call with the first state will be returned before any call with
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index 98d5bba..d0afe28 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -469,6 +469,11 @@
         }
     }
 
+    @VisibleForTesting
+    public void cleanup() {
+        sTonesPlaying = 0;
+    }
+
     private void cleanUpTonePlayer() {
         // Release focus on the main thread.
         mMainThreadHandler.post(new Runnable("ICTP.cUTP", mLock) {
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 51bfed7..193f47f 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -332,6 +332,8 @@
         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
         String callId = startOutgoingPhoneCallWithNoPhoneAccount("650-555-1212",
                 mConnectionServiceFixtureA);
+        mTelecomSystem.getCallsManager().getLatestPreAccountSelectionFuture().join();
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
                 mInCallServiceFixtureX.getCall(callId).getState());
         assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index fe4213f..d79ea33 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -35,8 +35,10 @@
 import android.content.ComponentName;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.SystemClock;
 import android.telecom.Connection;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -44,6 +46,8 @@
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telephony.CallerInfo;
 import com.android.server.telecom.AsyncRingtonePlayer;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallAudioManager;
@@ -95,7 +99,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @RunWith(JUnit4.class)
 public class CallsManagerTest extends TelecomTestCase {
@@ -122,6 +128,13 @@
             .setIsEnabled(true)
             .build();
     private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212");
+    private static final Uri TEST_ADDRESS2 = Uri.parse("tel:555-1213");
+    private static final Uri TEST_ADDRESS3 = Uri.parse("tel:555-1214");
+    private static final Map<Uri, PhoneAccountHandle> CONTACT_PREFERRED_ACCOUNT =
+            new HashMap<Uri, PhoneAccountHandle>() {{
+                put(TEST_ADDRESS2, SIM_1_HANDLE);
+                put(TEST_ADDRESS3, SIM_2_HANDLE);
+    }};
 
     private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
     @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper;
@@ -272,7 +285,13 @@
         doAnswer(invocation -> {
             Uri handle = invocation.getArgument(0);
             CallerInfoLookupHelper.OnQueryCompleteListener listener = invocation.getArgument(1);
-            listener.onCallerInfoQueryComplete(handle, null);
+            CallerInfo info = new CallerInfo();
+            if (CONTACT_PREFERRED_ACCOUNT.get(handle) != null) {
+                PhoneAccountHandle pah = CONTACT_PREFERRED_ACCOUNT.get(handle);
+                info.preferredPhoneAccountComponent = pah.getComponentName();
+                info.preferredPhoneAccountId = pah.getId();
+            }
+            listener.onCallerInfoQueryComplete(handle, info);
             return null;
         }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class),
                 any(CallerInfoLookupHelper.OnQueryCompleteListener.class));
@@ -414,6 +433,27 @@
     }
 
     /**
+     * Tests that we will use the provided target phone account if it exists.
+     * @throws Exception
+     */
+    @MediumTest
+    @Test
+    public void testUseContactSpecificAcct() throws Exception {
+        setupCallerInfoLookupHelper();
+        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
+                null);
+        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
+                any(), anyInt())).thenReturn(
+                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
+
+        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
+                null, TEST_ADDRESS2, false /* isVideo */, Process.myUserHandle()).get();
+
+        assertEquals(1, accounts.size());
+        assertTrue(accounts.contains(SIM_1_HANDLE));
+    }
+
+    /**
      * Verifies that an active call will result in playing a DTMF tone when requested.
      * @throws Exception
      */
diff --git a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
index eba494f..af59e74 100644
--- a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
+++ b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
@@ -36,6 +36,7 @@
 import android.media.ToneGenerator;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -98,6 +99,8 @@
     @Mock
     private CallAudioManager mCallAudioManager;
 
+    private InCallTonePlayer mInCallTonePlayer;
+
     @Override
     @Before
     public void setUp() throws Exception {
@@ -109,14 +112,21 @@
         mFactory = new InCallTonePlayer.Factory(mCallAudioRoutePeripheralAdapter, mLock,
                 mToneGeneratorFactory, mMediaPlayerFactory, mAudioManagerAdapter);
         mFactory.setCallAudioManager(mCallAudioManager);
+        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_ENDED);
+    }
+
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mInCallTonePlayer.cleanup();
     }
 
     @SmallTest
     @Test
     public void testNoEndCallToneInSilence() {
         when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(false);
-        InCallTonePlayer player = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_ENDED);
-        assertFalse(player.startTone());
+        assertFalse(mInCallTonePlayer.startTone());
 
         // Verify we didn't play a tone.
         verify(mCallAudioManager, never()).setIsTonePlaying(eq(true));
@@ -127,11 +137,10 @@
     @Test
     public void testEndCallToneWhenNotSilenced() {
         when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
-        InCallTonePlayer player = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_ENDED);
-        assertTrue(player.startTone());
+        assertTrue(mInCallTonePlayer.startTone());
 
         // Verify we did play a tone.
-        verify(mCallAudioManager).setIsTonePlaying(eq(true));
         verify(mMediaPlayerFactory, timeout(5000)).get(anyInt(), any());
+        verify(mCallAudioManager).setIsTonePlaying(eq(true));
     }
 }