Merge "Update MethodHandles.Lookup.unreflectSpecial test"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index caf7034..1a79aa7 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -205,8 +205,6 @@
     LOCAL_DX_FLAGS := --core-library
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-ojtests
-    # jack bug workaround: int[] java.util.stream.StatefulTestOp.-getjava-util-stream-StreamShapeSwitchesValues() is a private synthetic method in an interface which causes a hard verifier error
-    LOCAL_DEX_PREOPT := false # disable AOT preverification which breaks the build. it will still throw VerifyError at runtime.
     LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
     include $(BUILD_JAVA_LIBRARY)
 endif
@@ -234,8 +232,6 @@
     LOCAL_DX_FLAGS := --core-library
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-ojtests-public
-    # jack bug workaround: int[] java.util.stream.StatefulTestOp.-getjava-util-stream-StreamShapeSwitchesValues() is a private synthetic method in an interface which causes a hard verifier error
-    LOCAL_DEX_PREOPT := false # disable AOT preverification which breaks the build. it will still throw VerifyError at runtime.
     LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
     include $(BUILD_JAVA_LIBRARY)
 endif
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 404b822..6301ff9 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -186,17 +186,6 @@
     public static int getgid() { return Libcore.os.getgid(); }
 
     /**
-     * See <a href="http://man7.org/linux/man-pages/man2/getgroups.2.html">getgroups(2)</a>.
-     *
-     * <p>Should the number of groups change during the execution of this call, the call may
-     *    return an arbitrary subset. This may be worth reconsidering should this be exposed
-     *    as public API.
-     *
-     * @hide
-     */
-    public static int[] getgroups() throws ErrnoException { return Libcore.os.getgroups(); }
-
-    /**
      * See <a href="http://man7.org/linux/man-pages/man3/getenv.3.html">getenv(3)</a>.
      */
     public static String getenv(String name) { return Libcore.os.getenv(name); }
@@ -507,13 +496,6 @@
     public static void setgid(int gid) throws ErrnoException { Libcore.os.setgid(gid); }
 
     /**
-     * See <a href="http://man7.org/linux/man-pages/man2/setgroups.2.html">setgroups(2)</a>.
-     *
-     * @hide
-     */
-    public static void setgroups(int[] gids) throws ErrnoException { Libcore.os.setgroups(gids); }
-
-    /**
      * See <a href="http://man7.org/linux/man-pages/man2/setpgid.2.html">setpgid(2)</a>.
      */
     /** @hide */ public static void setpgid(int pid, int pgid) throws ErrnoException { Libcore.os.setpgid(pid, pgid); }
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index ce88a3b..f141694 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -91,7 +91,6 @@
     public int getegid() { return os.getegid(); }
     public int geteuid() { return os.geteuid(); }
     public int getgid() { return os.getgid(); }
-    public int[] getgroups() throws ErrnoException { return os.getgroups(); }
     public String getenv(String name) { return os.getenv(name); }
     public String getnameinfo(InetAddress address, int flags) throws GaiException { return os.getnameinfo(address, flags); }
     public SocketAddress getpeername(FileDescriptor fd) throws ErrnoException { return os.getpeername(fd); }
@@ -162,7 +161,6 @@
     public void setenv(String name, String value, boolean overwrite) throws ErrnoException { os.setenv(name, value, overwrite); }
     public void seteuid(int euid) throws ErrnoException { os.seteuid(euid); }
     public void setgid(int gid) throws ErrnoException { os.setgid(gid); }
-    public void setgroups(int[] gids) throws ErrnoException { os.setgroups(gids); }
     public void setpgid(int pid, int pgid) throws ErrnoException { os.setpgid(pid, pgid); }
     public void setregid(int rgid, int egid) throws ErrnoException { os.setregid(rgid, egid); }
     public void setreuid(int ruid, int euid) throws ErrnoException { os.setreuid(ruid, euid); }
diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java
index de3b103..807e5a2 100644
--- a/luni/src/main/java/libcore/io/Linux.java
+++ b/luni/src/main/java/libcore/io/Linux.java
@@ -82,7 +82,6 @@
     public native int getegid();
     public native int geteuid();
     public native int getgid();
-    public native int[] getgroups() throws ErrnoException;
     public native String getenv(String name);
     public native String getnameinfo(InetAddress address, int flags) throws GaiException;
     public native SocketAddress getpeername(FileDescriptor fd) throws ErrnoException;
@@ -236,7 +235,6 @@
     public native void setenv(String name, String value, boolean overwrite) throws ErrnoException;
     public native void seteuid(int euid) throws ErrnoException;
     public native void setgid(int gid) throws ErrnoException;
-    public native void setgroups(int[] gids) throws ErrnoException;
     public native void setpgid(int pid, int pgid) throws ErrnoException;
     public native void setregid(int rgid, int egid) throws ErrnoException;
     public native void setreuid(int ruid, int euid) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 194851f..61584b4 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -76,10 +76,6 @@
     public int getegid();
     public int geteuid();
     public int getgid();
-    /* Should the number of groups change during the execution of this call, the call may
-       return an arbitrary subset. This may be worth reconsidering should this be exposed
-       as public API. */
-    public int[] getgroups() throws ErrnoException;
     public String getenv(String name);
     /* TODO: break into getnameinfoHost and getnameinfoService? */
     public String getnameinfo(InetAddress address, int flags) throws GaiException;
@@ -152,7 +148,6 @@
     public void setenv(String name, String value, boolean overwrite) throws ErrnoException;
     public void seteuid(int euid) throws ErrnoException;
     public void setgid(int gid) throws ErrnoException;
-    public void setgroups(int[] gids) throws ErrnoException;
     public void setpgid(int pid, int pgid) throws ErrnoException;
     public void setregid(int rgid, int egid) throws ErrnoException;
     public void setreuid(int ruid, int euid) throws ErrnoException;
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index 04954b9..30da35c 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -19,7 +19,6 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <grp.h>
 #include <ifaddrs.h>
 #include <linux/rtnetlink.h>
 #include <net/if.h>
@@ -1322,24 +1321,6 @@
     return getgid();
 }
 
-static jintArray Linux_getgroups(JNIEnv* env, jobject) {
-    int ngrps = throwIfMinusOne(env, "getgroups", getgroups(0, nullptr));
-    if (ngrps == -1) {
-        return NULL;
-    }
-    std::vector<gid_t> groups(ngrps, 0);
-    ngrps = throwIfMinusOne(env, "getgroups", getgroups(ngrps, &groups[0]));
-    if (ngrps == -1) {
-        return NULL;
-    }
-    jintArray out = env->NewIntArray(ngrps);
-    if ((out != NULL) && (ngrps > 0)) {
-      env->SetIntArrayRegion(out, 0, ngrps, reinterpret_cast<int*>(&groups[0]));
-    }
-
-    return out;
-}
-
 static jstring Linux_getenv(JNIEnv* env, jobject, jstring javaName) {
     ScopedUtfChars name(env, javaName);
     if (name.c_str() == NULL) {
@@ -2179,13 +2160,6 @@
     throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid)));
 }
 
-static void Linux_setgroups(JNIEnv* env, jobject, jintArray gids) {
-    size_t ngrps = gids == NULL ? 0 : env->GetArrayLength(gids);
-    std::vector<gid_t> groups(ngrps, 0);
-    env->GetIntArrayRegion(gids, 0, ngrps, reinterpret_cast<int*>(&groups[0]));
-    throwIfMinusOne(env, "setgroups", setgroups(ngrps, &groups[0]));
-}
-
 static void Linux_setpgid(JNIEnv* env, jobject, jint pid, int pgid) {
     throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid)));
 }
@@ -2524,7 +2498,6 @@
     NATIVE_METHOD(Linux, getegid, "()I"),
     NATIVE_METHOD(Linux, geteuid, "()I"),
     NATIVE_METHOD(Linux, getgid, "()I"),
-    NATIVE_METHOD(Linux, getgroups, "()[I"),
     NATIVE_METHOD(Linux, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(Linux, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"),
     NATIVE_METHOD(Linux, getpeername, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
@@ -2590,7 +2563,6 @@
     NATIVE_METHOD(Linux, setenv, "(Ljava/lang/String;Ljava/lang/String;Z)V"),
     NATIVE_METHOD(Linux, seteuid, "(I)V"),
     NATIVE_METHOD(Linux, setgid, "(I)V"),
-    NATIVE_METHOD(Linux, setgroups, "([I)V"),
     NATIVE_METHOD(Linux, setpgid, "(II)V"),
     NATIVE_METHOD(Linux, setregid, "(II)V"),
     NATIVE_METHOD(Linux, setreuid, "(II)V"),
diff --git a/luni/src/test/java/libcore/libcore/io/OsTest.java b/luni/src/test/java/libcore/libcore/io/OsTest.java
index f169a2c..ab8f16e 100644
--- a/luni/src/test/java/libcore/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/OsTest.java
@@ -926,23 +926,6 @@
     return f;
   }
 
-  public void test_getgroups() throws Exception {
-    int[] gids = Libcore.os.getgroups();
-    assertNotNull(gids);
-  }
-
-  public void test_setgroups() throws Exception {
-    final long ngroupsMax = Libcore.os.sysconf(_SC_NGROUPS_MAX);
-    final int expectedError = ngroupsMax == 0 ? EINVAL : EPERM;
-
-    try {
-      Libcore.os.setgroups(new int[] {-1});
-      fail();
-    } catch (ErrnoException expected) {
-      assertEquals(expectedError, expected.errno);
-    }
-  }
-
   public void test_odirect() throws Exception {
     File testFile = createTempFile("test_odirect", "");
     try {
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index cfc2d13..1edfe34 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -290,9 +290,11 @@
         } catch (IOException e) {
             // Silently ignore and fall back.
         } finally {
-            try {
-                Libcore.os.close(fd);
-            } catch (ErrnoException e) { }
+            if (fd != null) {
+                try {
+                    Libcore.os.close(fd);
+                } catch (ErrnoException e) { }
+            }
         }
 
         return false;
diff --git a/ojluni/src/main/java/java/util/logging/LogManager.java b/ojluni/src/main/java/java/util/logging/LogManager.java
index 7a08510..0d51b0f 100644
--- a/ojluni/src/main/java/java/util/logging/LogManager.java
+++ b/ojluni/src/main/java/java/util/logging/LogManager.java
@@ -185,6 +185,7 @@
                 try {
                     cname = System.getProperty("java.util.logging.manager");
                     if (cname != null) {
+                        // Android-changed: Extract logic into the getClassInstance() helper.
                         mgr = (LogManager) getClassInstance(cname).newInstance();
                     }
                 } catch (Exception ex) {
@@ -198,7 +199,7 @@
 
             }
         });
-     }
+    }
 
 
     // This private class is used as a shutdown hook.
@@ -487,7 +488,7 @@
     // Returns the LoggerContext for the user code (i.e. application or AppContext).
     // Loggers are isolated from each AppContext.
     private LoggerContext getUserContext() {
-        // Android-changed: No AWT specific hooks.
+        // Android-changed: Remove AWT specific hooks.
         return userContext;
     }
 
@@ -582,20 +583,13 @@
         return sysLogger;
     }
 
-    private static Class getClassInstance(String cname) {
-        Class clz = null;
-        if (cname != null) {
-            try {
-                clz = ClassLoader.getSystemClassLoader().loadClass(cname);
-            } catch (ClassNotFoundException ex) {
-                try {
-                    clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
-                } catch (ClassNotFoundException innerEx) {
-                    clz = null;
-                }
-            }
+    // Android-added: getClassInstance helper method, used in several places in this class.
+    private static Class getClassInstance(String cname) throws ClassNotFoundException {
+        try {
+            return ClassLoader.getSystemClassLoader().loadClass(cname);
+        } catch (ClassNotFoundException ex) {
+            return Thread.currentThread().getContextClassLoader().loadClass(cname);
         }
-        return clz;
     }
 
     // LoggerContext maintains the logger namespace per context.
@@ -641,7 +635,7 @@
         // the context requires default loggers, will be added to the context
         // logger's tree.
         final Logger getGlobalLogger() {
-            // Android-changed: s/deprecated/deprecation
+            // Android-changed: Fix SuppressWarnings from "deprecated" to "deprecation".
             @SuppressWarnings("deprecation") // avoids initialization cycles.
             final Logger global = Logger.global;
             return global;
@@ -743,19 +737,9 @@
             return addLocalLogger(logger, requiresDefaultLoggers());
         }
 
-        boolean addLocalLogger(Logger logger, LogManager manager) {
-            // no need to add default loggers if it's not required
-            return addLocalLogger(logger, requiresDefaultLoggers(), manager);
-        }
-
-        boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) {
-            return addLocalLogger(logger, addDefaultLoggersIfNeeded, manager);
-        }
-
         // Add a logger to this context.  This method will only set its level
         // and process parent loggers.  It doesn't set its handlers.
-        synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded,
-                                            LogManager manager) {
+        synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) {
             // addDefaultLoggersIfNeeded serves to break recursion when adding
             // default loggers. If we're adding one of the default loggers
             // (we're being called from ensureDefaultLogger()) then
@@ -957,7 +941,8 @@
                 for (int i = 0; i < names.length; i++) {
                     String word = names[i];
                     try {
-                        // Android-changed:
+                        // Android-changed: Fall back from the system to the context classloader.
+                        // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
                         Class<?> clz = getClassInstance(word);
                         Handler hdl = (Handler) clz.newInstance();
                         // Check if there is a property defining the
@@ -1155,7 +1140,7 @@
         }
         drainLoggerRefQueueBounded();
         LoggerContext cx = getUserContext();
-        if (cx.addLocalLogger(logger, this)) {
+        if (cx.addLocalLogger(logger)) {
             // Do we have a per logger handler too?
             // Note: this will add a 200ms penalty
             loadLoggerHandlers(logger, name, name + ".handlers");
@@ -1268,6 +1253,7 @@
                 // Instantiate the named class.  It is its constructor's
                 // responsibility to initialize the logging configuration, by
                 // calling readConfiguration(InputStream) with a suitable stream.
+                // Android-changed: Extract logic into the getClassInstance() helper.
                 getClassInstance(cname).newInstance();
                 return;
             } catch (Exception ex) {
@@ -1288,8 +1274,14 @@
             fname = f.getCanonicalPath();
         }
 
-        // Android-changed: Look in the boot class-path jar files for the logging.properties.
-        // It will not be present in the file system.
+        // BEGIN Android-changed: Look in the boot class-path jar files for the logging.properties.
+        // It may not be present in the file system.
+        /*
+        try (final InputStream in = new FileInputStream(fname)) {
+            final BufferedInputStream bin = new BufferedInputStream(in);
+            readConfiguration(bin);
+        }
+        */
         InputStream in;
         try {
             in = new FileInputStream(fname);
@@ -1308,6 +1300,7 @@
                 in.close();
             }
         }
+        // END Android-changed: Look in the boot class-path jar files for the logging.properties.
     }
 
     /**
@@ -1419,6 +1412,9 @@
         for (int i = 0; i < names.length; i++) {
             String word = names[i];
             try {
+                // Android-changed: Fall back from the system to the context classloader.
+                // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
+                // clz.newInstance();
                 getClassInstance(word).newInstance();
             } catch (Exception ex) {
                 System.err.println("Can't load config class \"" + word + "\"");
@@ -1531,6 +1527,9 @@
         String val = getProperty(name);
         try {
             if (val != null) {
+                // Android-changed: Fall back from the system to the context classloader.
+                // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val);
+                // return (Filter) clz.newInstance();
                 return (Filter) getClassInstance(val).newInstance();
             }
         } catch (Exception ex) {
@@ -1551,6 +1550,9 @@
         String val = getProperty(name);
         try {
             if (val != null) {
+                // Android-changed: Fall back from the system to the context classloader.
+                // Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val);
+                // return (Formatter) clz.newInstance();
                 return (Formatter) getClassInstance(val).newInstance();
             }
         } catch (Exception ex) {
@@ -1702,6 +1704,7 @@
 
     // Management Support
     private static LoggingMXBean loggingMXBean = null;
+    // Android-removed: References to java.lang.management in javadoc.
     /**
      * String representation of the {@code ObjectName} for the management interface
      * for the logging facility.
@@ -1710,12 +1713,10 @@
      *
      * @since 1.5
      */
-    // Android-changed: Remove reference to java.lang.management.ObjectName.
-    //
-    //@see java.lang.management.PlatformLoggingMXBean
     public final static String LOGGING_MXBEAN_NAME
         = "java.util.logging:type=Logging";
 
+    // Android-removed: References to java.lang.management in javadoc.
     /**
      * Returns <tt>LoggingMXBean</tt> for managing loggers.
      *
@@ -1723,17 +1724,6 @@
      *
      * @since 1.5
      */
-    // Android-removed docs areferring to java.lang.management.
-    //
-    // An alternative way to manage loggers is through the
-    // {@link java.lang.management.PlatformLoggingMXBean} interface
-    // that can be obtained by calling:
-    // <pre>
-    //     PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
-    //        ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
-    // </pre>
-    //
-    // @see java.lang.management.PlatformLoggingMXBean
     public static synchronized LoggingMXBean getLoggingMXBean() {
         if (loggingMXBean == null) {
             loggingMXBean =  new Logging();