Merge "Allow Voicemails to be inserted as not new."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index aa1c396..ca4264b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -15,6 +15,7 @@
     <uses-permission android:name="android.permission.SEND_CALL_LOG_CHANGE" />
     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
 
     <permission
             android:name="android.permission.SEND_CALL_LOG_CHANGE"
diff --git a/src/com/android/providers/contacts/DbModifierWithNotification.java b/src/com/android/providers/contacts/DbModifierWithNotification.java
index 0babe1b..0580339 100644
--- a/src/com/android/providers/contacts/DbModifierWithNotification.java
+++ b/src/com/android/providers/contacts/DbModifierWithNotification.java
@@ -167,7 +167,7 @@
         Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs);
         packagesModified.addAll(getModifiedPackages(values));
 
-        boolean isVoicemail = packagesModified.size() != 0;
+        boolean isVoicemail = packagesModified.size() != 0 && isUpdatingVoicemailColumns(values);
 
         boolean hasMarkedRead = false;
         if (mIsCallsTable) {
@@ -189,13 +189,12 @@
                         }
                     }
                 }
-                // updateDirtyFlag might remove the value and leave values empty.
-                if(values.isEmpty()){
-                    return 0;
-                }
             }
         }
-
+        // updateDirtyFlag might remove the value and leave values empty.
+        if (values.isEmpty()) {
+            return 0;
+        }
         int count = mDb.update(table, values, whereClause, whereArgs);
         if (count > 0 && isVoicemail) {
             notifyVoicemailChange(mBaseUri, packagesModified);
@@ -237,6 +236,15 @@
         return isDirty == 0;
     }
 
+    private boolean isUpdatingVoicemailColumns(ContentValues values) {
+        for (String key : values.keySet()) {
+            if (VoicemailContentTable.ALLOWED_COLUMNS.contains(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void updateLastModified(String table, String whereClause, String[] whereArgs) {
         ContentValues values = new ContentValues();
         values.put(Calls.LAST_MODIFIED, getTimeMillis());
diff --git a/src/com/android/providers/contacts/VoicemailContentTable.java b/src/com/android/providers/contacts/VoicemailContentTable.java
index 1b39e7f..67dda92 100644
--- a/src/com/android/providers/contacts/VoicemailContentTable.java
+++ b/src/com/android/providers/contacts/VoicemailContentTable.java
@@ -58,7 +58,7 @@
 
     private static final String[] FILENAME_ONLY_PROJECTION = new String[] {Voicemails._DATA};
 
-    private static final ImmutableSet<String> ALLOWED_COLUMNS = new ImmutableSet.Builder<String>()
+    public static final ImmutableSet<String> ALLOWED_COLUMNS = new ImmutableSet.Builder<String>()
             .add(Voicemails._ID)
             .add(Voicemails.NUMBER)
             .add(Voicemails.DATE)
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index 52e2f09..d2bfa87 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -194,22 +194,47 @@
 
     public void testUpdateOwnPackageVoicemail_NotDirty() {
         final Uri uri = mResolver.insert(voicemailUri(), getTestVoicemailValues());
-        mResolver.update(uri, new ContentValues(), null, null);
+        ContentValues updateValues = new ContentValues();
+        updateValues.put(Voicemails.TRANSCRIPTION, "foo");
+        mResolver.update(uri, updateValues, null, null);
 
         // Updating a package's own voicemail should not make the voicemail dirty.
-        ContentValues values = getTestVoicemailValues();
-        values.put(Voicemails.DIRTY, "0");
-        assertStoredValues(uri, values);
+        try (Cursor cursor = mResolver
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(cursor.getInt(0), 0);
+        }
+    }
+
+    public void testUpdateOtherPackageCallLog_NotDirty() {
+        setUpForFullPermission();
+        final Uri uri = insertVoicemailForSourcePackage("another-package");
+        // Clear the mapping for our own UID so that this doesn't look like an internal transaction.
+        mPackageManager.removePackage(Process.myUid());
+
+        ContentValues values = new ContentValues();
+        values.put(Calls.CACHED_NAME, "foo");
+        mResolver.update(ContentUris
+                        .withAppendedId(CallLog.Calls.CONTENT_URI, ContentUris.parseId(uri)),
+                values, null, null);
+
+        try (Cursor cursor = mResolver
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(cursor.getInt(0), 0);
+        }
     }
 
     public void testUpdateOwnPackageVoicemail_RemovesDirtyStatus() {
         ContentValues values = getTestVoicemailValues();
         values.put(Voicemails.DIRTY, "1");
         final Uri uri = mResolver.insert(voicemailUri(), values);
-
-        mResolver.update(uri, new ContentValues(), null, null);
+        ContentValues updateValues = new ContentValues();
+        updateValues.put(Voicemails.IS_READ, 1);
+        mResolver.update(uri, updateValues, null, null);
         // At this point, the voicemail should be set back to not dirty.
         ContentValues newValues = getTestVoicemailValues();
+        newValues.put(Voicemails.IS_READ, 1);
         newValues.put(Voicemails.DIRTY, "0");
         assertStoredValues(uri, newValues);
     }