blob: c380d6b3e30f09a7b335028e573b65083ed9ded1 [file] [log] [blame]
Amit Mahajan82f245f2019-09-10 13:19:05 -07001/*
2 * Copyright (C) 2008 Esmertec AG.
3 * Copyright (C) 2008 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.google.android.mms.util;
19
Artur Satayev53ada2a2019-12-10 17:47:56 +000020import android.compat.annotation.UnsupportedAppUsage;
Amit Mahajan82f245f2019-09-10 13:19:05 -070021import android.content.ContentUris;
22import android.content.UriMatcher;
23import android.net.Uri;
24import android.provider.Telephony.Mms;
25import android.util.Log;
26
Amit Mahajan82f245f2019-09-10 13:19:05 -070027import java.util.HashMap;
28import java.util.HashSet;
29
30public final class PduCache extends AbstractCache<Uri, PduCacheEntry> {
31 private static final String TAG = "PduCache";
32 private static final boolean DEBUG = false;
33 private static final boolean LOCAL_LOGV = false;
34
35 private static final int MMS_ALL = 0;
36 private static final int MMS_ALL_ID = 1;
37 private static final int MMS_INBOX = 2;
38 private static final int MMS_INBOX_ID = 3;
39 private static final int MMS_SENT = 4;
40 private static final int MMS_SENT_ID = 5;
41 private static final int MMS_DRAFTS = 6;
42 private static final int MMS_DRAFTS_ID = 7;
43 private static final int MMS_OUTBOX = 8;
44 private static final int MMS_OUTBOX_ID = 9;
45 private static final int MMS_CONVERSATION = 10;
46 private static final int MMS_CONVERSATION_ID = 11;
47
48 private static final UriMatcher URI_MATCHER;
49 private static final HashMap<Integer, Integer> MATCH_TO_MSGBOX_ID_MAP;
50
51 private static PduCache sInstance;
52
53 static {
54 URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
55 URI_MATCHER.addURI("mms", null, MMS_ALL);
56 URI_MATCHER.addURI("mms", "#", MMS_ALL_ID);
57 URI_MATCHER.addURI("mms", "inbox", MMS_INBOX);
58 URI_MATCHER.addURI("mms", "inbox/#", MMS_INBOX_ID);
59 URI_MATCHER.addURI("mms", "sent", MMS_SENT);
60 URI_MATCHER.addURI("mms", "sent/#", MMS_SENT_ID);
61 URI_MATCHER.addURI("mms", "drafts", MMS_DRAFTS);
62 URI_MATCHER.addURI("mms", "drafts/#", MMS_DRAFTS_ID);
63 URI_MATCHER.addURI("mms", "outbox", MMS_OUTBOX);
64 URI_MATCHER.addURI("mms", "outbox/#", MMS_OUTBOX_ID);
65 URI_MATCHER.addURI("mms-sms", "conversations", MMS_CONVERSATION);
66 URI_MATCHER.addURI("mms-sms", "conversations/#", MMS_CONVERSATION_ID);
67
68 MATCH_TO_MSGBOX_ID_MAP = new HashMap<Integer, Integer>();
69 MATCH_TO_MSGBOX_ID_MAP.put(MMS_INBOX, Mms.MESSAGE_BOX_INBOX);
70 MATCH_TO_MSGBOX_ID_MAP.put(MMS_SENT, Mms.MESSAGE_BOX_SENT);
71 MATCH_TO_MSGBOX_ID_MAP.put(MMS_DRAFTS, Mms.MESSAGE_BOX_DRAFTS);
72 MATCH_TO_MSGBOX_ID_MAP.put(MMS_OUTBOX, Mms.MESSAGE_BOX_OUTBOX);
73 }
74
75 private final HashMap<Integer, HashSet<Uri>> mMessageBoxes;
76 private final HashMap<Long, HashSet<Uri>> mThreads;
77 private final HashSet<Uri> mUpdating;
78
79 @UnsupportedAppUsage
80 private PduCache() {
81 mMessageBoxes = new HashMap<Integer, HashSet<Uri>>();
82 mThreads = new HashMap<Long, HashSet<Uri>>();
83 mUpdating = new HashSet<Uri>();
84 }
85
86 @UnsupportedAppUsage
87 synchronized public static final PduCache getInstance() {
88 if (sInstance == null) {
89 if (LOCAL_LOGV) {
90 Log.v(TAG, "Constructing new PduCache instance.");
91 }
92 sInstance = new PduCache();
93 }
94 return sInstance;
95 }
96
97 @Override
98 synchronized public boolean put(Uri uri, PduCacheEntry entry) {
99 int msgBoxId = entry.getMessageBox();
100 HashSet<Uri> msgBox = mMessageBoxes.get(msgBoxId);
101 if (msgBox == null) {
102 msgBox = new HashSet<Uri>();
103 mMessageBoxes.put(msgBoxId, msgBox);
104 }
105
106 long threadId = entry.getThreadId();
107 HashSet<Uri> thread = mThreads.get(threadId);
108 if (thread == null) {
109 thread = new HashSet<Uri>();
110 mThreads.put(threadId, thread);
111 }
112
113 Uri finalKey = normalizeKey(uri);
114 boolean result = super.put(finalKey, entry);
115 if (result) {
116 msgBox.add(finalKey);
117 thread.add(finalKey);
118 }
119 setUpdating(uri, false);
120 return result;
121 }
122
123 synchronized public void setUpdating(Uri uri, boolean updating) {
124 if (updating) {
125 mUpdating.add(uri);
126 } else {
127 mUpdating.remove(uri);
128 }
129 }
130
131 @UnsupportedAppUsage
132 synchronized public boolean isUpdating(Uri uri) {
133 return mUpdating.contains(uri);
134 }
135
136 @Override
137 @UnsupportedAppUsage
138 synchronized public PduCacheEntry purge(Uri uri) {
139 int match = URI_MATCHER.match(uri);
140 switch (match) {
141 case MMS_ALL_ID:
142 return purgeSingleEntry(uri);
143 case MMS_INBOX_ID:
144 case MMS_SENT_ID:
145 case MMS_DRAFTS_ID:
146 case MMS_OUTBOX_ID:
147 String msgId = uri.getLastPathSegment();
148 return purgeSingleEntry(Uri.withAppendedPath(Mms.CONTENT_URI, msgId));
149 // Implicit batch of purge, return null.
150 case MMS_ALL:
151 case MMS_CONVERSATION:
152 purgeAll();
153 return null;
154 case MMS_INBOX:
155 case MMS_SENT:
156 case MMS_DRAFTS:
157 case MMS_OUTBOX:
158 purgeByMessageBox(MATCH_TO_MSGBOX_ID_MAP.get(match));
159 return null;
160 case MMS_CONVERSATION_ID:
161 purgeByThreadId(ContentUris.parseId(uri));
162 return null;
163 default:
164 return null;
165 }
166 }
167
168 private PduCacheEntry purgeSingleEntry(Uri key) {
169 mUpdating.remove(key);
170 PduCacheEntry entry = super.purge(key);
171 if (entry != null) {
172 removeFromThreads(key, entry);
173 removeFromMessageBoxes(key, entry);
174 return entry;
175 }
176 return null;
177 }
178
179 @UnsupportedAppUsage
180 @Override
181 synchronized public void purgeAll() {
182 super.purgeAll();
183
184 mMessageBoxes.clear();
185 mThreads.clear();
186 mUpdating.clear();
187 }
188
189 /**
190 * @param uri The Uri to be normalized.
191 * @return Uri The normalized key of cached entry.
192 */
193 private Uri normalizeKey(Uri uri) {
194 int match = URI_MATCHER.match(uri);
195 Uri normalizedKey = null;
196
197 switch (match) {
198 case MMS_ALL_ID:
199 normalizedKey = uri;
200 break;
201 case MMS_INBOX_ID:
202 case MMS_SENT_ID:
203 case MMS_DRAFTS_ID:
204 case MMS_OUTBOX_ID:
205 String msgId = uri.getLastPathSegment();
206 normalizedKey = Uri.withAppendedPath(Mms.CONTENT_URI, msgId);
207 break;
208 default:
209 return null;
210 }
211
212 if (LOCAL_LOGV) {
213 Log.v(TAG, uri + " -> " + normalizedKey);
214 }
215 return normalizedKey;
216 }
217
218 private void purgeByMessageBox(Integer msgBoxId) {
219 if (LOCAL_LOGV) {
220 Log.v(TAG, "Purge cache in message box: " + msgBoxId);
221 }
222
223 if (msgBoxId != null) {
224 HashSet<Uri> msgBox = mMessageBoxes.remove(msgBoxId);
225 if (msgBox != null) {
226 for (Uri key : msgBox) {
227 mUpdating.remove(key);
228 PduCacheEntry entry = super.purge(key);
229 if (entry != null) {
230 removeFromThreads(key, entry);
231 }
232 }
233 }
234 }
235 }
236
237 private void removeFromThreads(Uri key, PduCacheEntry entry) {
238 HashSet<Uri> thread = mThreads.get(entry.getThreadId());
239 if (thread != null) {
240 thread.remove(key);
241 }
242 }
243
244 private void purgeByThreadId(long threadId) {
245 if (LOCAL_LOGV) {
246 Log.v(TAG, "Purge cache in thread: " + threadId);
247 }
248
249 HashSet<Uri> thread = mThreads.remove(threadId);
250 if (thread != null) {
251 for (Uri key : thread) {
252 mUpdating.remove(key);
253 PduCacheEntry entry = super.purge(key);
254 if (entry != null) {
255 removeFromMessageBoxes(key, entry);
256 }
257 }
258 }
259 }
260
261 private void removeFromMessageBoxes(Uri key, PduCacheEntry entry) {
262 HashSet<Uri> msgBox = mThreads.get(Long.valueOf(entry.getMessageBox()));
263 if (msgBox != null) {
264 msgBox.remove(key);
265 }
266 }
267}