Implement binder native side for IArcVideoBridge

Bug: 63828247
Test: C2VDAComponent_test
Change-Id: I9b17c91512c32ec3119ff9420cc96c17027b2b8b
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index b18c1a0..0bc58e0 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -55,6 +55,17 @@
         "frameworks/native/services",
         "system/gatekeeper/include",
     ],
+
+    product_variables: {
+        arc: {
+            cflags: [
+                "-DUSE_ARC",
+            ],
+            srcs: [
+                "com_android_server_ArcVideoService.cpp",
+            ],
+        }
+    }
 }
 
 cc_defaults {
@@ -119,4 +130,17 @@
         "android.hardware.broadcastradio@common-utils-1x-lib",
         "libscrypt_static",
     ],
+
+    product_variables: {
+        arc: {
+            // TODO: remove the suffix "_bp" after finishing migration to Android.bp.
+            shared_libs: [
+                "libarcbridge",
+                "libarcbridgeservice",
+                "libarcvideobridge",
+                "libchrome",
+                "libmojo_bp",
+            ],
+        }
+    }
 }
diff --git a/services/core/jni/com_android_server_ArcVideoService.cpp b/services/core/jni/com_android_server_ArcVideoService.cpp
new file mode 100644
index 0000000..7df8276
--- /dev/null
+++ b/services/core/jni/com_android_server_ArcVideoService.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ArcVideoService"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <media/arcvideobridge/IArcVideoBridge.h>
+#include <utils/Log.h>
+
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <mojo/edk/embedder/embedder.h>
+#include <mojo/public/cpp/bindings/binding.h>
+
+#include <arc/ArcBridgeSupport.h>
+#include <arc/ArcService.h>
+#include <arc/Future.h>
+#include <arc/IArcBridgeService.h>
+#include <arc/MojoProcessSupport.h>
+#include <video.mojom.h>
+
+namespace {
+
+// [MinVersion] of OnVideoInstanceReady method in arc_bridge.mojom.
+constexpr int kMinimumArcBridgeHostVersion = 6;
+
+void onCaptureResult(arc::Future<arc::MojoBootstrapResult>* future, uint32_t version,
+                     mojo::ScopedHandle handle, const std::string& token) {
+    mojo::edk::ScopedPlatformHandle scoped_platform_handle;
+    MojoResult result =
+            mojo::edk::PassWrappedPlatformHandle(handle.release().value(), &scoped_platform_handle);
+    if (result != MOJO_RESULT_OK) {
+        ALOGE("Received invalid file descriptor.");
+        future->set(arc::MojoBootstrapResult());
+        return;
+    }
+
+    base::ScopedFD fd(scoped_platform_handle.release().handle);
+    future->set(arc::MojoBootstrapResult(std::move(fd), token, version));
+}
+
+}  // namespace
+
+namespace arc {
+
+class VideoService : public mojom::VideoInstance,
+                     public ArcService,
+                     public android::BnArcVideoBridge {
+public:
+    explicit VideoService(MojoProcessSupport* mojoProcessSupport)
+          : mMojoProcessSupport(mojoProcessSupport), mBinding(this) {
+        mMojoProcessSupport->arc_bridge_support().requestArcBridgeProxyAsync(
+                this, kMinimumArcBridgeHostVersion);
+    }
+
+    ~VideoService() override { mMojoProcessSupport->disconnect(&mBinding, &mHostPtr); }
+
+    // VideoInstance overrides:
+    void InitDeprecated(mojom::VideoHostPtr hostPtr) override {
+        Init(std::move(hostPtr), base::Bind(&base::DoNothing));
+    }
+
+    void Init(mojom::VideoHostPtr hostPtr, const InitCallback& callback) override {
+        ALOGV("Init");
+        mHostPtr = std::move(hostPtr);
+        // A method must be called while we are still in a Mojo thread so the
+        // proxy can perform lazy initialization and be able to be called from
+        // non-Mojo threads later.
+        // This also caches the version number so it can be obtained by calling
+        // .version().
+        mHostPtr.QueryVersion(base::Bind(
+            [](const InitCallback& callback, uint32_t version) {
+                ALOGI("VideoService ready (version=%d)", version);
+                callback.Run();
+            },
+            callback));
+        ALOGV("Init done");
+    }
+
+    // ArcService overrides:
+    void ready(mojom::ArcBridgeHostPtr* bridgeHost) override {
+        (*bridgeHost)->OnVideoInstanceReady(mBinding.CreateInterfacePtrAndBind());
+    }
+
+    void versionMismatch(uint32_t version) override {
+        ALOGE("ArcBridgeHost version %d, does not support video (version %d)\n", version,
+              kMinimumArcBridgeHostVersion);
+    }
+
+    // BnArcVideoBridge overrides:
+    MojoBootstrapResult bootstrapVideoAcceleratorFactory() override {
+        ALOGV("VideoService::bootstrapVideoAcceleratorFactory");
+
+        Future<MojoBootstrapResult> future;
+        mMojoProcessSupport->mojo_thread().getTaskRunner()->PostTask(
+                FROM_HERE, base::Bind(&VideoService::bootstrapVideoAcceleratorFactoryOnMojoThread,
+                                      base::Unretained(this), &future));
+        return future.get();
+    }
+
+    int32_t hostVersion() override {
+        ALOGV("VideoService::hostVersion");
+        return mHostPtr.version();
+    }
+
+private:
+    void bootstrapVideoAcceleratorFactoryOnMojoThread(Future<MojoBootstrapResult>* future) {
+        if (!mHostPtr) {
+            ALOGE("mHostPtr is not ready yet");
+            future->set(MojoBootstrapResult());
+            return;
+        }
+        mHostPtr->OnBootstrapVideoAcceleratorFactory(
+                base::Bind(&onCaptureResult, base::Unretained(future), mHostPtr.version()));
+    }
+
+    // Outlives VideoService.
+    MojoProcessSupport* const mMojoProcessSupport;
+    mojo::Binding<mojom::VideoInstance> mBinding;
+    mojom::VideoHostPtr mHostPtr;
+};
+
+}  // namespace arc
+
+namespace android {
+
+int register_android_server_ArcVideoService() {
+    defaultServiceManager()->addService(
+            String16("android.os.IArcVideoBridge"),
+            new arc::VideoService(arc::MojoProcessSupport::getLeakyInstance()));
+    return 0;
+}
+
+}  // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 071b6b8..07ddb05 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -52,6 +52,9 @@
 int register_android_server_GraphicsStatsService(JNIEnv* env);
 int register_android_hardware_display_DisplayViewport(JNIEnv* env);
 int register_android_server_net_NetworkStatsService(JNIEnv* env);
+#ifdef USE_ARC
+int register_android_server_ArcVideoService();
+#endif
 };
 
 using namespace android;
@@ -97,6 +100,8 @@
     register_android_server_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
     register_android_server_net_NetworkStatsService(env);
-
+#ifdef USE_ARC
+    register_android_server_ArcVideoService();
+#endif
     return JNI_VERSION_1_4;
 }