1 /*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ArcVideoService"
19
20 #include <binder/IPCThreadState.h>
21 #include <binder/IServiceManager.h>
22 #include <media/arcvideobridge/IArcVideoBridge.h>
23 #include <utils/Log.h>
24
25 #include <base/bind.h>
26 #include <base/bind_helpers.h>
27 #include <mojo/edk/embedder/embedder.h>
28 #include <mojo/public/cpp/bindings/binding.h>
29
30 #include <arc/ArcBridgeSupport.h>
31 #include <arc/ArcService.h>
32 #include <arc/Future.h>
33 #include <arc/IArcBridgeService.h>
34 #include <arc/MojoProcessSupport.h>
35 #include <components/arc/common/video.mojom.h>
36
37 namespace {
38
39 // [MinVersion] of OnVideoInstanceReady method in arc_bridge.mojom.
40 constexpr int kMinimumArcBridgeHostVersion = 6;
41
onCaptureResult(arc::Future<arc::MojoBootstrapResult> * future,uint32_t version,mojo::ScopedHandle handle,const std::string & token)42 void onCaptureResult(arc::Future<arc::MojoBootstrapResult>* future, uint32_t version,
43 mojo::ScopedHandle handle, const std::string& token) {
44 mojo::edk::ScopedPlatformHandle scoped_platform_handle;
45 MojoResult result =
46 mojo::edk::PassWrappedPlatformHandle(handle.release().value(), &scoped_platform_handle);
47 if (result != MOJO_RESULT_OK) {
48 ALOGE("Received invalid file descriptor.");
49 future->set(arc::MojoBootstrapResult());
50 return;
51 }
52
53 base::ScopedFD fd(scoped_platform_handle.release().handle);
54 future->set(arc::MojoBootstrapResult(std::move(fd), token, version));
55 }
56
57 } // namespace
58
59 namespace arc {
60
61 class VideoService : public mojom::VideoInstance,
62 public ArcService,
63 public android::BnArcVideoBridge {
64 public:
VideoService(MojoProcessSupport * mojoProcessSupport)65 explicit VideoService(MojoProcessSupport* mojoProcessSupport)
66 : mMojoProcessSupport(mojoProcessSupport), mBinding(this) {
67 mMojoProcessSupport->arc_bridge_support().requestArcBridgeProxyAsync(
68 this, kMinimumArcBridgeHostVersion);
69 }
70
~VideoService()71 ~VideoService() override { mMojoProcessSupport->disconnect(&mBinding, &mHostPtr); }
72
73 // VideoInstance overrides:
InitDeprecated(mojom::VideoHostPtr hostPtr)74 void InitDeprecated(mojom::VideoHostPtr hostPtr) override {
75 Init(std::move(hostPtr), base::Bind(&base::DoNothing));
76 }
77
Init(mojom::VideoHostPtr hostPtr,const InitCallback & callback)78 void Init(mojom::VideoHostPtr hostPtr, const InitCallback& callback) override {
79 ALOGV("Init");
80 mHostPtr = std::move(hostPtr);
81 // A method must be called while we are still in a Mojo thread so the
82 // proxy can perform lazy initialization and be able to be called from
83 // non-Mojo threads later.
84 // This also caches the version number so it can be obtained by calling
85 // .version().
86 mHostPtr.QueryVersion(base::Bind(
87 [](const InitCallback& callback, uint32_t version) {
88 ALOGI("VideoService ready (version=%d)", version);
89 callback.Run();
90 },
91 callback));
92 ALOGV("Init done");
93 }
94
95 // ArcService overrides:
ready(mojom::ArcBridgeHostPtr * bridgeHost)96 void ready(mojom::ArcBridgeHostPtr* bridgeHost) override {
97 (*bridgeHost)->OnVideoInstanceReady(mBinding.CreateInterfacePtrAndBind());
98 }
99
versionMismatch(uint32_t version)100 void versionMismatch(uint32_t version) override {
101 ALOGE("ArcBridgeHost version %d, does not support video (version %d)\n", version,
102 kMinimumArcBridgeHostVersion);
103 }
104
105 // BnArcVideoBridge overrides:
bootstrapVideoAcceleratorFactory()106 MojoBootstrapResult bootstrapVideoAcceleratorFactory() override {
107 ALOGV("VideoService::bootstrapVideoAcceleratorFactory");
108
109 Future<MojoBootstrapResult> future;
110 mMojoProcessSupport->mojo_thread().getTaskRunner()->PostTask(
111 FROM_HERE, base::Bind(&VideoService::bootstrapVideoAcceleratorFactoryOnMojoThread,
112 base::Unretained(this), &future));
113 return future.get();
114 }
115
hostVersion()116 int32_t hostVersion() override {
117 ALOGV("VideoService::hostVersion");
118 return mHostPtr.version();
119 }
120
121 private:
bootstrapVideoAcceleratorFactoryOnMojoThread(Future<MojoBootstrapResult> * future)122 void bootstrapVideoAcceleratorFactoryOnMojoThread(Future<MojoBootstrapResult>* future) {
123 if (!mHostPtr) {
124 ALOGE("mHostPtr is not ready yet");
125 future->set(MojoBootstrapResult());
126 return;
127 }
128 mHostPtr->OnBootstrapVideoAcceleratorFactory(
129 base::Bind(&onCaptureResult, base::Unretained(future), mHostPtr.version()));
130 }
131
132 // Outlives VideoService.
133 MojoProcessSupport* const mMojoProcessSupport;
134 mojo::Binding<mojom::VideoInstance> mBinding;
135 mojom::VideoHostPtr mHostPtr;
136 };
137
138 } // namespace arc
139
140 namespace android {
141
register_android_server_ArcVideoService()142 int register_android_server_ArcVideoService() {
143 defaultServiceManager()->addService(
144 String16("android.os.IArcVideoBridge"),
145 new arc::VideoService(arc::MojoProcessSupport::getLeakyInstance()));
146 return 0;
147 }
148
149 } // namespace android
150