Merge "Add new StrictMode thread policy - DETECT_UNBUFFERED_IO"
diff --git a/api/current.txt b/api/current.txt
index 1121d9f..5ef2c97 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29288,6 +29288,7 @@
     method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
     method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
@@ -29300,6 +29301,7 @@
     method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
     method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
   }
 
   public static final class StrictMode.VmPolicy {
diff --git a/api/system-current.txt b/api/system-current.txt
index 7f51406..200f6d1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -31797,6 +31797,7 @@
     method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
     method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
@@ -31809,6 +31810,7 @@
     method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
     method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
   }
 
   public static final class StrictMode.VmPolicy {
diff --git a/api/test-current.txt b/api/test-current.txt
index cd75455..a3d3443 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -29358,6 +29358,7 @@
     method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
     method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
@@ -29370,6 +29371,7 @@
     method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
     method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
     method public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
   }
 
   public static final class StrictMode.VmPolicy {
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index c36b488..ff69cf6 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -191,9 +191,14 @@
      */
     public static final int DETECT_RESOURCE_MISMATCH = 0x10;  // for ThreadPolicy
 
+    /**
+     * @hide
+     */
+    public static final int DETECT_UNBUFFERED_IO = 0x20;  // for ThreadPolicy
+
     private static final int ALL_THREAD_DETECT_BITS =
             DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
-            DETECT_RESOURCE_MISMATCH;
+            DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
 
     // Byte 2: Process-policy
 
@@ -465,6 +470,20 @@
             }
 
             /**
+             * Detect unbuffered input/output operations.
+             */
+            public Builder detectUnbufferedIo() {
+                return enable(DETECT_UNBUFFERED_IO);
+            }
+
+            /**
+             * Detect unbuffered input/output operations.
+             */
+            public Builder permitUnbufferedIo() {
+                return disable(DETECT_UNBUFFERED_IO);
+            }
+
+            /**
              * Enables detection of mismatches between defined resource types
              * and getter calls.
              * <p>
@@ -974,6 +993,15 @@
     }
 
     /**
+     * @hide
+     */
+    private static class StrictModeUnbufferedIOViolation extends StrictModeViolation {
+        public StrictModeUnbufferedIOViolation(int policyMask) {
+            super(policyMask, DETECT_UNBUFFERED_IO, null);
+        }
+    }
+
+    /**
      * Returns the bitmask of the current thread's policy.
      *
      * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
@@ -1281,6 +1309,20 @@
             startHandlingViolationException(e);
         }
 
+        // Part of BlockGuard.Policy; just part of StrictMode:
+        public void onUnbufferedIO() {
+            if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
+                return;
+            }
+            if (tooManyViolationsThisLoop()) {
+                return;
+            }
+            BlockGuard.BlockGuardPolicyException e =
+                    new StrictModeUnbufferedIOViolation(mPolicyMask);
+            e.fillInStackTrace();
+            startHandlingViolationException(e);
+        }
+
         // Part of BlockGuard.Policy interface:
         public void onReadFromDisk() {
             if ((mPolicyMask & DETECT_DISK_READ) == 0) {
@@ -2208,6 +2250,18 @@
     /**
      * @hide
      */
+    public static void noteUnbufferedIO() {
+        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
+        if (!(policy instanceof AndroidBlockGuardPolicy)) {
+            // StrictMode not enabled.
+            return;
+        }
+        ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
+    }
+
+    /**
+     * @hide
+     */
     public static void noteDiskRead() {
         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
         if (!(policy instanceof AndroidBlockGuardPolicy)) {