Add DIRTY_RETAIN constant

Previously the DIRTY flag can only be automatically or explicitly set.
There are no option to express "This operation does not change the DIRTY
flag". This causes issue when the voicemail source is downloading
changes from the server instead of uploading and would clobber the flag.

After this CL, if DIRTY is updated with DIRTY_RETAIN, the flag will not
be updated for the operation.

Change-Id: I4ed430865c28c824cbd13ccf884091637b106d8a
Fixes: 64371667
Test: CtsProviderTestCases#VoicemailProviderTest
diff --git a/api/current.txt b/api/current.txt
index 7c22491..9c5154f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35955,6 +35955,7 @@
     field public static final java.lang.String DATE = "date";
     field public static final java.lang.String DELETED = "deleted";
     field public static final java.lang.String DIRTY = "dirty";
+    field public static final int DIRTY_RETAIN = -1; // 0xffffffff
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String HAS_CONTENT = "has_content";
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 864a0fd..6be0e76 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -16,7 +16,6 @@
 
 package android.provider;
 
-import android.Manifest;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
@@ -50,7 +49,7 @@
  * </ul>
  *
  * <P> The minimum permission needed to access this content provider is
- * {@link Manifest.permission#ADD_VOICEMAIL}
+ * {@link android.Manifest.permission#ADD_VOICEMAIL}
  *
  * <P>Voicemails are inserted by what is called as a "voicemail source"
  * application, which is responsible for syncing voicemail data between a remote
@@ -293,11 +292,26 @@
          * Flag used to indicate that local, unsynced changes are present.
          * Currently, this is used to indicate that the voicemail was read or deleted.
          * The value will be 1 if dirty is true, 0 if false.
+         *
+         * <p>When a caller updates a voicemail row (either with {@link ContentResolver#update} or
+         * {@link ContentResolver#applyBatch}), and if the {@link ContentValues} doesn't contain
+         * this column, the voicemail provider implicitly sets it to 0 if the calling package is
+         * the {@link #SOURCE_PACKAGE} or to 1 otherwise. To prevent this behavior, explicitly set
+         * {@link #DIRTY_RETAIN} to this column in the {@link ContentValues}.
+         *
          * <P>Type: INTEGER (boolean)</P>
+         *
+         * @see #DIRTY_RETAIN
          */
         public static final String DIRTY = "dirty";
 
         /**
+         * Value of {@link #DIRTY} when updating to indicate that the value should not be updated
+         * during this operation.
+         */
+        public static final int DIRTY_RETAIN = -1;
+
+        /**
          * Flag used to indicate that the voicemail was deleted but not synced to the server.
          * A deleted row should be ignored.
          * The value will be 1 if deleted is true, 0 if false.