Fix buttom mapping issue for wifi handoff.

Introduce the concept of a "mutually exclusive button".

Buttons that conflict with a "mutually exclusive button" that
is eligible to be placed, will never be placed.

Bug: 37275934
Test: unit tests.
PiperOrigin-RevId: 164210228
Change-Id: I64af6065c89d143a331ea226f9a6cb1004b5a155
diff --git a/java/com/android/incallui/incall/impl/ButtonChooser.java b/java/com/android/incallui/incall/impl/ButtonChooser.java
index 55b82f0..095a8be 100644
--- a/java/com/android/incallui/incall/impl/ButtonChooser.java
+++ b/java/com/android/incallui/incall/impl/ButtonChooser.java
@@ -18,6 +18,7 @@
 
 import android.support.annotation.NonNull;
 import com.android.dialer.common.Assert;
+import com.android.incallui.incall.impl.MappedButtonConfig.MappingInfo;
 import com.android.incallui.incall.protocol.InCallButtonIds;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -103,12 +104,29 @@
       if (placedButtons.size() >= numUiButtons) {
         return;
       }
+
       // If the conflict button is allowed but disabled, don't place it since it probably will
       // move when it's enabled.
       if (!allowedButtons.contains(conflict) || disabledButtons.contains(conflict)) {
         continue;
       }
+
+      if (isMutuallyExclusiveButtonAvailable(
+          config.lookupMappingInfo(conflict).getMutuallyExclusiveButton(), allowedButtons)) {
+        continue;
+      }
       placedButtons.add(conflict);
     }
   }
+
+  private boolean isMutuallyExclusiveButtonAvailable(
+      int mutuallyExclusiveButton, @NonNull Set<Integer> allowedButtons) {
+    if (mutuallyExclusiveButton == MappingInfo.NO_MUTUALLY_EXCLUSIVE_BUTTON_SET) {
+      return false;
+    }
+    if (allowedButtons.contains(mutuallyExclusiveButton)) {
+      return true;
+    }
+    return false;
+  }
 }
diff --git a/java/com/android/incallui/incall/impl/ButtonChooserFactory.java b/java/com/android/incallui/incall/impl/ButtonChooserFactory.java
index 99364e2..0f4a95d 100644
--- a/java/com/android/incallui/incall/impl/ButtonChooserFactory.java
+++ b/java/com/android/incallui/incall/impl/ButtonChooserFactory.java
@@ -74,6 +74,12 @@
     mapping.put(
         InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO, MappingInfo.builder(4).setSlotOrder(10).build());
     mapping.put(InCallButtonIds.BUTTON_SWAP, MappingInfo.builder(5).setSlotOrder(0).build());
+    mapping.put(
+        InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY,
+        MappingInfo.builder(5)
+            .setSlotOrder(Integer.MAX_VALUE)
+            .setMutuallyExclusiveButton(InCallButtonIds.BUTTON_SWAP)
+            .build());
 
     return new ButtonChooser(new MappedButtonConfig(mapping));
   }
diff --git a/java/com/android/incallui/incall/impl/MappedButtonConfig.java b/java/com/android/incallui/incall/impl/MappedButtonConfig.java
index 7229837..67c4137 100644
--- a/java/com/android/incallui/incall/impl/MappedButtonConfig.java
+++ b/java/com/android/incallui/incall/impl/MappedButtonConfig.java
@@ -141,7 +141,7 @@
   }
 
   @NonNull
-  private MappingInfo lookupMappingInfo(@InCallButtonIds int button) {
+  public MappingInfo lookupMappingInfo(@InCallButtonIds int button) {
     MappingInfo info = mapping.get(button);
     if (info == null) {
       throw new IllegalArgumentException(
@@ -154,6 +154,8 @@
   @AutoValue
   abstract static class MappingInfo {
 
+    public static final int NO_MUTUALLY_EXCLUSIVE_BUTTON_SET = -1;
+
     /** The Ui slot into which a given button desires to be placed. */
     public abstract int getSlot();
 
@@ -171,11 +173,20 @@
      */
     public abstract int getConflictOrder();
 
+    /**
+     * Returns an integer representing a button for which the given button conflicts. Defaults to
+     * {@link NO_MUTUALLY_EXCLUSIVE_BUTTON_SET}.
+     *
+     * <p>If the mutually exclusive button is chosen, the associated button should never be chosen.
+     */
+    public abstract @InCallButtonIds int getMutuallyExclusiveButton();
+
     static Builder builder(int slot) {
       return new AutoValue_MappedButtonConfig_MappingInfo.Builder()
           .setSlot(slot)
           .setSlotOrder(Integer.MAX_VALUE)
-          .setConflictOrder(Integer.MAX_VALUE);
+          .setConflictOrder(Integer.MAX_VALUE)
+          .setMutuallyExclusiveButton(NO_MUTUALLY_EXCLUSIVE_BUTTON_SET);
     }
 
     /** Class used to build instances of {@link MappingInfo}. */
@@ -187,6 +198,8 @@
 
       public abstract Builder setConflictOrder(int conflictOrder);
 
+      public abstract Builder setMutuallyExclusiveButton(@InCallButtonIds int button);
+
       public abstract MappingInfo build();
     }
   }