Merge "Ensure null ConnectionService references don't crash phone." into nyc-mr1-dev
diff --git a/proto/telecom.proto b/proto/telecom.proto
index f0b3d02..06dd394 100644
--- a/proto/telecom.proto
+++ b/proto/telecom.proto
@@ -149,6 +149,23 @@
   optional int64 time_millis = 2;
 }
 
+message InCallServiceInfo {
+  // Keep this up-to-date with com.android.server.telecom.InCallController.
+  enum InCallServiceType {
+    IN_CALL_SERVICE_TYPE_INVALID = 0;
+    IN_CALL_SERVICE_TYPE_DIALER_UI = 1;
+    IN_CALL_SERVICE_TYPE_SYSTEM_UI = 2;
+    IN_CALL_SERVICE_TYPE_CAR_MODE_UI = 3;
+    IN_CALL_SERVICE_TYPE_NON_UI = 4;
+  }
+
+  // The shortened component name of the in-call service.
+  optional string in_call_service_name = 1;
+
+  // The type of the in-call service
+  optional InCallServiceType in_call_service_type = 2;
+}
+
 // Information about each call.
 message CallLog {
 
@@ -227,7 +244,7 @@
   // A bitmask with bits corresponding to call technologies that were used
   // during the call. The ones that we will record are CDMA, GSM, IMS, SIP,
   // and third-party.
-  // https://googleplex-android-review.git.corp.google.com/#/c/816516/6/src/com/android/server/telecom/Analytics.java
+  // See the com.android.server.telecom.Analytics.*_PHONE constants.
   optional int32 call_technologies = 6;
 
   // Indicates the call termination code.
@@ -253,4 +270,11 @@
 
   // A list of the video events during the call.
   repeated VideoEvent video_events = 15;
+
+  // A list of the in-call services bound during the call.
+  repeated InCallServiceInfo in_call_services = 16;
+
+  // A bitmask of the properties that were set at any point during the call.
+  // Bits are defined by android.telecom.Connection.PROPERTY_* constants.
+  optional int32 connection_properties = 17;
 }
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index 0ad130b..4456734 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.ParcelableCallAnalytics;
 import android.telecom.TelecomAnalytics;
@@ -176,6 +177,12 @@
 
         public void addVideoEvent(int eventId, int videoState) {
         }
+
+        public void addInCallService(String serviceName, int type) {
+        }
+
+        public void addCallProperties(int properties) {
+        }
     }
 
     /**
@@ -207,6 +214,9 @@
 
         public boolean isVideo = false;
         public List<TelecomLogClass.VideoEvent> videoEvents;
+        public List<TelecomLogClass.InCallServiceInfo> inCallServiceInfos;
+        public int callProperties = 0;
+
         private long mTimeOfLastVideoEvent = -1;
 
         CallInfoImpl(String callId, int callDirection) {
@@ -217,6 +227,7 @@
             callTechnologies = 0;
             connectionService = "";
             videoEvents = new LinkedList<>();
+            inCallServiceInfos = new LinkedList<>();
         }
 
         CallInfoImpl(CallInfoImpl other) {
@@ -233,6 +244,7 @@
             this.callEvents = other.callEvents;
             this.isVideo = other.isVideo;
             this.videoEvents = other.videoEvents;
+            this.callProperties = other.callProperties;
 
             if (other.callTerminationReason != null) {
                 this.callTerminationReason = new DisconnectCause(
@@ -324,6 +336,18 @@
         }
 
         @Override
+        public void addInCallService(String serviceName, int type) {
+            inCallServiceInfos.add(new TelecomLogClass.InCallServiceInfo()
+                    .setInCallServiceName(serviceName)
+                    .setInCallServiceType(type));
+        }
+
+        @Override
+        public void addCallProperties(int properties) {
+            this.callProperties |= properties;
+        }
+
+        @Override
         public String toString() {
             return "{\n"
                     + "    startTime: " + startTime + '\n'
@@ -335,6 +359,9 @@
                     + "    callTerminationReason: " + getCallDisconnectReasonString() + '\n'
                     + "    connectionService: " + connectionService + '\n'
                     + "    isVideoCall: " + isVideo + '\n'
+                    + "    inCallServices: " + getInCallServicesString() + '\n'
+                    + "    callProperties: " + Connection.propertiesToStringShort(callProperties)
+                    + '\n'
                     + "}\n";
         }
 
@@ -402,7 +429,8 @@
                     .setIsEmergencyCall(isEmergency)
                     .setIsCreatedFromExistingConnection(createdFromExistingConnection)
                     .setIsEmergencyCall(isEmergency)
-                    .setIsVideoCall(isVideo);
+                    .setIsVideoCall(isVideo)
+                    .setConnectionProperties(callProperties);
 
             result.connectionService = new String[] {connectionService};
             if (callEvents != null) {
@@ -413,6 +441,9 @@
             }
             result.videoEvents =
                     videoEvents.toArray(new TelecomLogClass.VideoEvent[videoEvents.size()]);
+            result.inCallServices = inCallServiceInfos.toArray(
+                    new TelecomLogClass.InCallServiceInfo[inCallServiceInfos.size()]);
+
             return result;
         }
 
@@ -448,6 +479,21 @@
                 return "NOT SET";
             }
         }
+
+        private String getInCallServicesString() {
+            StringBuilder s = new StringBuilder();
+            s.append("[\n");
+            for (TelecomLogClass.InCallServiceInfo service : inCallServiceInfos) {
+                s.append("    ");
+                s.append("name: ");
+                s.append(service.getInCallServiceName());
+                s.append(" type: ");
+                s.append(service.getInCallServiceType());
+                s.append("\n");
+            }
+            s.append("]");
+            return s.toString();
+        }
     }
     public static final String TAG = "TelecomAnalytics";
 
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index e225e8a..8d98179 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1052,6 +1052,8 @@
 
             }
 
+            mAnalytics.addCallProperties(mConnectionProperties);
+
             int xorProps = previousProperties ^ mConnectionProperties;
             Log.event(this, Log.Events.PROPERTY_CHANGE,
                     "Current: [%s], Removed [%s], Added [%s]",
@@ -2146,6 +2148,7 @@
      * @param extras The extras.
      */
     public void onConnectionEvent(String event, Bundle extras) {
+        Log.event(this, Log.Events.CONNECTION_EVENT, event);
         if (Connection.EVENT_ON_HOLD_TONE_START.equals(event)) {
             mIsRemotelyHeld = true;
             Log.event(this, Log.Events.REMOTELY_HELD);
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index b11a3e9..aff1362 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -452,6 +452,11 @@
         return mCallAudioRouteStateMachine;
     }
 
+    @VisibleForTesting
+    public CallAudioModeStateMachine getCallAudioModeStateMachine() {
+        return mCallAudioModeStateMachine;
+    }
+
     void dump(IndentingPrintWriter pw) {
         pw.println("All calls:");
         pw.increaseIndent();
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index a501dca..3cc2dad 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -1080,6 +1080,7 @@
     private final StatusBarNotifier mStatusBarNotifier;
     private final CallAudioManager.AudioServiceFactory mAudioServiceFactory;
     private final boolean mDoesDeviceSupportEarpieceRoute;
+    private final TelecomSystem.SyncRoot mLock;
     private boolean mHasUserExplicitlyLeftBluetooth = false;
 
     private HashMap<String, Integer> mStateNameToRouteCode;
@@ -1117,6 +1118,7 @@
         mStatusBarNotifier = statusBarNotifier;
         mAudioServiceFactory = audioServiceFactory;
         mDoesDeviceSupportEarpieceRoute = doesDeviceSupportEarpieceRoute;
+        mLock = callsManager.getLock();
 
         mStateNameToRouteCode = new HashMap<>(8);
         mStateNameToRouteCode.put(mQuiescentEarpieceRoute.getName(), ROUTE_EARPIECE);
@@ -1298,18 +1300,20 @@
     }
 
     private void setSystemAudioState(CallAudioState newCallAudioState, boolean force) {
-        Log.i(this, "setSystemAudioState: changing from %s to %s", mLastKnownCallAudioState,
-                newCallAudioState);
-        if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) {
-            if (newCallAudioState.getRoute() != mLastKnownCallAudioState.getRoute()) {
-                Log.event(mCallsManager.getForegroundCall(),
-                        AUDIO_ROUTE_TO_LOG_EVENT.get(newCallAudioState.getRoute(),
-                                Log.Events.AUDIO_ROUTE));
-            }
+        synchronized (mLock) {
+            Log.i(this, "setSystemAudioState: changing from %s to %s", mLastKnownCallAudioState,
+                    newCallAudioState);
+            if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) {
+                if (newCallAudioState.getRoute() != mLastKnownCallAudioState.getRoute()) {
+                    Log.event(mCallsManager.getForegroundCall(),
+                            AUDIO_ROUTE_TO_LOG_EVENT.get(newCallAudioState.getRoute(),
+                                    Log.Events.AUDIO_ROUTE));
+                }
 
-            mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState);
-            updateAudioForForegroundCall(newCallAudioState);
-            mLastKnownCallAudioState = newCallAudioState;
+                mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState);
+                updateAudioForForegroundCall(newCallAudioState);
+                mLastKnownCallAudioState = newCallAudioState;
+            }
         }
     }
 
diff --git a/src/com/android/server/telecom/CallerInfoLookupHelper.java b/src/com/android/server/telecom/CallerInfoLookupHelper.java
index 0dec317..e557c8a 100644
--- a/src/com/android/server/telecom/CallerInfoLookupHelper.java
+++ b/src/com/android/server/telecom/CallerInfoLookupHelper.java
@@ -150,7 +150,7 @@
                         }
                     } else {
                         Log.i(CallerInfoLookupHelper.this, "CI query for handle %s has completed," +
-                                " but there are no listeners left.", handle);
+                                " but there are no listeners left.", Log.piiHandle(handle));
                     }
                 } finally {
                     Log.endSession();
@@ -197,7 +197,8 @@
                         mQueryEntries.remove(handle);
                     } else {
                         Log.i(CallerInfoLookupHelper.this, "Photo query for handle %s has" +
-                                " completed, but there are no listeners left.", handle);
+                                " completed, but there are no listeners left.",
+                                Log.piiHandle(handle));
                     }
                 } finally {
                     Log.endSession();
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index f24ffc0..2157bf3 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -79,12 +79,16 @@
     }
 
     private class InCallServiceInfo {
-        private ComponentName mComponentName;
+        private final ComponentName mComponentName;
         private boolean mIsExternalCallsSupported;
+        private final int mType;
 
-        public InCallServiceInfo(ComponentName componentName, boolean isExternalCallsSupported) {
+        public InCallServiceInfo(ComponentName componentName,
+                boolean isExternalCallsSupported,
+                int type) {
             mComponentName = componentName;
             mIsExternalCallsSupported = isExternalCallsSupported;
+            mType = type;
         }
 
         public ComponentName getComponentName() {
@@ -95,6 +99,10 @@
             return mIsExternalCallsSupported;
         }
 
+        public int getType() {
+            return mType;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (this == o) {
@@ -192,6 +200,12 @@
                 mIsConnected = false;
             }
 
+            if (call != null && mIsConnected) {
+                call.getAnalytics().addInCallService(
+                        mInCallServiceInfo.getComponentName().flattenToShortString(),
+                        mInCallServiceInfo.getType());
+            }
+
             return mIsConnected;
         }
 
@@ -920,7 +934,7 @@
             // Last Resort: Try to bind to the ComponentName given directly.
             Log.e(this, new Exception(), "Package Manager could not find ComponentName: "
                     + componentName +". Trying to bind anyway.");
-            return new InCallServiceInfo(componentName, false);
+            return new InCallServiceInfo(componentName, false, type);
         }
     }
 
@@ -974,7 +988,7 @@
 
                     retval.add(new InCallServiceInfo(
                             new ComponentName(serviceInfo.packageName, serviceInfo.name),
-                            isExternalCallsSupported));
+                            isExternalCallsSupported, requestedType));
                 }
             }
         }
diff --git a/src/com/android/server/telecom/Log.java b/src/com/android/server/telecom/Log.java
index 29d9576..2282ff0 100644
--- a/src/com/android/server/telecom/Log.java
+++ b/src/com/android/server/telecom/Log.java
@@ -170,6 +170,7 @@
         public static final String IS_EXTERNAL = "IS_EXTERNAL";
         public static final String PROPERTY_CHANGE = "PROPERTY_CHANGE";
         public static final String CAPABILITY_CHANGE = "CAPABILITY_CHANGE";
+        public static final String CONNECTION_EVENT = "CONNECTION_EVENT";
 
         public static class Timings {
             public static final String ACCEPT_TIMING = "accept";
diff --git a/src/com/android/server/telecom/VideoProviderProxy.java b/src/com/android/server/telecom/VideoProviderProxy.java
index 6b63255..3722b59 100644
--- a/src/com/android/server/telecom/VideoProviderProxy.java
+++ b/src/com/android/server/telecom/VideoProviderProxy.java
@@ -205,7 +205,8 @@
         @Override
         public void handleCallSessionEvent(int event) {
             synchronized (mLock) {
-                logFromVideoProvider("handleCallSessionEvent: " + event);
+                logFromVideoProvider("handleCallSessionEvent: " +
+                        Connection.VideoProvider.sessionEventToString(event));
                 VideoProviderProxy.this.handleCallSessionEvent(event);
             }
         }
@@ -477,7 +478,7 @@
      * @param toLog The message to log.
      */
     private void logFromInCall(String toLog) {
-        Log.v(this, "IC->VP: " + toLog);
+        Log.i(this, "IC->VP (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog);
     }
 
     /**
@@ -487,6 +488,6 @@
      * @param toLog The message to log.
      */
     private void logFromVideoProvider(String toLog) {
-        Log.v(this, "VP->IC: " + toLog);
+        Log.i(this, "VP->IC (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog);
     }
 }
diff --git a/tests/Android.mk b/tests/Android.mk
index 1065ad1..8a8113b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,7 +21,8 @@
         android-ex-camera2 \
         android-support-v4 \
         guava \
-        mockito-target
+        mockito-target \
+        platform-test-annotations
 
 LOCAL_SRC_FILES := \
         $(call all-java-files-under, src) \
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
index d8e152a..81d4aa5 100644
--- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom.tests;
 
 import android.content.Context;
+import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.InCallService;
 import android.telecom.ParcelableCallAnalytics;
@@ -54,6 +55,7 @@
                 "650-555-1212",
                 mPhoneAccountA0.getAccountHandle(),
                 mConnectionServiceFixtureA);
+
         Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
 
         assertTrue(analyticsMap.containsKey(testCall.mCallId));
@@ -250,7 +252,7 @@
         sessions.stream()
                 .filter(s -> Log.Sessions.CSW_ADD_CONFERENCE_CALL.equals(
                         Analytics.sSessionIdToLogSession.get(s.getKey())))
-                .forEach(s -> assertTrue(s.getTime() > minTime));
+                .forEach(s -> assertTrue(s.getTime() >= minTime));
     }
 
     @MediumTest
@@ -300,6 +302,41 @@
                 ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED));
     }
 
+    @MediumTest
+    public void testAnalyticsConnectionProperties() throws Exception {
+        Analytics.reset();
+        IdPair testCall = startAndMakeActiveIncomingCall(
+                "650-555-1212",
+                mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA);
+
+        int properties1 = Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE
+                | Connection.PROPERTY_WIFI
+                | Connection.PROPERTY_EMERGENCY_CALLBACK_MODE;
+        int properties2 = Connection.PROPERTY_HIGH_DEF_AUDIO
+                | Connection.PROPERTY_WIFI;
+        int expectedProperties = properties1 | properties2;
+
+        mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties =
+                properties1;
+        mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId);
+        mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties =
+                properties2;
+        mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId);
+
+        mConnectionServiceFixtureA.
+                sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        Analytics.dumpToEncodedProto(pw, new String[]{});
+        TelecomLogClass.TelecomLog analyticsProto =
+                TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT));
+
+        assertEquals(expectedProperties,
+                analyticsProto.callLogs[0].getConnectionProperties() & expectedProperties);
+    }
+
     private void assertIsRoundedToOneSigFig(long x) {
         assertEquals(x, Analytics.roundToOneSigFig(x));
     }
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index ceec91b..6688ca0 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -278,6 +278,7 @@
                 .createConnection(any(PhoneAccountHandle.class), anyString(),
                         any(ConnectionRequest.class), eq(true), eq(false));
 
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
         for (CallerInfoAsyncQueryFactoryFixture.Request request :
                 mCallerInfoAsyncQueryFactoryFixture.mRequests) {
@@ -314,10 +315,12 @@
         mTelecomSystem.getTelecomServiceImpl().getBinder()
                 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
 
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         verify(mConnectionServiceFixtureA.getTestDouble())
                 .createConnection(any(PhoneAccountHandle.class), anyString(),
                         any(ConnectionRequest.class), eq(true), eq(false));
 
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         // Never reply to the caller info lookup.
         assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
 
@@ -357,10 +360,12 @@
         mTelecomSystem.getTelecomServiceImpl().getBinder()
                 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
 
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         verify(mConnectionServiceFixtureA.getTestDouble())
                 .createConnection(any(PhoneAccountHandle.class), anyString(),
                         any(ConnectionRequest.class), eq(true), eq(false));
 
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
         for (CallerInfoAsyncQueryFactoryFixture.Request request :
                 mCallerInfoAsyncQueryFactoryFixture.mRequests) {
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 615fd0e..4e5fe69 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -32,6 +32,7 @@
 import com.android.server.telecom.ConnectionServiceWrapper;
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.StatusBarNotifier;
+import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.WiredHeadsetManager;
 
 import org.mockito.ArgumentCaptor;
@@ -117,6 +118,7 @@
     private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
     private static final int TEST_TIMEOUT = 500;
     private AudioManager mockAudioManager;
+    private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
 
     @Override
     public void setUp() throws Exception {
@@ -133,6 +135,7 @@
         };
 
         when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
+        when(mockCallsManager.getLock()).thenReturn(mLock);
         when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
         when(fakeCall.isAlive()).thenReturn(true);
         doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
@@ -856,6 +859,7 @@
         reset(mockAudioManager, mockBluetoothManager, mockCallsManager,
                 mockConnectionServiceWrapper);
         when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
+        when(mockCallsManager.getLock()).thenReturn(mLock);
         doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
                 any(CallAudioState.class));
     }
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index b8dcb68..e9db543 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -28,14 +28,17 @@
 import android.location.CountryListener;
 import android.net.Uri;
 import android.os.Looper;
+import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
 import android.telecom.DisconnectCause;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.VideoProfile;
+import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -53,6 +56,7 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -195,8 +199,13 @@
     public void testDontLogCallsFromEmergencyAccount() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
                 .thenReturn(makeFakePhoneAccount(EMERGENCY_ACCT_HANDLE, 0));
-        mComponentContextFixture.putBooleanResource(R.bool.allow_emergency_numbers_in_call_log,
-                false);
+        CarrierConfigManager mockCarrierConfigManager =
+                (CarrierConfigManager) mComponentContextFixture.getTestDouble()
+                        .getApplicationContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false);
+        when(mockCarrierConfigManager.getConfig()).thenReturn(bundle);
+
         Call fakeCall = makeFakeCall(
                 DisconnectCause.OTHER, // disconnectCauseCode
                 false, // isConference
@@ -285,7 +294,9 @@
         ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID);
         assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE),
                 Integer.valueOf(CallLog.Calls.MISSED_TYPE));
-        verify(mMissedCallNotifier).showMissedCallNotification(fakeMissedCall);
+        // Timeout needed because showMissedCallNotification is called from onPostExecute.
+        verify(mMissedCallNotifier, timeout(TEST_TIMEOUT_MILLIS))
+                .showMissedCallNotification(fakeMissedCall);
     }
 
     @MediumTest
@@ -413,6 +424,7 @@
     }
 
     @MediumTest
+    @Postsubmit
     public void testLogCallDirectionOutgoingWithMultiUserCapability() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
                 .thenReturn(makeFakePhoneAccount(mOtherUserAccountHandle,
@@ -506,6 +518,7 @@
     }
 
     @MediumTest
+    @Postsubmit
     public void testLogCallDirectionOutgoingFromManagedProfile() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
                 .thenReturn(makeFakePhoneAccount(mManagedProfileAccountHandle, 0));
@@ -656,10 +669,13 @@
 
     private void verifyNoInsertion() {
         try {
-            verify(mContentProvider, timeout(TEST_TIMEOUT_MILLIS).never()).insert(any(String.class),
+            Thread.sleep(TEST_TIMEOUT_MILLIS);
+            verify(mContentProvider, never()).insert(any(String.class),
                     any(Uri.class), any(ContentValues.class));
         } catch (android.os.RemoteException e) {
             fail("Remote exception occurred during test execution");
+        } catch (InterruptedException e) {
+            e.printStackTrace();
         }
     }
 
@@ -667,10 +683,13 @@
     private void verifyNoInsertionInUser(int userId) {
         try {
             Uri uri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI, userId);
-            verify(getContentProviderForUser(userId), timeout(TEST_TIMEOUT_MILLIS).never())
+            Thread.sleep(TEST_TIMEOUT_MILLIS);
+            verify(getContentProviderForUser(userId), never())
                     .insert(any(String.class), eq(uri), any(ContentValues.class));
         } catch (android.os.RemoteException e) {
             fail("Remote exception occurred during test execution");
+        } catch (InterruptedException e) {
+            e.printStackTrace();
         }
     }
 
@@ -719,6 +738,8 @@
         when(fakeCall.getViaNumber()).thenReturn(viaNumber);
         when(fakeCall.getInitiatingUser()).thenReturn(initiatingUser);
         when(fakeCall.getCallDataUsage()).thenReturn(callDataUsage);
+        when(fakeCall.isEmergencyCall()).thenReturn(
+                phoneAccountHandle.equals(EMERGENCY_ACCT_HANDLE));
         return fakeCall;
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 962ab10..255f3ea 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -434,6 +434,11 @@
         }
     }
 
+    public void sendSetConnectionProperties(String id) throws Exception {
+        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
+            a.setConnectionProperties(id, mConnectionById.get(id).properties);
+        }
+    }
     public void sendSetIsConferenced(String id) throws Exception {
         for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
             a.setIsConferenced(id, mConnectionById.get(id).conferenceId);
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index cf72225..f5c0439 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -39,6 +39,7 @@
 
 import com.android.internal.telecom.IInCallAdapter;
 import com.android.internal.telecom.IInCallService;
+import com.android.server.telecom.Analytics;
 import com.android.server.telecom.BluetoothHeadsetProxy;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallsManager;
@@ -101,6 +102,7 @@
     public void setUp() throws Exception {
         super.setUp();
         MockitoAnnotations.initMocks(this);
+        when(mMockCall.getAnalytics()).thenReturn(new Analytics.CallInfo());
         doReturn(mMockResources).when(mMockContext).getResources();
         doReturn(SYS_PKG).when(mMockResources).getString(R.string.ui_default_package);
         doReturn(SYS_CLASS).when(mMockResources).getString(R.string.incall_default_class);
@@ -121,7 +123,6 @@
         when(mMockCall.isIncoming()).thenReturn(true);
         when(mMockCall.isExternalCall()).thenReturn(false);
 
-        Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
         setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
         mInCallController.bindToServices(mMockCall);
 
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index 98231ce..8de54bf 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -53,7 +53,9 @@
 
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
+import org.mockito.Matchers;
 import org.mockito.Mock;
+import org.mockito.internal.matchers.VarargMatcher;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -139,6 +141,13 @@
         }
     }
 
+    private static class IntVarArgMatcher extends ArgumentMatcher<int[]> implements VarargMatcher {
+        @Override
+        public boolean matches(Object argument) {
+            return true;
+        }
+    }
+
     private ITelecomService.Stub mTSIBinder;
     private AppOpsManager mAppOpsManager;
     private UserManager mUserManager;
@@ -859,7 +868,7 @@
     public void testEndCallWithNoForegroundCall() throws Exception {
         Call call = mock(Call.class);
         when(call.getState()).thenReturn(CallState.ACTIVE);
-        when(mFakeCallsManager.getFirstCallWithState(anyInt(), anyInt(), anyInt(), anyInt()))
+        when(mFakeCallsManager.getFirstCallWithState(argThat(new IntVarArgMatcher())))
                 .thenReturn(call);
         assertTrue(mTSIBinder.endCall());
         verify(call).disconnect();
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index c8a1285..d275747 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -61,6 +61,7 @@
 import com.android.server.telecom.AsyncRingtonePlayer;
 import com.android.server.telecom.BluetoothPhoneServiceImpl;
 import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioRouteStateMachine;
 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.CallsManagerListenerBase;
@@ -75,8 +76,10 @@
 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
 import com.android.server.telecom.ProximitySensorManager;
 import com.android.server.telecom.ProximitySensorManagerFactory;
+import com.android.server.telecom.Runnable;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
+import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
 import com.android.server.telecom.components.UserCallIntentProcessor;
 import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
 
@@ -89,6 +92,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Implements mocks and functionality required to implement telecom system tests.
@@ -197,7 +202,8 @@
                     .addSupportedUriScheme("tel")
                     .setCapabilities(
                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
-                            PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+                                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+                                    PhoneAccount.CAPABILITY_VIDEO_CALLING)
                     .build();
     final PhoneAccount mPhoneAccountA1 =
             PhoneAccount.builder(
@@ -342,7 +348,7 @@
 
         mTimeoutsAdapter = mock(Timeouts.Adapter.class);
         when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class)))
-                .thenReturn(TEST_TIMEOUT / 10L);
+                .thenReturn(TEST_TIMEOUT / 5L);
 
         mTelecomSystem = new TelecomSystem(
                 mComponentContextFixture.getTestDouble(),
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index ca56247..0319e81 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -18,11 +18,14 @@
 
 import org.mockito.ArgumentCaptor;
 
+import android.os.RemoteException;
 import android.telecom.CallAudioState;
 import android.telecom.VideoProfile;
 import android.test.suitebuilder.annotation.MediumTest;
 
+import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
+import com.android.server.telecom.Log;
 
 import java.util.List;
 
@@ -134,13 +137,25 @@
     private void verifyAudioRoute(int expectedRoute) throws Exception {
         // Capture all onCallAudioStateChanged callbacks to InCall.
         CallAudioRouteStateMachine carsm = mTelecomSystem.getCallsManager()
-                        .getCallAudioManager().getCallAudioRouteStateMachine();
+                .getCallAudioManager().getCallAudioRouteStateMachine();
+        CallAudioModeStateMachine camsm = mTelecomSystem.getCallsManager()
+                .getCallAudioManager().getCallAudioModeStateMachine();
+        waitForHandlerAction(camsm.getHandler(), TEST_TIMEOUT);
+        final boolean[] success = {true};
+        carsm.sendMessage(CallAudioRouteStateMachine.RUN_RUNNABLE, (Runnable) () -> {
+            ArgumentCaptor<CallAudioState> callAudioStateArgumentCaptor = ArgumentCaptor.forClass(
+                    CallAudioState.class);
+            try {
+                verify(mInCallServiceFixtureX.getTestDouble(), atLeastOnce())
+                        .onCallAudioStateChanged(callAudioStateArgumentCaptor.capture());
+            } catch (RemoteException e) {
+                fail("Remote exception in InCallServiceFixture");
+            }
+            List<CallAudioState> changes = callAudioStateArgumentCaptor.getAllValues();
+            assertEquals(expectedRoute, changes.get(changes.size() - 1).getRoute());
+            success[0] = true;
+        });
         waitForHandlerAction(carsm.getHandler(), TEST_TIMEOUT);
-        ArgumentCaptor<CallAudioState> callAudioStateArgumentCaptor = ArgumentCaptor.forClass(
-                CallAudioState.class);
-        verify(mInCallServiceFixtureX.getTestDouble(), atLeastOnce()).onCallAudioStateChanged(
-                callAudioStateArgumentCaptor.capture());
-        List<CallAudioState> changes = callAudioStateArgumentCaptor.getAllValues();
-        assertEquals(expectedRoute, changes.get(changes.size() - 1).getRoute());
+        assertTrue(success[0]);
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
index 92f876b..993679e 100644
--- a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
@@ -113,6 +113,7 @@
 
         mConnectionInfo = mConnectionServiceFixtureA.mConnectionById.get(mCallIds.mConnectionId);
         mVerificationLock = new CountDownLatch(1);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
     }
 
     @Override