android: Call bindIsolatedService

The call is going to be implemented in private code until Q sdk can be
made public. So upstream just calls through to downstream code through
reflection.

Also add a method that returns whether bindIsolatedService is supported.

Bug: 953307
Change-Id: Ibdb39265ad987f56fa26abcc4e65981a7ad166ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1574900
Commit-Queue: Bo <boliu@chromium.org>
Reviewed-by: ssid <ssid@chromium.org>
Cr-Commit-Position: refs/heads/master@{#652775}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/BindService.java b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
index bd1b9764..ac304e70 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/BindService.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
@@ -14,6 +14,9 @@
 import android.os.Process;
 import android.os.UserHandle;
 
+import org.chromium.base.BuildInfo;
+import org.chromium.base.StrictModeContext;
+
 import java.lang.reflect.Method;
 import java.util.concurrent.Executor;
 
@@ -21,12 +24,42 @@
  * Class of static helper methods to call Context.bindService variants.
  */
 final class BindService {
+    private static final Method sDoBindServiceQMethod;
+    static {
+        Method method = null;
+        try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
+            if (BuildInfo.isAtLeastQ()) {
+                Class<?> clazz =
+                        Class.forName("org.chromium.base.process_launcher.BindServiceInternal");
+                method = clazz.getDeclaredMethod("doBindServiceQ", Context.class, Intent.class,
+                        ServiceConnection.class, int.class, Executor.class, String.class);
+            }
+        } catch (Exception e) {
+            // Ignore exceptions.
+        } finally {
+            sDoBindServiceQMethod = method;
+        }
+    }
+
     private static Method sBindServiceAsUserMethod;
 
+    static boolean supportVariableConnections() {
+        return sDoBindServiceQMethod != null;
+    }
+
     // Note that handler is not guaranteed to be used, and client still need to correctly handle
     // callbacks on the UI thread.
     static boolean doBindService(Context context, Intent intent, ServiceConnection connection,
             int flags, Handler handler, Executor executor, String instanceName) {
+        if (supportVariableConnections()) {
+            try {
+                return (boolean) sDoBindServiceQMethod.invoke(
+                        null, context, intent, connection, flags, executor, instanceName);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
             return bindServiceByCall(context, intent, connection, flags);
         }