Merge "IMS-VT: Fix exception caused by incorrect conversion"
diff --git a/scripts/telecom_testing.sh b/scripts/telecom_testing.sh
index 6884f5f..e6423a3 100644
--- a/scripts/telecom_testing.sh
+++ b/scripts/telecom_testing.sh
@@ -51,15 +51,15 @@
     # Build and exit script early if build fails
 
     if [ $coverage = true ] ; then
-      emma_opt="EMMA_INSTRUMENT_STATIC=true"
+      emma_opt="EMMA_INSTRUMENT=true LOCAL_EMMA_INSTRUMENT=true EMMA_INSTRUMENT_STATIC=true"
     else
-      emma_opt="EMMA_INSTRUMENT_STATIC=false"
+      emma_opt="EMMA_INSTRUMENT=false"
     fi
 
     if [ $installwdep = true ] ; then
-      mmma -j40 "packages/services/Telecomm/tests" ${emma_opt}
+      (export ${emma_opt}; mmma -j40 "packages/services/Telecomm/tests")
     else
-      mmm "packages/services/Telecomm/tests" ${emma_opt}
+      (export ${emma_opt}; mmm "packages/services/Telecomm/tests")
     fi
     if [ $? -ne 0 ] ; then
       echo "Make failed! try using -a instead of -i if building with coverage"
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 4fe3242..ba89682 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -289,6 +289,8 @@
 
     private boolean mSpeakerphoneOn;
 
+    private boolean mIsDisconnectingChildCall = false;
+
     /**
      * Tracks the video states which were applicable over the duration of a call.
      * See {@link VideoProfile} for a list of valid video states.
@@ -1179,6 +1181,19 @@
         return mWasConferencePreviouslyMerged;
     }
 
+    public boolean isDisconnectingChildCall() {
+        return mIsDisconnectingChildCall;
+    }
+
+    /**
+     * Sets whether this call is a child call.
+     */
+    private void maybeSetCallAsDisconnectingChild() {
+        if (mParentCall != null) {
+            mIsDisconnectingChildCall = true;
+        }
+    }
+
     @VisibleForTesting
     public Call getConferenceLevelActiveCall() {
         return mConferenceLevelActiveCall;
@@ -1402,6 +1417,7 @@
 
         // Track that the call is now locally disconnecting.
         setLocallyDisconnecting(true);
+        maybeSetCallAsDisconnectingChild();
 
         if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT ||
                 mState == CallState.CONNECTING) {
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 8f3aefe..dd69534 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -65,6 +65,9 @@
  * mIsMuted: a boolean indicating whether the audio is muted
  */
 public class CallAudioRouteStateMachine extends StateMachine {
+    private static final String TELECOM_PACKAGE =
+            CallAudioRouteStateMachine.class.getPackage().getName();
+
     /** Direct the audio stream through the device's earpiece. */
     public static final int ROUTE_EARPIECE      = CallAudioState.ROUTE_EARPIECE;
 
@@ -167,6 +170,19 @@
                 String action = intent.getAction();
 
                 if (action.equals(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)) {
+                    // We get an this broadcast any time the notification filter is changed, even if
+                    // we are the initiator of the change.
+                    // So, we'll look at who the initiator of the manual zen rule is in the
+                    // notification manager.  If its us, then we can just exit now.
+                    String initiator =
+                            mInterruptionFilterProxy.getInterruptionModeInitiator();
+
+                    if (TELECOM_PACKAGE.equals(initiator)) {
+                        // We are the initiator of this change, so ignore it.
+                        Log.i(this, "interruptionFilterChanged - ignoring own change");
+                        return;
+                    }
+
                     if (mAreNotificationSuppressed) {
                         // If we've already set the interruption filter, and the user changes it to
                         // something other than INTERRUPTION_FILTER_ALARMS, assume we will no longer
@@ -174,6 +190,8 @@
                         mAreNotificationSuppressed =
                                 mInterruptionFilterProxy.getCurrentInterruptionFilter()
                                         == NotificationManager.INTERRUPTION_FILTER_ALARMS;
+                        Log.i(this, "interruptionFilterChanged - changing to %b",
+                                mAreNotificationSuppressed);
                     }
                 }
             } finally {
@@ -805,8 +823,8 @@
                     }
                     return HANDLED;
                 case BT_AUDIO_DISCONNECT:
-                    // Ignore BT_AUDIO_DISCONNECT when ringing, since SCO audio should not be
-                    // connected.
+                    // BT SCO might be connected when in-band ringing is enabled
+                    sendInternalMessage(SWITCH_BASELINE_ROUTE);
                     return HANDLED;
                 default:
                     return NOT_HANDLED;
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 5359859..ced282c 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -648,7 +648,7 @@
         return true;
     }
 
-    boolean hasVideoCall() {
+    public boolean hasVideoCall() {
         for (Call call : mCalls) {
             if (VideoProfile.isVideo(call.getVideoState())) {
                 return true;
@@ -1496,8 +1496,15 @@
         removeCall(call);
         Call foregroundCall = mCallAudioManager.getPossiblyHeldForegroundCall();
         if (mLocallyDisconnectingCalls.contains(call)) {
+            boolean isDisconnectingChildCall = call.isDisconnectingChildCall();
+            Log.v(this, "markCallAsRemoved: isDisconnectingChildCall = "
+                + isDisconnectingChildCall + "call -> %s", call);
             mLocallyDisconnectingCalls.remove(call);
-            if (foregroundCall != null && foregroundCall.getState() == CallState.ON_HOLD) {
+            // Auto-unhold the foreground call due to a locally disconnected call, except if the
+            // call which was disconnected is a member of a conference (don't want to auto un-hold
+            // the conference if we remove a member of the conference).
+            if (!isDisconnectingChildCall && foregroundCall != null
+                    && foregroundCall.getState() == CallState.ON_HOLD) {
                 foregroundCall.unhold();
             }
         } else if (foregroundCall != null &&
diff --git a/src/com/android/server/telecom/InterruptionFilterProxy.java b/src/com/android/server/telecom/InterruptionFilterProxy.java
index 434c341..b659de8 100644
--- a/src/com/android/server/telecom/InterruptionFilterProxy.java
+++ b/src/com/android/server/telecom/InterruptionFilterProxy.java
@@ -24,4 +24,5 @@
 public interface InterruptionFilterProxy {
     void setInterruptionFilter(int interruptionFilter);
     int getCurrentInterruptionFilter();
+    String getInterruptionModeInitiator();
 }
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index ea1db36..a066b6c 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -26,6 +26,7 @@
 import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.ServiceManager;
+import android.service.notification.ZenModeConfig;
 import android.telecom.Log;
 
 import com.android.internal.telephony.CallerInfoAsyncQuery;
@@ -170,6 +171,15 @@
                                 public int getCurrentInterruptionFilter() {
                                     return notificationManager.getCurrentInterruptionFilter();
                                 }
+
+                                @Override
+                                public String getInterruptionModeInitiator() {
+                                    ZenModeConfig config = notificationManager.getZenModeConfig();
+                                    if (config.manualRule != null) {
+                                        return config.manualRule.enabler;
+                                    }
+                                    return null;
+                                }
                             }
                     ));
         }
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 1f444f2..14fdf05 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -164,6 +164,7 @@
 
         when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
         when(mockCallsManager.getLock()).thenReturn(mLock);
+        when(mockCallsManager.hasVideoCall()).thenReturn(false);
         when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
         when(fakeCall.isAlive()).thenReturn(true);
         when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index 83cee9d..3bf044c 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -31,7 +31,6 @@
 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.support.test.filters.FlakyTest;
@@ -426,7 +425,6 @@
 
     @MediumTest
     @FlakyTest
-    @Postsubmit
     public void testLogCallDirectionOutgoingWithMultiUserCapability() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
                 .thenReturn(makeFakePhoneAccount(mOtherUserAccountHandle,
@@ -521,7 +519,6 @@
 
     @MediumTest
     @FlakyTest
-    @Postsubmit
     public void testLogCallDirectionOutgoingFromManagedProfile() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
                 .thenReturn(makeFakePhoneAccount(mManagedProfileAccountHandle, 0));
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index 6baaf85..3d2a52e 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -54,8 +54,8 @@
 import com.android.server.telecom.components.UserCallIntentProcessorFactory;
 
 import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
+import org.mockito.compat.ArgumentMatcher;
 import org.mockito.internal.matchers.VarargMatcher;
 
 import java.util.ArrayList;
@@ -114,14 +114,14 @@
         }
 
         @Override
-        public boolean matches(Object string) {
+        public boolean matchesObject(Object string) {
             return mStrings.contains(string);
         }
     }
 
     private static class IntVarArgMatcher extends ArgumentMatcher<int[]> implements VarargMatcher {
         @Override
-        public boolean matches(Object argument) {
+        public boolean matchesObject(Object argument) {
             return true;
         }
     }
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index f590e8c..78d0fec 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -181,6 +181,11 @@
         public int getCurrentInterruptionFilter() {
             return mInterruptionFilter;
         }
+
+        @Override
+        public String getInterruptionModeInitiator() {
+            return "com.android.server.telecom";
+        }
     }
     @Mock HeadsetMediaButton mHeadsetMediaButton;
     @Mock ProximitySensorManager mProximitySensorManager;