• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.impl.MappedButtonConfig.MappingInfo;
22 import com.android.incallui.incall.protocol.InCallButtonIds;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Set;
27 import javax.annotation.concurrent.Immutable;
28 
29 /**
30  * Determines where logical buttons should be placed in the {@link InCallFragment} based on the
31  * provided mapping.
32  *
33  * <p>The button placement returned by a call to {@link #getButtonPlacement(int, Set)} is created as
34  * follows: one button is placed at each UI slot, using the provided mapping to resolve conflicts.
35  * Any allowed buttons that were not chosen for their desired slot are filled in at the end of the
36  * list until it becomes the proper size.
37  */
38 @Immutable
39 final class ButtonChooser {
40 
41   private final MappedButtonConfig config;
42 
ButtonChooser(@onNull MappedButtonConfig config)43   public ButtonChooser(@NonNull MappedButtonConfig config) {
44     this.config = Assert.isNotNull(config);
45   }
46 
47   /**
48    * Returns the buttons that should be shown in the {@link InCallFragment}, ordered appropriately.
49    *
50    * @param numUiButtons the number of ui buttons available.
51    * @param allowedButtons the {@link InCallButtonIds} that can be shown.
52    * @param disabledButtons the {@link InCallButtonIds} that can be shown but in disabled stats.
53    * @return an immutable list whose size is at most {@code numUiButtons}, containing the buttons to
54    *     show.
55    */
56   @NonNull
getButtonPlacement( int numUiButtons, @NonNull Set<Integer> allowedButtons, @NonNull Set<Integer> disabledButtons)57   public List<Integer> getButtonPlacement(
58       int numUiButtons,
59       @NonNull Set<Integer> allowedButtons,
60       @NonNull Set<Integer> disabledButtons) {
61     Assert.isNotNull(allowedButtons);
62     Assert.checkArgument(numUiButtons >= 0);
63 
64     if (numUiButtons == 0 || allowedButtons.isEmpty()) {
65       return Collections.emptyList();
66     }
67 
68     List<Integer> placedButtons = new ArrayList<>();
69     List<Integer> conflicts = new ArrayList<>();
70     placeButtonsInSlots(numUiButtons, allowedButtons, placedButtons, conflicts);
71     placeConflictsInOpenSlots(
72         numUiButtons, allowedButtons, disabledButtons, placedButtons, conflicts);
73     return Collections.unmodifiableList(placedButtons);
74   }
75 
placeButtonsInSlots( int numUiButtons, @NonNull Set<Integer> allowedButtons, @NonNull List<Integer> placedButtons, @NonNull List<Integer> conflicts)76   private void placeButtonsInSlots(
77       int numUiButtons,
78       @NonNull Set<Integer> allowedButtons,
79       @NonNull List<Integer> placedButtons,
80       @NonNull List<Integer> conflicts) {
81     List<Integer> configuredSlots = config.getOrderedMappedSlots();
82     for (int i = 0; i < configuredSlots.size() && placedButtons.size() < numUiButtons; ++i) {
83       int slotNumber = configuredSlots.get(i);
84       List<Integer> potentialButtons = config.getButtonsForSlot(slotNumber);
85       Collections.sort(potentialButtons, config.getSlotComparator());
86       for (int j = 0; j < potentialButtons.size(); ++j) {
87         if (allowedButtons.contains(potentialButtons.get(j))) {
88           placedButtons.add(potentialButtons.get(j));
89           conflicts.addAll(potentialButtons.subList(j + 1, potentialButtons.size()));
90           break;
91         }
92       }
93     }
94   }
95 
placeConflictsInOpenSlots( int numUiButtons, @NonNull Set<Integer> allowedButtons, @NonNull Set<Integer> disabledButtons, @NonNull List<Integer> placedButtons, @NonNull List<Integer> conflicts)96   private void placeConflictsInOpenSlots(
97       int numUiButtons,
98       @NonNull Set<Integer> allowedButtons,
99       @NonNull Set<Integer> disabledButtons,
100       @NonNull List<Integer> placedButtons,
101       @NonNull List<Integer> conflicts) {
102     Collections.sort(conflicts, config.getConflictComparator());
103     for (Integer conflict : conflicts) {
104       if (placedButtons.size() >= numUiButtons) {
105         return;
106       }
107 
108       // If the conflict button is allowed but disabled, don't place it since it probably will
109       // move when it's enabled.
110       if (!allowedButtons.contains(conflict) || disabledButtons.contains(conflict)) {
111         continue;
112       }
113 
114       if (isMutuallyExclusiveButtonAvailable(
115           config.lookupMappingInfo(conflict).getMutuallyExclusiveButton(), allowedButtons)) {
116         continue;
117       }
118       placedButtons.add(conflict);
119     }
120   }
121 
isMutuallyExclusiveButtonAvailable( int mutuallyExclusiveButton, @NonNull Set<Integer> allowedButtons)122   private boolean isMutuallyExclusiveButtonAvailable(
123       int mutuallyExclusiveButton, @NonNull Set<Integer> allowedButtons) {
124     if (mutuallyExclusiveButton == MappingInfo.NO_MUTUALLY_EXCLUSIVE_BUTTON_SET) {
125       return false;
126     }
127     if (allowedButtons.contains(mutuallyExclusiveButton)) {
128       return true;
129     }
130     return false;
131   }
132 }
133