Prevent writing to FRP partition during factory reset.

Avoid potential race condition between FRP wipe and write operations
during factory reset by making the FRP partition unwritable after
wipe.

Bug: 30352311
Test: manual
Change-Id: If3f024a1611366c0677a996705724458094fcfad
(cherry picked from commit a629c772f4a7a5ddf7ff9f78fb19f7ab86c2a9c2)
(cherry picked from commit a9437bd1caeeb38780d920a81bde8cc7ca280fe0)
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 0f92ed0..8e8c019 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -79,6 +79,9 @@
      * Returns the number of bytes written or -1 on error. If the block is too big
      * to fit on the partition, returns -MAX_BLOCK_SIZE.
      *
+     * {@link #wipe} will block any further {@link #write} operation until reboot,
+     * in which case -1 will be returned.
+     *
      * @param data the data to write
      */
     public int write(byte[] data) {
@@ -129,6 +132,8 @@
     /**
      * Zeroes the previously written block in its entirety. Calling this method
      * will erase all data written to the persistent data partition.
+     * It will also prevent any further {@link #write} operation until reboot,
+     * in order to prevent a potential race condition. See b/30352311.
      */
     public void wipe() {
         try {
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 080b46c..a989a17 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -53,15 +53,14 @@
  * This data will live across factory resets not initiated via the Settings UI.
  * When a device is factory reset through Settings this data is wiped.
  *
- * Allows writing one block at a time. Namely, each time
- * {@link android.service.persistentdata.IPersistentDataBlockService}.write(byte[] data)
- * is called, it will overwite the data that was previously written on the block.
+ * Allows writing one block at a time. Namely, each time {@link IPersistentDataBlockService#write}
+ * is called, it will overwrite the data that was previously written on the block.
  *
  * Clients can query the size of the currently written block via
- * {@link android.service.persistentdata.IPersistentDataBlockService}.getTotalDataSize().
+ * {@link IPersistentDataBlockService#getDataBlockSize}
  *
- * Clients can any number of bytes from the currently written block up to its total size by invoking
- * {@link android.service.persistentdata.IPersistentDataBlockService}.read(byte[] data)
+ * Clients can read any number of bytes from the currently written block up to its total size by
+ * invoking {@link IPersistentDataBlockService#read}
  */
 public class PersistentDataBlockService extends SystemService {
     private static final String TAG = PersistentDataBlockService.class.getSimpleName();
@@ -84,6 +83,7 @@
 
     private int mAllowedUid = -1;
     private long mBlockDeviceSize;
+    private boolean mIsWritable = true;
 
     public PersistentDataBlockService(Context context) {
         super(context);
@@ -377,6 +377,11 @@
             headerAndData.put(data);
 
             synchronized (mLock) {
+                if (!mIsWritable) {
+                    IoUtils.closeQuietly(outputStream);
+                    return -1;
+                }
+
                 try {
                     byte[] checksum = new byte[DIGEST_SIZE_BYTES];
                     outputStream.write(checksum, 0, DIGEST_SIZE_BYTES);
@@ -451,6 +456,9 @@
 
                 if (ret < 0) {
                     Slog.e(TAG, "failed to wipe persistent partition");
+                } else {
+                    mIsWritable = false;
+                    Slog.i(TAG, "persistent partition now wiped and unwritable");
                 }
             }
         }