Merge "Do BlockGuard check on Runtime.gc()."
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index 6426bd8..caf0470 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -71,6 +71,11 @@
         void onUnbufferedIO();
 
         /**
+         * Called on explicit GC request, i.e. Runtime.gc().
+         */
+        void onExplicitGc();
+
+        /**
          * Returns the policy bitmask, for shipping over Binder calls
          * to remote threads/processes and reinstantiating the policy
          * there.  The bits in the mask are from the DISALLOW_* and
@@ -124,6 +129,7 @@
             public void onReadFromDisk() {}
             public void onNetwork() {}
             public void onUnbufferedIO() {}
+            public void onExplicitGc() {}
             public int getPolicyMask() {
                 return 0;
             }
diff --git a/luni/src/test/java/libcore/dalvik/system/BlockGuardTest.java b/luni/src/test/java/libcore/dalvik/system/BlockGuardTest.java
index fa99f53..f1c56cf 100644
--- a/luni/src/test/java/libcore/dalvik/system/BlockGuardTest.java
+++ b/luni/src/test/java/libcore/dalvik/system/BlockGuardTest.java
@@ -266,7 +266,13 @@
         Os.close(fd);
     }
 
-    public static class RecordingPolicy implements BlockGuard.Policy {
+    public void testSystemGc() throws Exception {
+        recorder.clear();
+        Runtime.getRuntime().gc();
+        recorder.expectAndClear("onExplicitGc");
+    }
+
+    private static class RecordingPolicy implements BlockGuard.Policy {
         private final List<String> violations = new ArrayList<>();
         private Set<Check> checksList;
 
@@ -275,6 +281,7 @@
             READ_FROM_DISK,
             NETWORK,
             UNBUFFERED_IO,
+            EXPLICIT_GC,
         }
 
         public void setChecks(EnumSet<Check> checksList) {
@@ -309,6 +316,13 @@
             }
         }
 
+        @Override
+        public void onExplicitGc() {
+            if (checksList != null && checksList.contains(Check.EXPLICIT_GC)) {
+                addViolation("onExplicitGc");
+            }
+        }
+
         private void addViolation(String type) {
             StackTraceElement[] threadTrace = Thread.currentThread().getStackTrace();
 
diff --git a/luni/src/test/java/libcore/dalvik/system/PathClassLoaderTest.java b/luni/src/test/java/libcore/dalvik/system/PathClassLoaderTest.java
index 552c732..1320d6c 100644
--- a/luni/src/test/java/libcore/dalvik/system/PathClassLoaderTest.java
+++ b/luni/src/test/java/libcore/dalvik/system/PathClassLoaderTest.java
@@ -150,6 +150,11 @@
             }
 
             @Override
+            public void onExplicitGc() {
+                throw new RuntimeException("onExplicitGc");
+            }
+
+            @Override
             public int getPolicyMask() {
                 return 0;
             }
diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java
index 1ff9b33..333594c 100644
--- a/luni/src/test/java/libcore/java/net/URLTest.java
+++ b/luni/src/test/java/libcore/java/net/URLTest.java
@@ -913,6 +913,11 @@
             }
 
             @Override
+            public void onExplicitGc() {
+                fail("Blockguard.Policy.onExplicitGc");
+            }
+
+            @Override
             public int getPolicyMask() {
                 return 0;
             }
diff --git a/ojluni/src/main/java/java/lang/Runtime.java b/ojluni/src/main/java/java/lang/Runtime.java
index acc75b0..7c48a6c 100644
--- a/ojluni/src/main/java/java/lang/Runtime.java
+++ b/ojluni/src/main/java/java/lang/Runtime.java
@@ -29,6 +29,8 @@
 import dalvik.annotation.optimization.FastNative;
 import java.io.*;
 import java.util.StringTokenizer;
+
+import dalvik.system.BlockGuard;
 import sun.reflect.CallerSensitive;
 import java.lang.ref.FinalizerReference;
 import java.util.ArrayList;
@@ -765,7 +767,14 @@
      * The method {@link System#gc()} is the conventional and convenient
      * means of invoking this method.
      */
-    public native void gc();
+    // Android-changed: Added BlockGuard check to gc()
+    // public native void gc();
+    public void gc() {
+        BlockGuard.getThreadPolicy().onExplicitGc();
+        nativeGc();
+    }
+
+    private native void nativeGc();
 
     /* Wormhole for calling java.lang.ref.Finalizer.runFinalization */
     private static native void runFinalization0();
diff --git a/ojluni/src/main/native/Runtime.c b/ojluni/src/main/native/Runtime.c
index 4c023b5..ad734fd 100644
--- a/ojluni/src/main/native/Runtime.c
+++ b/ojluni/src/main/native/Runtime.c
@@ -62,7 +62,7 @@
 }
 
 JNIEXPORT void JNICALL
-Runtime_gc(JNIEnv *env, jobject this)
+Runtime_nativeGc(JNIEnv *env, jobject this)
 {
     JVM_GC();
 }
@@ -84,7 +84,7 @@
   FAST_NATIVE_METHOD(Runtime, freeMemory, "()J"),
   FAST_NATIVE_METHOD(Runtime, totalMemory, "()J"),
   FAST_NATIVE_METHOD(Runtime, maxMemory, "()J"),
-  NATIVE_METHOD(Runtime, gc, "()V"),
+  NATIVE_METHOD(Runtime, nativeGc, "()V"),
   NATIVE_METHOD(Runtime, nativeExit, "(I)V"),
   NATIVE_METHOD(Runtime, nativeLoad,
                 "(Ljava/lang/String;Ljava/lang/ClassLoader;)"