1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.incallui.incall.impl; 18 19 import android.support.annotation.NonNull; 20 import com.android.dialer.common.Assert; 21 import com.android.incallui.incall.protocol.InCallButtonIds; 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.List; 25 import java.util.Set; 26 import javax.annotation.concurrent.Immutable; 27 28 /** 29 * Determines where logical buttons should be placed in the {@link InCallFragment} based on the 30 * provided mapping. 31 * 32 * <p>The button placement returned by a call to {@link #getButtonPlacement(int, Set)} is created as 33 * follows: one button is placed at each UI slot, using the provided mapping to resolve conflicts. 34 * Any allowed buttons that were not chosen for their desired slot are filled in at the end of the 35 * list until it becomes the proper size. 36 */ 37 @Immutable 38 final class ButtonChooser { 39 40 private final MappedButtonConfig config; 41 ButtonChooser(@onNull MappedButtonConfig config)42 public ButtonChooser(@NonNull MappedButtonConfig config) { 43 this.config = Assert.isNotNull(config); 44 } 45 46 /** 47 * Returns the buttons that should be shown in the {@link InCallFragment}, ordered appropriately. 48 * 49 * @param numUiButtons the number of ui buttons available. 50 * @param allowedButtons the {@link InCallButtonIds} that can be shown. 51 * @param disabledButtons the {@link InCallButtonIds} that can be shown but in disabled stats. 52 * @return an immutable list whose size is at most {@code numUiButtons}, containing the buttons to 53 * show. 54 */ 55 @NonNull getButtonPlacement( int numUiButtons, @NonNull Set<Integer> allowedButtons, @NonNull Set<Integer> disabledButtons)56 public List<Integer> getButtonPlacement( 57 int numUiButtons, 58 @NonNull Set<Integer> allowedButtons, 59 @NonNull Set<Integer> disabledButtons) { 60 Assert.isNotNull(allowedButtons); 61 Assert.checkArgument(numUiButtons >= 0); 62 63 if (numUiButtons == 0 || allowedButtons.isEmpty()) { 64 return Collections.emptyList(); 65 } 66 67 List<Integer> placedButtons = new ArrayList<>(); 68 List<Integer> conflicts = new ArrayList<>(); 69 placeButtonsInSlots(numUiButtons, allowedButtons, placedButtons, conflicts); 70 placeConflictsInOpenSlots( 71 numUiButtons, allowedButtons, disabledButtons, placedButtons, conflicts); 72 return Collections.unmodifiableList(placedButtons); 73 } 74 placeButtonsInSlots( int numUiButtons, @NonNull Set<Integer> allowedButtons, @NonNull List<Integer> placedButtons, @NonNull List<Integer> conflicts)75 private void placeButtonsInSlots( 76 int numUiButtons, 77 @NonNull Set<Integer> allowedButtons, 78 @NonNull List<Integer> placedButtons, 79 @NonNull List<Integer> conflicts) { 80 List<Integer> configuredSlots = config.getOrderedMappedSlots(); 81 for (int i = 0; i < configuredSlots.size() && placedButtons.size() < numUiButtons; ++i) { 82 int slotNumber = configuredSlots.get(i); 83 List<Integer> potentialButtons = config.getButtonsForSlot(slotNumber); 84 Collections.sort(potentialButtons, config.getSlotComparator()); 85 for (int j = 0; j < potentialButtons.size(); ++j) { 86 if (allowedButtons.contains(potentialButtons.get(j))) { 87 placedButtons.add(potentialButtons.get(j)); 88 conflicts.addAll(potentialButtons.subList(j + 1, potentialButtons.size())); 89 break; 90 } 91 } 92 } 93 } 94 placeConflictsInOpenSlots( int numUiButtons, @NonNull Set<Integer> allowedButtons, @NonNull Set<Integer> disabledButtons, @NonNull List<Integer> placedButtons, @NonNull List<Integer> conflicts)95 private void placeConflictsInOpenSlots( 96 int numUiButtons, 97 @NonNull Set<Integer> allowedButtons, 98 @NonNull Set<Integer> disabledButtons, 99 @NonNull List<Integer> placedButtons, 100 @NonNull List<Integer> conflicts) { 101 Collections.sort(conflicts, config.getConflictComparator()); 102 for (Integer conflict : conflicts) { 103 if (placedButtons.size() >= numUiButtons) { 104 return; 105 } 106 // If the conflict button is allowed but disabled, don't place it since it probably will 107 // move when it's enabled. 108 if (!allowedButtons.contains(conflict) || disabledButtons.contains(conflict)) { 109 continue; 110 } 111 placedButtons.add(conflict); 112 } 113 } 114 } 115