blob: 94e38946f6320056354a12f10dfdbf690fc0fd1a [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
20import android.content.ContentUris;
21import android.content.UriMatcher;
22import android.net.Uri;
23import android.provider.Telephony.Mms;
24import android.util.Log;
25
26import dalvik.annotation.compat.UnsupportedAppUsage;
27
28import java.util.HashMap;
29import java.util.HashSet;
30
31public final class PduCache extends AbstractCache<Uri, PduCacheEntry> {
32 private static final String TAG = "PduCache";
33 private static final boolean DEBUG = false;
34 private static final boolean LOCAL_LOGV = false;
35
36 private static final int MMS_ALL = 0;
37 private static final int MMS_ALL_ID = 1;
38 private static final int MMS_INBOX = 2;
39 private static final int MMS_INBOX_ID = 3;
40 private static final int MMS_SENT = 4;
41 private static final int MMS_SENT_ID = 5;
42 private static final int MMS_DRAFTS = 6;
43 private static final int MMS_DRAFTS_ID = 7;
44 private static final int MMS_OUTBOX = 8;
45 private static final int MMS_OUTBOX_ID = 9;
46 private static final int MMS_CONVERSATION = 10;
47 private static final int MMS_CONVERSATION_ID = 11;
48
49 private static final UriMatcher URI_MATCHER;
50 private static final HashMap<Integer, Integer> MATCH_TO_MSGBOX_ID_MAP;
51
52 private static PduCache sInstance;
53
54 static {
55 URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
56 URI_MATCHER.addURI("mms", null, MMS_ALL);
57 URI_MATCHER.addURI("mms", "#", MMS_ALL_ID);
58 URI_MATCHER.addURI("mms", "inbox", MMS_INBOX);
59 URI_MATCHER.addURI("mms", "inbox/#", MMS_INBOX_ID);
60 URI_MATCHER.addURI("mms", "sent", MMS_SENT);
61 URI_MATCHER.addURI("mms", "sent/#", MMS_SENT_ID);
62 URI_MATCHER.addURI("mms", "drafts", MMS_DRAFTS);
63 URI_MATCHER.addURI("mms", "drafts/#", MMS_DRAFTS_ID);
64 URI_MATCHER.addURI("mms", "outbox", MMS_OUTBOX);
65 URI_MATCHER.addURI("mms", "outbox/#", MMS_OUTBOX_ID);
66 URI_MATCHER.addURI("mms-sms", "conversations", MMS_CONVERSATION);
67 URI_MATCHER.addURI("mms-sms", "conversations/#", MMS_CONVERSATION_ID);
68
69 MATCH_TO_MSGBOX_ID_MAP = new HashMap<Integer, Integer>();
70 MATCH_TO_MSGBOX_ID_MAP.put(MMS_INBOX, Mms.MESSAGE_BOX_INBOX);
71 MATCH_TO_MSGBOX_ID_MAP.put(MMS_SENT, Mms.MESSAGE_BOX_SENT);
72 MATCH_TO_MSGBOX_ID_MAP.put(MMS_DRAFTS, Mms.MESSAGE_BOX_DRAFTS);
73 MATCH_TO_MSGBOX_ID_MAP.put(MMS_OUTBOX, Mms.MESSAGE_BOX_OUTBOX);
74 }
75
76 private final HashMap<Integer, HashSet<Uri>> mMessageBoxes;
77 private final HashMap<Long, HashSet<Uri>> mThreads;
78 private final HashSet<Uri> mUpdating;
79
80 @UnsupportedAppUsage
81 private PduCache() {
82 mMessageBoxes = new HashMap<Integer, HashSet<Uri>>();
83 mThreads = new HashMap<Long, HashSet<Uri>>();
84 mUpdating = new HashSet<Uri>();
85 }
86
87 @UnsupportedAppUsage
88 synchronized public static final PduCache getInstance() {
89 if (sInstance == null) {
90 if (LOCAL_LOGV) {
91 Log.v(TAG, "Constructing new PduCache instance.");
92 }
93 sInstance = new PduCache();
94 }
95 return sInstance;
96 }
97
98 @Override
99 synchronized public boolean put(Uri uri, PduCacheEntry entry) {
100 int msgBoxId = entry.getMessageBox();
101 HashSet<Uri> msgBox = mMessageBoxes.get(msgBoxId);
102 if (msgBox == null) {
103 msgBox = new HashSet<Uri>();
104 mMessageBoxes.put(msgBoxId, msgBox);
105 }
106
107 long threadId = entry.getThreadId();
108 HashSet<Uri> thread = mThreads.get(threadId);
109 if (thread == null) {
110 thread = new HashSet<Uri>();
111 mThreads.put(threadId, thread);
112 }
113
114 Uri finalKey = normalizeKey(uri);
115 boolean result = super.put(finalKey, entry);
116 if (result) {
117 msgBox.add(finalKey);
118 thread.add(finalKey);
119 }
120 setUpdating(uri, false);
121 return result;
122 }
123
124 synchronized public void setUpdating(Uri uri, boolean updating) {
125 if (updating) {
126 mUpdating.add(uri);
127 } else {
128 mUpdating.remove(uri);
129 }
130 }
131
132 @UnsupportedAppUsage
133 synchronized public boolean isUpdating(Uri uri) {
134 return mUpdating.contains(uri);
135 }
136
137 @Override
138 @UnsupportedAppUsage
139 synchronized public PduCacheEntry purge(Uri uri) {
140 int match = URI_MATCHER.match(uri);
141 switch (match) {
142 case MMS_ALL_ID:
143 return purgeSingleEntry(uri);
144 case MMS_INBOX_ID:
145 case MMS_SENT_ID:
146 case MMS_DRAFTS_ID:
147 case MMS_OUTBOX_ID:
148 String msgId = uri.getLastPathSegment();
149 return purgeSingleEntry(Uri.withAppendedPath(Mms.CONTENT_URI, msgId));
150 // Implicit batch of purge, return null.
151 case MMS_ALL:
152 case MMS_CONVERSATION:
153 purgeAll();
154 return null;
155 case MMS_INBOX:
156 case MMS_SENT:
157 case MMS_DRAFTS:
158 case MMS_OUTBOX:
159 purgeByMessageBox(MATCH_TO_MSGBOX_ID_MAP.get(match));
160 return null;
161 case MMS_CONVERSATION_ID:
162 purgeByThreadId(ContentUris.parseId(uri));
163 return null;
164 default:
165 return null;
166 }
167 }
168
169 private PduCacheEntry purgeSingleEntry(Uri key) {
170 mUpdating.remove(key);
171 PduCacheEntry entry = super.purge(key);
172 if (entry != null) {
173 removeFromThreads(key, entry);
174 removeFromMessageBoxes(key, entry);
175 return entry;
176 }
177 return null;
178 }
179
180 @UnsupportedAppUsage
181 @Override
182 synchronized public void purgeAll() {
183 super.purgeAll();
184
185 mMessageBoxes.clear();
186 mThreads.clear();
187 mUpdating.clear();
188 }
189
190 /**
191 * @param uri The Uri to be normalized.
192 * @return Uri The normalized key of cached entry.
193 */
194 private Uri normalizeKey(Uri uri) {
195 int match = URI_MATCHER.match(uri);
196 Uri normalizedKey = null;
197
198 switch (match) {
199 case MMS_ALL_ID:
200 normalizedKey = uri;
201 break;
202 case MMS_INBOX_ID:
203 case MMS_SENT_ID:
204 case MMS_DRAFTS_ID:
205 case MMS_OUTBOX_ID:
206 String msgId = uri.getLastPathSegment();
207 normalizedKey = Uri.withAppendedPath(Mms.CONTENT_URI, msgId);
208 break;
209 default:
210 return null;
211 }
212
213 if (LOCAL_LOGV) {
214 Log.v(TAG, uri + " -> " + normalizedKey);
215 }
216 return normalizedKey;
217 }
218
219 private void purgeByMessageBox(Integer msgBoxId) {
220 if (LOCAL_LOGV) {
221 Log.v(TAG, "Purge cache in message box: " + msgBoxId);
222 }
223
224 if (msgBoxId != null) {
225 HashSet<Uri> msgBox = mMessageBoxes.remove(msgBoxId);
226 if (msgBox != null) {
227 for (Uri key : msgBox) {
228 mUpdating.remove(key);
229 PduCacheEntry entry = super.purge(key);
230 if (entry != null) {
231 removeFromThreads(key, entry);
232 }
233 }
234 }
235 }
236 }
237
238 private void removeFromThreads(Uri key, PduCacheEntry entry) {
239 HashSet<Uri> thread = mThreads.get(entry.getThreadId());
240 if (thread != null) {
241 thread.remove(key);
242 }
243 }
244
245 private void purgeByThreadId(long threadId) {
246 if (LOCAL_LOGV) {
247 Log.v(TAG, "Purge cache in thread: " + threadId);
248 }
249
250 HashSet<Uri> thread = mThreads.remove(threadId);
251 if (thread != null) {
252 for (Uri key : thread) {
253 mUpdating.remove(key);
254 PduCacheEntry entry = super.purge(key);
255 if (entry != null) {
256 removeFromMessageBoxes(key, entry);
257 }
258 }
259 }
260 }
261
262 private void removeFromMessageBoxes(Uri key, PduCacheEntry entry) {
263 HashSet<Uri> msgBox = mThreads.get(Long.valueOf(entry.getMessageBox()));
264 if (msgBox != null) {
265 msgBox.remove(key);
266 }
267 }
268}