Merge "Set Calls.NEW to 0 if the voicemail is read." into mnc-dev
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index b5dbd06..f83e4a7 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -125,7 +125,6 @@
         sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_COMPONENT_NAME, Calls.PHONE_ACCOUNT_COMPONENT_NAME);
         sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ID, Calls.PHONE_ACCOUNT_ID);
         sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ADDRESS, Calls.PHONE_ACCOUNT_ADDRESS);
-        sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_HIDDEN, Calls.PHONE_ACCOUNT_HIDDEN);
         sCallsProjectionMap.put(Calls.NEW, Calls.NEW);
         sCallsProjectionMap.put(Calls.VOICEMAIL_URI, Calls.VOICEMAIL_URI);
         sCallsProjectionMap.put(Calls.TRANSCRIPTION, Calls.TRANSCRIPTION);
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index bbde779..2bccea1 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -122,7 +122,7 @@
      *   1000-1099 M
      * </pre>
      */
-    static final int DATABASE_VERSION = 1009;
+    static final int DATABASE_VERSION = 1010;
 
     public interface Tables {
         public static final String CONTACTS = "contacts";
@@ -1872,6 +1872,7 @@
                 + Data.DATA13 + ", "
                 + Data.DATA14 + ", "
                 + Data.DATA15 + ", "
+                + Data.CARRIER_PRESENCE + ", "
                 + Data.SYNC1 + ", "
                 + Data.SYNC2 + ", "
                 + Data.SYNC3 + ", "
@@ -2937,6 +2938,11 @@
             oldVersion = 1009;
         }
 
+        if (oldVersion < 1010) {
+            upgradeViewsAndTriggers = true;
+            oldVersion = 1010;
+        }
+
         if (upgradeViewsAndTriggers) {
             createContactsViews(db);
             createGroupsView(db);
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 6cf6d98..72512b7 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -712,6 +712,7 @@
             .add(Data.DATA13)
             .add(Data.DATA14)
             .add(Data.DATA15)
+            .add(Data.CARRIER_PRESENCE)
             .add(Data.DATA_VERSION)
             .add(Data.IS_PRIMARY)
             .add(Data.IS_SUPER_PRIMARY)
@@ -6771,6 +6772,10 @@
             final Uri remoteUri = maybeAddUserId(localUri, corpUserId);
             final Cursor managedCursor = getContext().getContentResolver().query(remoteUri,
                     projection, selection, selectionArgs, sortOrder, null);
+            if (managedCursor == null) {
+                // No corp results.  Just return the local result.
+                return primaryCursor;
+            }
             final Cursor[] cursorArray = new Cursor[] {
                     primaryCursor, new EnterprisePhoneCursorWrapper(managedCursor)
             };
@@ -6814,10 +6819,7 @@
             local.close();
             throw th;
         }
-
-        if (local != null) {
-            local.close();
-        }
+        // "local" is still open.  If we fail the managed CP2 query, we'll still return it.
 
         // Step 2.  No rows found in the local db, and there is a corp profile. Look at the corp
         // DB.
@@ -6831,7 +6833,11 @@
         // Note in order to re-write the cursor correctly, we need all columns from the corp cp2.
         final Cursor corp = getContext().getContentResolver().query(remoteUri, null,
                 selection, selectionArgs, sortOrder, /* cancellationsignal */null);
+        if (corp == null) {
+            return local;
+        }
         try {
+            local.close();
             if (VERBOSE_LOGGING) {
                 MoreDatabaseUtils.dumpCursor(TAG, "corp raw", corp);
             }
diff --git a/src/com/android/providers/contacts/DbModifierWithNotification.java b/src/com/android/providers/contacts/DbModifierWithNotification.java
index 3576849..23a4333 100644
--- a/src/com/android/providers/contacts/DbModifierWithNotification.java
+++ b/src/com/android/providers/contacts/DbModifierWithNotification.java
@@ -160,7 +160,7 @@
             // the server and thus is synced or "clean". Otherwise, it means that a local change
             // is being made to the database, so the entries should be marked as "dirty" so that
             // the corresponding sync adapter knows they need to be synced.
-            final int isDirty = isSelfModifying(packagesModified) ? 0 : 1;
+            final int isDirty = isSelfModifyingOrInternal(packagesModified) ? 0 : 1;
             values.put(VoicemailContract.Voicemails.DIRTY, isDirty);
         }
 
@@ -185,8 +185,10 @@
         // mark the entry as "deleted"--deleted entries should be hidden from the user.
         // Once the changes are synced to the server, delete will be called again, this time
         // removing the rows from the table.
+        // If the deletion is being made by the package that inserted the voicemail or by
+        // CP2 (cleanup after uninstall), then we don't need to wait for sync, so just delete it.
         final int count;
-        if (mIsCallsTable && isVoicemail && !isSelfModifying(packagesModified)) {
+        if (mIsCallsTable && isVoicemail && !isSelfModifyingOrInternal(packagesModified)) {
             ContentValues values = new ContentValues();
             values.put(VoicemailContract.Voicemails.DIRTY, 1);
             values.put(VoicemailContract.Voicemails.DELETED, 1);
@@ -236,9 +238,21 @@
         return impactedPackages;
     }
 
-    private boolean isSelfModifying(Set<String> packagesModified) {
-        return packagesModified.size() == 1 && getCallingPackages().contains(
-                Iterables.getOnlyElement(packagesModified));
+    /**
+     * @param packagesModified source packages that inserted the voicemail that is being modified
+     * @return {@code true} if the caller is modifying its own voicemail, or this is an internal
+     *         transaction, {@code false} otherwise.
+     */
+    private boolean isSelfModifyingOrInternal(Set<String> packagesModified) {
+        final Collection<String> callingPackages = getCallingPackages();
+        if (callingPackages == null) {
+            return false;
+        }
+        // The last clause has the same effect as doing Process.myUid() == Binder.getCallingUid(),
+        // but allows us to mock the results for testing.
+        return packagesModified.size() == 1 && (callingPackages.contains(
+                Iterables.getOnlyElement(packagesModified))
+                        || callingPackages.contains(mContext.getPackageName()));
     }
 
     private void notifyVoicemailChange(Uri notificationUri, Set<String> modifiedPackages,
diff --git a/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java b/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java
index 8e4121d..afb9980 100644
--- a/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java
@@ -22,6 +22,7 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.os.Process;
 import android.provider.CallLog.Calls;
 import android.provider.VoicemailContract;
 
@@ -37,12 +38,17 @@
 
     protected boolean mUseSourceUri = false;
     private File mTestDirectory;
+    ContactsMockPackageManager mPackageManager;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         addProvider(TestVoicemailProvider.class, VoicemailContract.AUTHORITY);
         TestVoicemailProvider.setVvmProviderCallDelegate(createMockProviderCalls());
+
+        mPackageManager = (ContactsMockPackageManager) getProvider()
+                .getContext().getPackageManager();
+        mPackageManager.addPackage(Process.myUid(), mActor.packageName);
     }
 
     @Override
@@ -101,7 +107,7 @@
 
             @Override
             public PackageManager getPackageManager() {
-                return new MockPackageManager(mActor.getProviderContext().getPackageName());
+                return mActor.getProviderContext().getPackageManager();
             }
         };
     }
diff --git a/tests/src/com/android/providers/contacts/CallLogProviderTest.java b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
index ea436d8..32e0988 100644
--- a/tests/src/com/android/providers/contacts/CallLogProviderTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
@@ -64,7 +64,7 @@
             Voicemails.DIRTY,
             Voicemails.DELETED};
     /** Total number of columns exposed by call_log provider. */
-    private static final int NUM_CALLLOG_FIELDS = 25;
+    private static final int NUM_CALLLOG_FIELDS = 26;
 
     private CallLogProvider mCallLogProvider;
 
@@ -481,7 +481,7 @@
             return new ContextWrapper(super.context()) {
                 @Override
                 public PackageManager getPackageManager() {
-                    return new MockPackageManager("com.test.package1", "com.test.package2");
+                    return super.getPackageManager();
                 }
 
                 @Override
diff --git a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
index a5aa7c7..1f3f52e 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
@@ -16,16 +16,16 @@
 package com.android.providers.contacts;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.os.Binder;
 import android.test.mock.MockPackageManager;
 
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
@@ -51,6 +51,13 @@
         mReverse.put(packageName, packageUid);
     }
 
+    public void removePackage(int packageUid) {
+        final String packageName = mForward.remove(packageUid);
+        if (packageName != null) {
+            mReverse.remove(packageName);
+        }
+    }
+
     @Override
     public String getNameForUid(int uid) {
         return "name-for-uid";
@@ -58,10 +65,13 @@
 
     @Override
     public String[] getPackagesForUid(int uid) {
-        if (mPackages != null) {
+        final String packageName = mForward.get(uid);
+        if (packageName != null) {
+            return new String[] {packageName};
+        } else if (mPackages != null) {
             return new String[] { mPackages.get(0).packageName };
         } else {
-            return new String[] { ContactsActor.sCallingPackage };
+            return new String[] {};
         }
     }
 
@@ -93,6 +103,11 @@
     }
 
     @Override
+    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
+        return new ArrayList<ResolveInfo>();
+    }
+
+    @Override
     public Resources getResourcesForApplication(String appPackageName) {
         return new ContactsMockResources();
     }
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index 73d0083..3c21d21 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -97,6 +97,7 @@
 import com.android.providers.contacts.testutil.RawContactUtil;
 import com.android.providers.contacts.testutil.TestUtil;
 import com.android.providers.contacts.tests.R;
+import com.android.providers.contacts.util.NullContentProvider;
 
 import com.google.android.collect.Lists;
 import com.google.android.collect.Sets;
@@ -367,6 +368,7 @@
                 Data.DATA13,
                 Data.DATA14,
                 Data.DATA15,
+                Data.CARRIER_PRESENCE,
                 Data.SYNC1,
                 Data.SYNC2,
                 Data.SYNC3,
@@ -453,6 +455,7 @@
                 Data.DATA13,
                 Data.DATA14,
                 Data.DATA15,
+                Data.CARRIER_PRESENCE,
                 Data.SYNC1,
                 Data.SYNC2,
                 Data.SYNC3,
@@ -534,6 +537,7 @@
                 Data.DATA13,
                 Data.DATA14,
                 Data.DATA15,
+                Data.CARRIER_PRESENCE,
                 Data.SYNC1,
                 Data.SYNC2,
                 Data.SYNC3,
@@ -641,6 +645,7 @@
                 Data.DATA13,
                 Data.DATA14,
                 Data.DATA15,
+                Data.CARRIER_PRESENCE,
                 Data.SYNC1,
                 Data.SYNC2,
                 Data.SYNC3,
@@ -1784,6 +1789,35 @@
     }
 
     /**
+     * Test for enterprise caller-id.  Corp profile exists, but it returns a null cursor.
+     */
+    public void testPhoneLookupEnterprise_withCorpProfile_nullResult() throws Exception {
+        setUpNullCorpProvider();
+
+        Uri uri1 = Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, "408-111-1111");
+
+        // No contacts profile, no data.
+        assertEquals(0, getCount(uri1));
+
+        // Insert a contact into the primary CP2.
+        long rawContactId = ContentUris.parseId(
+                mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()));
+        DataUtil.insertStructuredName(mResolver, rawContactId, "Contact1", "Doe");
+        insertPhoneNumber(rawContactId, "408-111-1111");
+
+        // Do the query again and check the result.
+        Cursor c = mResolver.query(uri1, null, null, null, null);
+        try {
+            assertEquals(1, c.getCount());
+            c.moveToPosition(0);
+            long contactId = c.getLong(c.getColumnIndex(PhoneLookup._ID));
+            assertFalse(Contacts.isEnterpriseContactId(contactId)); // Make sure it's not rewritten.
+        } finally {
+            c.close();
+        }
+    }
+
+    /**
      * Set up the corp user / CP2 and returns the corp CP2 instance.
      *
      * Create a second instance of CP2, and add it to the resolver, with the "user-id@" authority.
@@ -1802,12 +1836,27 @@
     }
 
     /**
+     * Similar to {@link setUpCorpProvider}, but the corp CP2 set up with this will always return
+     * null from query().
+     */
+    private void setUpNullCorpProvider() throws Exception {
+        mActor.mockUserManager.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.CORP_USER);
+
+        mActor.addProvider(
+                NullContentProvider.class,
+                "" + MockUserManager.CORP_USER.id + "@com.android.contacts",
+                new AlteringUserContext(mActor.getProviderContext(), MockUserManager.CORP_USER.id));
+    }
+
+    /**
      * Test for query of merged primary and work contacts.
      * <p/>
      * Note: in this test, we add one more provider instance for the authority
      * "10@com.android.contacts" and use it as the corp cp2.
      */
     public void testQueryMergedDataPhones() throws Exception {
+        mActor.addPermissions("android.permission.INTERACT_ACROSS_USERS");
+
         // Insert a contact to the primary CP2.
         long rawContactId = ContentUris.parseId(
                 mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()));
@@ -1880,6 +1929,43 @@
     }
 
     /**
+     * Test for query of merged primary and work contacts.
+     * <p/>
+     * Note: in this test, we add one more provider instance for the authority
+     * "10@com.android.contacts" and use it as the corp cp2.
+     */
+    public void testQueryMergedDataPhones_nullCorp() throws Exception {
+        mActor.addPermissions("android.permission.INTERACT_ACROSS_USERS");
+
+        // Insert a contact to the primary CP2.
+        long rawContactId = ContentUris.parseId(
+                mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()));
+        DataUtil.insertStructuredName(mResolver, rawContactId, "Contact1", "Primary");
+
+        insertPhoneNumber(rawContactId, "111-111-1111", false, false, Phone.TYPE_MOBILE);
+
+        // Insert a contact to the corp CP2, with different name and phone number.
+        setUpNullCorpProvider();
+
+        // Execute the query to get the merged result.
+        Cursor c = mResolver.query(Phone.ENTERPRISE_CONTENT_URI, new String[]{Phone.CONTACT_ID,
+                        Phone.DISPLAY_NAME, Phone.NUMBER}, Phone.TYPE + " = ?",
+                new String[]{String.valueOf(Phone.TYPE_MOBILE)}, null);
+        try {
+            // Verify the primary contact.
+            assertEquals(1, c.getCount());
+            assertEquals(3, c.getColumnCount());
+            c.moveToPosition(0);
+            assertEquals("Contact1 Primary", c.getString(c.getColumnIndex(Phone.DISPLAY_NAME)));
+            assertEquals("111-111-1111", c.getString(c.getColumnIndex(Phone.NUMBER)));
+            long contactId = c.getLong(c.getColumnIndex(Phone.CONTACT_ID));
+            assertFalse(Contacts.isEnterpriseContactId(contactId));
+        } finally {
+            c.close();
+        }
+    }
+
+    /**
      * Test for enterprise caller-id, with the corp profile.
      *
      * Note: in this test, we add one more provider instance for the authority
@@ -1976,6 +2062,8 @@
     }
 
     public void testQueryRawContactEntitiesCorp_noCorpProfile() {
+        mActor.addPermissions("android.permission.INTERACT_ACROSS_USERS");
+
         // Insert a contact into the primary CP2.
         long rawContactId = ContentUris.parseId(
                 mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()));
@@ -1987,6 +2075,8 @@
     }
 
     public void testQueryRawContactEntitiesCorp_withCorpProfile() throws Exception {
+        mActor.addPermissions("android.permission.INTERACT_ACROSS_USERS");
+
         // Insert a contact into the primary CP2.
         long rawContactId = ContentUris.parseId(
                 mResolver.insert(RawContacts.CONTENT_URI, new ContentValues()));
@@ -6057,6 +6147,7 @@
         values.put(Data.DATA13, "old13");
         values.put(Data.DATA14, "old14");
         values.put(Data.DATA15, "old15");
+        values.put(Data.CARRIER_PRESENCE, 0);
         Uri uri = mResolver.insert(Data.CONTENT_URI, values);
         assertStoredValues(uri, values);
         assertNetworkNotified(true);
@@ -6080,6 +6171,7 @@
         values.put(Data.DATA13, "new13");
         values.put(Data.DATA14, "new14");
         values.put(Data.DATA15, "new15");
+        values.put(Data.CARRIER_PRESENCE, Data.CARRIER_PRESENCE_VT_CAPABLE);
         mResolver.update(Data.CONTENT_URI, values, Data.RAW_CONTACT_ID + "=" + rawContactId +
                 " AND " + Data.MIMETYPE + "='testmimetype'", null);
         assertNetworkNotified(true);
@@ -9115,6 +9207,7 @@
         values.put(Data.DATA13, "thirteen");
         values.put(Data.DATA14, "fourteen");
         values.put(Data.DATA15, "fifteen");
+        values.put(Data.CARRIER_PRESENCE, Data.CARRIER_PRESENCE_VT_CAPABLE);
         values.put(Data.SYNC1, "sync1");
         values.put(Data.SYNC2, "sync2");
         values.put(Data.SYNC3, "sync3");
diff --git a/tests/src/com/android/providers/contacts/MockPackageManager.java b/tests/src/com/android/providers/contacts/MockPackageManager.java
deleted file mode 100644
index 7c2d4df..0000000
--- a/tests/src/com/android/providers/contacts/MockPackageManager.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.providers.contacts;
-
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ResolveInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MockPackageManager extends android.test.mock.MockPackageManager {
-    private final String[] mPackages;
-    public MockPackageManager(String... packages) {
-        mPackages = packages;
-    }
-
-    @Override
-    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
-        List<ResolveInfo> resolveInfos = new ArrayList<ResolveInfo>();
-        for (String pkg : mPackages) {
-            resolveInfos.add(createResolveInfo(pkg));
-        }
-        return resolveInfos;
-    }
-
-    private ResolveInfo createResolveInfo(String packageName) {
-        ActivityInfo activityInfo = new ActivityInfo();
-        activityInfo.packageName = packageName;
-        activityInfo.name = "FooClass";
-        ResolveInfo resolveInfo = new ResolveInfo();
-        resolveInfo.activityInfo = activityInfo;
-        return resolveInfo;
-    }
-
-    @Override
-    public String[] getPackagesForUid(int uid) {
-        return new String[] {mPackages[0]};
-    }
-
-    @Override
-    public int checkPermission(String permName, String pkgName) {
-        return PERMISSION_GRANTED;
-    }
-}
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index 4f79837..dc4335c 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -21,6 +21,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.provider.CallLog.Calls;
 import android.provider.VoicemailContract;
 import android.provider.VoicemailContract.Status;
@@ -144,6 +145,33 @@
         assertStoredValues(uri, newValues);
     }
 
+    public void testDeleteOwnPackageVoicemail_DeletesRow() {
+        setUpForFullPermission();
+        final Uri ownVoicemail = insertVoicemail();
+        assertEquals(1, getCount(voicemailUri(), null, null));
+
+        mResolver.delete(ownVoicemail, null, null);
+
+        assertEquals(0, getCount(ownVoicemail, null, null));
+    }
+
+    public void testDeleteOtherPackageVoicemail_SetsDirtyStatus() {
+        setUpForFullPermission();
+        final Uri anotherVoicemail = insertVoicemailForSourcePackage("another-package");
+        assertEquals(1, getCount(voicemailUri(), null, null));
+
+        // Clear the mapping for our own UID so that this doesn't look like an internal transaction.
+        mPackageManager.removePackage(Process.myUid());
+        mResolver.delete(anotherVoicemail, null, null);
+
+        ContentValues values = getTestVoicemailValues();
+        values.put(Voicemails.DIRTY, "1");
+        values.put(Voicemails.DELETED, "1");
+
+        assertEquals(1, getCount(anotherVoicemail, null, null));
+        assertStoredValues(anotherVoicemail, values);
+    }
+
     public void testDelete() {
         Uri uri = insertVoicemail();
         int count = mResolver.delete(voicemailUri(), Voicemails._ID + "="
@@ -265,9 +293,7 @@
         });
 
         // If we have the manage voicemail permission, we should be able to both update voicemails
-        // from all packages. However, when updating or deleting a voicemail from a different
-        // package, the "dirty" flag must be set on updates and "dirty" and "delete" flags must be
-        // set on deletion.
+        // from all packages.
         setUpForNoPermission();
         mActor.addPermissions(WRITE_VOICEMAIL_PERMISSION);
         mResolver.update(anotherVoicemail, getTestVoicemailValues(), null, null);
@@ -280,15 +306,11 @@
 
         mResolver.delete(anotherVoicemail, null, null);
 
-        // Now add the read voicemail permission temporarily to verify that the delete flag is set.
+        // Now add the read voicemail permission temporarily to verify that the voicemail is
+        // deleted.
         mActor.addPermissions(READ_VOICEMAIL_PERMISSION);
 
-        ContentValues values = getTestVoicemailValues();
-        values.put(Voicemails.DIRTY, "1");
-        values.put(Voicemails.DELETED, "1");
-
-        assertEquals(1, getCount(anotherVoicemail, null, null));
-        assertStoredValues(anotherVoicemail, values);
+        assertEquals(0, getCount(anotherVoicemail, null, null));
     }
 
     private Uri withSourcePackageParam(Uri uri) {
diff --git a/tests/src/com/android/providers/contacts/util/NullContentProvider.java b/tests/src/com/android/providers/contacts/util/NullContentProvider.java
new file mode 100644
index 0000000..1f39b18
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/util/NullContentProvider.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.providers.contacts.util;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class NullContentProvider extends ContentProvider {
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+}