blob: f93cd905a58451e21140c637ea077f8e4ba3976f [file] [log] [blame]
/*
* 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 <components/arc/common/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