You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
11 KiB
368 lines
11 KiB
/*
|
|
* Copyright (c) 2009 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 "IOMXStore"
|
|
|
|
#include <utils/Log.h>
|
|
|
|
#include <media/IOMX.h>
|
|
#include <media/IOMXStore.h>
|
|
#include <android/hardware/media/omx/1.0/IOmxStore.h>
|
|
|
|
#include <binder/IInterface.h>
|
|
#include <binder/IBinder.h>
|
|
#include <binder/Parcel.h>
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
namespace android {
|
|
|
|
namespace {
|
|
|
|
enum {
|
|
CONNECT = IBinder::FIRST_CALL_TRANSACTION,
|
|
LIST_SERVICE_ATTRIBUTES,
|
|
GET_NODE_PREFIX,
|
|
LIST_ROLES,
|
|
GET_OMX,
|
|
};
|
|
|
|
// Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
|
|
// depend on writeToParcel() and readToParcel() for T <-> Parcel.
|
|
|
|
template <typename T>
|
|
status_t writeToParcel(const std::vector<T>& v, Parcel* p);
|
|
|
|
template <typename T>
|
|
status_t readFromParcel(std::vector<T>* v, const Parcel& p);
|
|
|
|
// std::string <-> Parcel
|
|
|
|
status_t writeToParcel(const std::string& s, Parcel* p) {
|
|
if (s.size() > INT32_MAX) {
|
|
return BAD_VALUE;
|
|
}
|
|
return p->writeByteArray(
|
|
s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
|
|
}
|
|
|
|
status_t readFromParcel(std::string* s, const Parcel& p) {
|
|
int32_t len;
|
|
status_t status = p.readInt32(&len);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
} else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
|
|
return BAD_VALUE;
|
|
}
|
|
s->resize(len);
|
|
if (len == 0) {
|
|
return NO_ERROR;
|
|
}
|
|
return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
|
|
}
|
|
|
|
// IOMXStore::Attribute <-> Parcel
|
|
|
|
status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
|
|
status_t status = writeToParcel(a.key, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return writeToParcel(a.value, p);
|
|
}
|
|
|
|
status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
|
|
status_t status = readFromParcel(&(a->key), p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return readFromParcel(&(a->value), p);
|
|
}
|
|
|
|
// IOMXStore::NodeInfo <-> Parcel
|
|
|
|
status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
|
|
status_t status = writeToParcel(n.name, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = writeToParcel(n.owner, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return writeToParcel(n.attributes, p);
|
|
}
|
|
|
|
status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
|
|
status_t status = readFromParcel(&(n->name), p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = readFromParcel(&(n->owner), p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return readFromParcel(&(n->attributes), p);
|
|
}
|
|
|
|
// IOMXStore::RoleInfo <-> Parcel
|
|
|
|
status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
|
|
status_t status = writeToParcel(r.role, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = writeToParcel(r.type, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = p->writeBool(r.isEncoder);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = p->writeBool(r.preferPlatformNodes);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return writeToParcel(r.nodes, p);
|
|
}
|
|
|
|
status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
|
|
status_t status = readFromParcel(&(r->role), p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = readFromParcel(&(r->type), p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = p.readBool(&(r->isEncoder));
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = p.readBool(&(r->preferPlatformNodes));
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return readFromParcel(&(r->nodes), p);
|
|
}
|
|
|
|
// std::vector<NodeInfo> <-> Parcel
|
|
// std::vector<RoleInfo> <-> Parcel
|
|
|
|
template <typename T>
|
|
status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
|
|
status_t status = p->writeVectorSize(v);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
for (const T& x : v) {
|
|
status = writeToParcel(x, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
template <typename T>
|
|
status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
|
|
status_t status = p.resizeOutVector(v);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
for (T& x : *v) {
|
|
status = readFromParcel(&x, p);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
} // unnamed namespace
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class BpOMXStore : public BpInterface<IOMXStore> {
|
|
public:
|
|
explicit BpOMXStore(const sp<IBinder> &impl)
|
|
: BpInterface<IOMXStore>(impl) {
|
|
}
|
|
|
|
status_t listServiceAttributes(
|
|
std::vector<Attribute>* attributes) override {
|
|
Parcel data, reply;
|
|
status_t status;
|
|
status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return readFromParcel(attributes, reply);
|
|
}
|
|
|
|
status_t getNodePrefix(std::string* prefix) override {
|
|
Parcel data, reply;
|
|
status_t status;
|
|
status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = remote()->transact(GET_NODE_PREFIX, data, &reply);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return readFromParcel(prefix, reply);
|
|
}
|
|
|
|
status_t listRoles(std::vector<RoleInfo>* roleList) override {
|
|
Parcel data, reply;
|
|
status_t status;
|
|
status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = remote()->transact(LIST_ROLES, data, &reply);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return readFromParcel(roleList, reply);
|
|
}
|
|
|
|
status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
|
|
Parcel data, reply;
|
|
status_t status;
|
|
status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = writeToParcel(name, &data);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
status = remote()->transact(GET_OMX, data, &reply);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
return reply.readStrongBinder(omx);
|
|
}
|
|
|
|
};
|
|
|
|
IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define CHECK_OMX_INTERFACE(interface, data, reply) \
|
|
do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
|
|
ALOGW("Call incorrectly routed to " #interface); \
|
|
return PERMISSION_DENIED; \
|
|
} } while (0)
|
|
|
|
status_t BnOMXStore::onTransact(
|
|
uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
|
|
switch (code) {
|
|
case LIST_SERVICE_ATTRIBUTES: {
|
|
CHECK_OMX_INTERFACE(IOMXStore, data, reply);
|
|
status_t status;
|
|
std::vector<Attribute> attributes;
|
|
|
|
status = listServiceAttributes(&attributes);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("listServiceAttributes() fails with status %d",
|
|
static_cast<int>(status));
|
|
return NO_ERROR;
|
|
}
|
|
status = writeToParcel(attributes, reply);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("listServiceAttributes() fails to send reply");
|
|
return NO_ERROR;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
case GET_NODE_PREFIX: {
|
|
CHECK_OMX_INTERFACE(IOMXStore, data, reply);
|
|
status_t status;
|
|
std::string prefix;
|
|
|
|
status = getNodePrefix(&prefix);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("getNodePrefix() fails with status %d",
|
|
static_cast<int>(status));
|
|
return NO_ERROR;
|
|
}
|
|
status = writeToParcel(prefix, reply);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("getNodePrefix() fails to send reply");
|
|
return NO_ERROR;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
case LIST_ROLES: {
|
|
CHECK_OMX_INTERFACE(IOMXStore, data, reply);
|
|
status_t status;
|
|
std::vector<RoleInfo> roleList;
|
|
|
|
status = listRoles(&roleList);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("listRoles() fails with status %d",
|
|
static_cast<int>(status));
|
|
return NO_ERROR;
|
|
}
|
|
status = writeToParcel(roleList, reply);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("listRoles() fails to send reply");
|
|
return NO_ERROR;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
case GET_OMX: {
|
|
CHECK_OMX_INTERFACE(IOMXStore, data, reply);
|
|
status_t status;
|
|
std::string name;
|
|
sp<IOMX> omx;
|
|
|
|
status = readFromParcel(&name, data);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("getOmx() fails to retrieve name");
|
|
return NO_ERROR;
|
|
}
|
|
status = getOmx(name, &omx);
|
|
if (status != NO_ERROR) {
|
|
ALOGE("getOmx() fails with status %d",
|
|
static_cast<int>(status));
|
|
return NO_ERROR;
|
|
}
|
|
status = reply->writeStrongBinder(IInterface::asBinder(omx));
|
|
if (status != NO_ERROR) {
|
|
ALOGE("getOmx() fails to send reply");
|
|
return NO_ERROR;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
default:
|
|
return BBinder::onTransact(code, data, reply, flags);
|
|
}
|
|
}
|
|
|
|
} // namespace android
|