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    private final BiMap<String, Call> mCalls = new BiMap<>();
81
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
88    void addCall(Call call, String id) {
89        if (call == null) {
90            return;
91        }
92        mCalls.put(id, call);
93    }
94
95    void addCall(Call call) {
96        addCall(call, call.getId());
97    }
98
99    void removeCall(Call call) {
100        if (call == null) {
101            return;
102        }
103        mCalls.removeValue(call);
104    }
105
106    void removeCall(String callId) {
107        mCalls.remove(callId);
108    }
109
110    String getCallId(Call call) {
111        if (call == null || mCalls.getKey(call) == null) {
112            return null;
113        }
114        return call.getId();
115    }
116
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
126    void clear() {
127        mCalls.clear();
128    }
129}
130