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
17package com.android.server.telecom;
18
19import android.util.ArrayMap;
20
21import com.android.internal.annotations.VisibleForTesting;
22
23import java.util.Map;
24
25/** Utility to map {@link Call} objects to unique IDs. IDs are generated when a call is added. */
26@VisibleForTesting
27public 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
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
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
59        public boolean removeValue(V value) {
60            if (value == null) {
61                return false;
62            }
63            return remove(getKey(value));
64        }
65
66        public V getValue(K key) {
67            return mPrimaryMap.get(key);
68        }
69
70        public K getKey(V value) {
71            return mSecondaryMap.get(value);
72        }
73
74        public void clear() {
75            mPrimaryMap.clear();
76            mSecondaryMap.clear();
77        }
78    }
79
80    public interface ICallInfo {
81        String getCallId(Call call);
82    }
83
84    private final BiMap<String, Call> mCalls = new BiMap<>();
85    private ICallInfo mCallInfo;
86
87    public CallIdMapper(ICallInfo callInfo) {
88        mCallInfo = callInfo;
89    }
90
91    void replaceCall(Call newCall, Call callToReplace) {
92        // Use the old call's ID for the new call.
93        String callId = getCallId(callToReplace);
94        mCalls.put(callId, newCall);
95    }
96
97    void addCall(Call call, String id) {
98        if (call == null) {
99            return;
100        }
101        mCalls.put(id, call);
102    }
103
104    void addCall(Call call) {
105        addCall(call, mCallInfo.getCallId(call));
106    }
107
108    void removeCall(Call call) {
109        if (call == null) {
110            return;
111        }
112        mCalls.removeValue(call);
113    }
114
115    void removeCall(String callId) {
116        mCalls.remove(callId);
117    }
118
119    String getCallId(Call call) {
120        if (call == null || mCalls.getKey(call) == null) {
121            return null;
122        }
123        return mCallInfo.getCallId(call);
124    }
125
126    Call getCall(Object objId) {
127        String callId = null;
128        if (objId instanceof String) {
129            callId = (String) objId;
130        }
131
132        return mCalls.getValue(callId);
133    }
134
135    void clear() {
136        mCalls.clear();
137    }
138}
139