"Rollback" mimetype cache

Bug 6239243

Change-Id: Icf473e5178a76fda66b33fc11875f00d87b36c16
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index 32928ba..a476ee7 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -700,12 +700,16 @@
     }
 
     /** In-memory cache of previously found MIME-type mappings */
-    // TODO Use ConcurrentHashMap?
     private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
-    /** In-memory cache of previously found package name mappings */
-    // TODO Use ConcurrentHashMap?
+
+    /** TODO Remove it */
     private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
 
+    /**
+     * The last known maximum mimetype ID when the current transaction started.  Used to
+     * "Rollback" {@link #mMimetypeCache}.
+     */
+    private long mMaxMimeTypeIdAtTransactionStart;
     private long mMimeTypeIdEmail;
     private long mMimeTypeIdIm;
     private long mMimeTypeIdNickname;
@@ -4122,6 +4126,42 @@
         }
     }
 
+    private long getBiggestCachedMimetypeId() {
+        long max = -1;
+        for (long id : mMimetypeCache.values()) {
+            if (id > max) max = id;
+        }
+        return max;
+    }
+
+    public void onBeginTransaction() {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "onBeginTransaction: [" + getClass().getSimpleName() + "]");
+        }
+        mMaxMimeTypeIdAtTransactionStart = getBiggestCachedMimetypeId();
+    }
+
+    public void onCommitTransaction() {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "onCommitTransaction: [" + getClass().getSimpleName() + "]");
+        }
+    }
+
+    public void onRollbackTransaction() {
+        Log.w(TAG, "onRollbackTransaction: [" + getClass().getSimpleName() + "]");
+
+        final Set<String> mimetypesToRemove = Sets.newHashSet();
+        for (String mimetype : mMimetypeCache.keySet()) {
+            if (mMimetypeCache.get(mimetype) > mMaxMimeTypeIdAtTransactionStart) {
+                mimetypesToRemove.add(mimetype);
+            }
+        }
+
+        for (String mimetype : mimetypesToRemove) {
+            mMimetypeCache.remove(mimetype);
+        }
+    }
+
     /**
      * Gets all accounts in the accounts table.
      */
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 6de16df..33eeb80 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -2125,6 +2125,7 @@
             mContactAggregator.clearPendingAggregations();
             mContactTransactionContext.clear();
         }
+        mDbHelper.get().onBeginTransaction();
     }
 
     @Override
@@ -2148,11 +2149,15 @@
             updateProviderStatus();
             mProviderStatusUpdateNeeded = false;
         }
+        mDbHelper.get().onCommitTransaction();
     }
 
     @Override
     public void onRollback() {
-        // Not used.
+        if (VERBOSE_LOGGING) {
+            Log.v(TAG, "onRollback");
+        }
+        mDbHelper.get().onRollbackTransaction();
     }
 
     private void updateSearchIndexInTransaction() {
diff --git a/src/com/android/providers/contacts/ProfileProvider.java b/src/com/android/providers/contacts/ProfileProvider.java
index 8aa653d..360909f 100644
--- a/src/com/android/providers/contacts/ProfileProvider.java
+++ b/src/com/android/providers/contacts/ProfileProvider.java
@@ -140,11 +140,13 @@
         return mDelegate.getLocale();
     }
 
+    @Override
     public void onBegin() {
         mDelegate.switchToProfileMode();
         mDelegate.onBegin();
     }
 
+    @Override
     public void onCommit() {
         mDelegate.switchToProfileMode();
         mDelegate.onCommit();