1 /*
2  * Copyright (C) 2014 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.server.telecom;
18 
19 import android.util.ArrayMap;
20 
21 import com.android.internal.annotations.VisibleForTesting;
22 
23 import java.util.Map;
24 
25 /** Utility to map {@link Call} objects to unique IDs. IDs are generated when a call is added. */
26 @VisibleForTesting
27 public class CallIdMapper {
28     /**
29      * A very basic bidirectional map.
30      */
31     static class BiMap<K, V> {
32         private Map<K, V> mPrimaryMap = new ArrayMap<>();
33         private Map<V, K> mSecondaryMap = new ArrayMap<>();
34 
put(K key, V value)35         public boolean put(K key, V value) {
36             if (key == null || value == null || mPrimaryMap.containsKey(key) ||
37                     mSecondaryMap.containsKey(value)) {
38                 return false;
39             }
40 
41             mPrimaryMap.put(key, value);
42             mSecondaryMap.put(value, key);
43             return true;
44         }
45 
remove(K key)46         public boolean remove(K key) {
47             if (key == null) {
48                 return false;
49             }
50             if (mPrimaryMap.containsKey(key)) {
51                 V value = getValue(key);
52                 mPrimaryMap.remove(key);
53                 mSecondaryMap.remove(value);
54                 return true;
55             }
56             return false;
57         }
58 
removeValue(V value)59         public boolean removeValue(V value) {
60             if (value == null) {
61                 return false;
62             }
63             return remove(getKey(value));
64         }
65 
getValue(K key)66         public V getValue(K key) {
67             return mPrimaryMap.get(key);
68         }
69 
getKey(V value)70         public K getKey(V value) {
71             return mSecondaryMap.get(value);
72         }
73 
clear()74         public void clear() {
75             mPrimaryMap.clear();
76             mSecondaryMap.clear();
77         }
78     }
79 
80     private final BiMap<String, Call> mCalls = new BiMap<>();
81 
replaceCall(Call newCall, Call callToReplace)82     void replaceCall(Call newCall, Call callToReplace) {
83         // Use the old call's ID for the new call.
84         String callId = getCallId(callToReplace);
85         mCalls.put(callId, newCall);
86     }
87 
addCall(Call call, String id)88     void addCall(Call call, String id) {
89         if (call == null) {
90             return;
91         }
92         mCalls.put(id, call);
93     }
94 
addCall(Call call)95     void addCall(Call call) {
96         addCall(call, call.getId());
97     }
98 
removeCall(Call call)99     void removeCall(Call call) {
100         if (call == null) {
101             return;
102         }
103         mCalls.removeValue(call);
104     }
105 
removeCall(String callId)106     void removeCall(String callId) {
107         mCalls.remove(callId);
108     }
109 
getCallId(Call call)110     String getCallId(Call call) {
111         if (call == null || mCalls.getKey(call) == null) {
112             return null;
113         }
114         return call.getId();
115     }
116 
getCall(Object objId)117     Call getCall(Object objId) {
118         String callId = null;
119         if (objId instanceof String) {
120             callId = (String) objId;
121         }
122 
123         return mCalls.getValue(callId);
124     }
125 
clear()126     void clear() {
127         mCalls.clear();
128     }
129 }
130