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