Merge "Follow system mic mute state in Telecom" into pi-dev
diff --git a/res/values/config.xml b/res/values/config.xml
index ecfa12b..7db3315 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -50,4 +50,9 @@
     <!-- Determines if the granting of temporary location permission to the default dialer
          during an emergency call should be allowed. -->
     <bool name="grant_location_permission_enabled">false</bool>
+
+    <!-- When true, a simple full intensity on/off vibration pattern will be used when calls ring.
+         When false, a fancy vibration pattern which ramps up and down will be used.
+         Devices should overlay this value based on the type of vibration hardware they employ. -->
+    <bool name="use_simple_vibration_pattern">false</bool>
 </resources>
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index c7e994b..8834a41 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -2472,15 +2472,17 @@
     private void rejectHandoverTo(Call handoverTo) {
         Call handoverFrom = handoverTo.getHandoverSourceCall();
         Log.i(this, "rejectHandoverTo: from=%s, to=%s", handoverFrom.getId(), handoverTo.getId());
-        Log.addEvent(handoverFrom, LogUtils.Events.HANDOVER_FAILED, "from=%s, to=%s",
+        Log.addEvent(handoverFrom, LogUtils.Events.HANDOVER_FAILED, "from=%s, to=%s, rejected",
                 handoverTo.getId(), handoverFrom.getId());
-        Log.addEvent(handoverTo, LogUtils.Events.HANDOVER_FAILED, "from=%s, to=%s",
+        Log.addEvent(handoverTo, LogUtils.Events.HANDOVER_FAILED, "from=%s, to=%s, rejected",
                 handoverTo.getId(), handoverFrom.getId());
 
         // Inform the "from" Call (ie the source call) that the handover from it has
         // failed; this allows the InCallService to be notified that a handover it
         // initiated failed.
         handoverFrom.onConnectionEvent(Connection.EVENT_HANDOVER_FAILED, null);
+        handoverFrom.onHandoverFailed(android.telecom.Call.Callback.HANDOVER_FAILURE_USER_REJECTED);
+
         // Inform the "to" ConnectionService that handover to it has failed.  This
         // allows the ConnectionService the call was being handed over
         if (handoverTo.getConnectionService() != null) {
@@ -2488,6 +2490,8 @@
             // early on in the handover process, the CS will be unbound and we won't be
             // able to send the call event.
             handoverTo.sendCallEvent(android.telecom.Call.EVENT_HANDOVER_FAILED, null);
+            handoverTo.getConnectionService().handoverFailed(handoverTo,
+                    android.telecom.Call.Callback.HANDOVER_FAILURE_USER_REJECTED);
         }
         handoverTo.markFinishedHandoverStateAndCleanup(HandoverState.HANDOVER_FAILED);
     }
@@ -2496,7 +2500,9 @@
         Call handoverFrom = handoverTo.getHandoverSourceCall();
         Log.i(this, "acceptHandoverTo: from=%s, to=%s", handoverFrom.getId(), handoverTo.getId());
         handoverTo.setHandoverState(HandoverState.HANDOVER_ACCEPTED);
+        handoverTo.onHandoverComplete();
         handoverFrom.setHandoverState(HandoverState.HANDOVER_ACCEPTED);
+        handoverFrom.onHandoverComplete();
 
         Log.addEvent(handoverTo, LogUtils.Events.ACCEPT_HANDOVER, "from=%s, to=%s",
                 handoverFrom.getId(), handoverTo.getId());
@@ -3411,7 +3417,7 @@
         boolean isHandoverToSupported = isHandoverToPhoneAccountSupported(handoverToHandle);
         if (!isHandoverFromSupported || !isHandoverToSupported) {
             handoverFromCall.onHandoverFailed(
-                    android.telecom.Call.Callback.HANDOVER_FAILURE_DEST_NOT_SUPPORTED);
+                    android.telecom.Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED);
             return;
         }
 
@@ -3642,7 +3648,7 @@
                 hasEmergencyCall()) {
             Log.w(this, "acceptHandover: Handover not supported");
             notifyHandoverFailed(call,
-                    android.telecom.Call.Callback.HANDOVER_FAILURE_DEST_NOT_SUPPORTED);
+                    android.telecom.Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED);
             return;
         }
 
@@ -3650,7 +3656,7 @@
         if (phoneAccount == null) {
             Log.w(this, "acceptHandover: Handover not supported. phoneAccount = null");
             notifyHandoverFailed(call,
-                    android.telecom.Call.Callback.HANDOVER_FAILURE_DEST_NOT_SUPPORTED);
+                    android.telecom.Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED);
             return;
         }
         call.setIsSelfManaged(phoneAccount.isSelfManaged());
diff --git a/src/com/android/server/telecom/ConnectionServiceRepository.java b/src/com/android/server/telecom/ConnectionServiceRepository.java
index 4685704..d34ea3c 100644
--- a/src/com/android/server/telecom/ConnectionServiceRepository.java
+++ b/src/com/android/server/telecom/ConnectionServiceRepository.java
@@ -43,7 +43,8 @@
                 @Override
                 public void onUnbind(ConnectionServiceWrapper service) {
                     synchronized (mLock) {
-                        mServiceCache.remove(service.getComponentName());
+                        mServiceCache.remove(Pair.create(service.getComponentName(),
+                                service.getUserHandle()));
                     }
                 }
             };
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 67f3017..bb011bf 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -1602,8 +1602,16 @@
                 @Override
                 public void onSuccess() {
                     Log.d(this, "Adding simService %s", currentSimService.getComponentName());
-                    simServiceComponentNames.add(currentSimService.getComponentName());
-                    simServiceBinders.add(currentSimService.mServiceInterface.asBinder());
+                    if (currentSimService.mServiceInterface == null) {
+                        // The remote ConnectionService died, so do not add it.
+                        // We will still perform maybeComplete() and notify the caller with an empty
+                        // list of sim services via maybeComplete().
+                        Log.w(this, "queryRemoteConnectionServices: simService %s died - Skipping.",
+                                currentSimService.getComponentName());
+                    } else {
+                        simServiceComponentNames.add(currentSimService.getComponentName());
+                        simServiceBinders.add(currentSimService.mServiceInterface.asBinder());
+                    }
                     maybeComplete();
                 }
 
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 39a8185..e8b2b26 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -49,6 +49,18 @@
             255, // Peak
             0}; // pause before repetition
 
+    private static final long[] SIMPLE_VIBRATION_PATTERN = {
+            0, // No delay before starting
+            1000, // How long to vibrate
+            1000, // How long to wait before vibrating again
+    };
+
+    private static final int[] SIMPLE_VIBRATION_AMPLITUDE = {
+            0, // No delay before starting
+            255, // Vibrate full amplitude
+            0, // No amplitude while waiting
+    };
+
     /**
      * Indicates that vibration should be repeated at element 5 in the {@link #PULSE_AMPLITUDE} and
      * {@link #PULSE_PATTERN} arrays.  This means repetition will happen for the main ease-in/peak
@@ -56,6 +68,8 @@
      */
     private static final int REPEAT_VIBRATION_AT = 5;
 
+    private static final int REPEAT_SIMPLE_VIBRATION_AT = 1;
+
     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
             .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
@@ -110,8 +124,13 @@
         mRingtoneFactory = ringtoneFactory;
         mInCallController = inCallController;
 
-        mVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN, PULSE_AMPLITUDE,
-                REPEAT_VIBRATION_AT);
+        if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
+            mVibrationEffect = VibrationEffect.createWaveform(SIMPLE_VIBRATION_PATTERN,
+                    SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT);
+        } else {
+            mVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN, PULSE_AMPLITUDE,
+                    REPEAT_VIBRATION_AT);
+        }
     }
 
     public boolean startRinging(Call foregroundCall, boolean isHfpDeviceAttached) {
diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java
index 47ba295..44ddc24 100644
--- a/src/com/android/server/telecom/ServiceBinder.java
+++ b/src/com/android/server/telecom/ServiceBinder.java
@@ -261,6 +261,10 @@
         mUserHandle = userHandle;
     }
 
+    final UserHandle getUserHandle() {
+        return mUserHandle;
+    }
+
     final void incrementAssociatedCallCount() {
         mAssociatedCallCount++;
         Log.v(this, "Call count increment %d, %s", mAssociatedCallCount,
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index 7d9cf88..e688416 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -59,6 +59,7 @@
 import java.io.File;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
@@ -1036,9 +1037,10 @@
             PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) {
         assertEquals(a.defaultOutgoingAccountHandles.size(),
                 b.defaultOutgoingAccountHandles.size());
-        for (int i = 0; i < a.defaultOutgoingAccountHandles.size(); i++) {
-            assertDefaultPhoneAccountHandleEquals(a.defaultOutgoingAccountHandles.get(i),
-                    b.defaultOutgoingAccountHandles.get(i));
+        for (Map.Entry<UserHandle, DefaultPhoneAccountHandle> e :
+                a.defaultOutgoingAccountHandles.entrySet()) {
+            assertDefaultPhoneAccountHandleEquals(e.getValue(),
+                    b.defaultOutgoingAccountHandles.get(e.getKey()));
         }
         assertEquals(a.accounts.size(), b.accounts.size());
         for (int i = 0; i < a.accounts.size(); i++) {