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