blob: 63b7a8c31f7409a0f3aa525f98315cdd2ca38751 [file] [log] [blame]
/*
* Copyright (C) 2008 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.
*/
/*
* Implementation of the user-space ashmem API for devices, which have our
* ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version,
* used by the simulator.
*/
#include "IPCSerializer.h"
#include "../Buffering/IPCBuffer.h"
#include "../IPCByteArray.h"
#include "../IPCCheck.h"
#include "../IPCString.h"
#include "../IPCType.h"
#include <sstream>
#include <stdlib.h>
#include <string>
#include <vector>
namespace {
class IPCSerializerImpl : public IPCSerializer {
public:
void setMsg(uint32_t msg) override;
void add(int32_t) override;
void add(int64_t) override;
void add(float) override;
void add(double) override;
void add(const uint16_t* data, size_t len) override;
void addJSON(const uint16_t* data, size_t len) override;
void add(const char* data, size_t len) override;
void add(const IPCByteArray* bytes) override;
void addJSUndefined() override;
void addVoid() override;
std::unique_ptr<IPCBuffer> finish() override;
private:
uint32_t m_msg{ MSG_END };
std::vector<uint32_t> m_types;
std::vector<std::unique_ptr<char[]>> m_datas;
};
class StringBasedIPCBufferImpl : public IPCBuffer {
public:
explicit StringBasedIPCBufferImpl(std::string&& s);
const void* get() override;
size_t length() override;
private:
std::string m_str;
};
void IPCSerializerImpl::setMsg(uint32_t msg)
{
m_msg = msg;
}
void IPCSerializerImpl::add(int32_t n)
{
std::unique_ptr<char[]> buffer(new char[sizeof(n)]);
*reinterpret_cast<int32_t*>(buffer.get()) = n;
m_types.emplace_back(static_cast<uint32_t>(IPCType::INT32));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::add(int64_t n)
{
std::unique_ptr<char[]> buffer(new char[sizeof(n)]);
*reinterpret_cast<int64_t*>(buffer.get()) = n;
m_types.emplace_back(static_cast<uint32_t>(IPCType::INT64));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::add(float n)
{
std::unique_ptr<char[]> buffer(new char[sizeof(n)]);
*reinterpret_cast<float*>(buffer.get()) = n;
m_types.emplace_back(static_cast<uint32_t>(IPCType::FLOAT));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::add(double n)
{
std::unique_ptr<char[]> buffer(new char[sizeof(n)]);
*reinterpret_cast<double*>(buffer.get()) = n;
m_types.emplace_back(static_cast<uint32_t>(IPCType::DOUBLE));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::add(const uint16_t* data, size_t len)
{
size_t byteLength = len * sizeof(uint16_t);
std::unique_ptr<char[]> buffer(new char[byteLength + sizeof(IPCString)]);
IPCString* s = reinterpret_cast<IPCString*>(buffer.get());
s->length = len;
memcpy(s->content, data, byteLength);
m_types.emplace_back(static_cast<uint32_t>(IPCType::STRING));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::addJSON(const uint16_t* data, size_t len)
{
size_t byteLength = len * sizeof(uint16_t);
std::unique_ptr<char[]> buffer(new char[byteLength + sizeof(IPCString)]);
IPCString* s = reinterpret_cast<IPCString*>(buffer.get());
s->length = len;
memcpy(s->content, data, byteLength);
m_types.emplace_back(static_cast<uint32_t>(IPCType::JSONSTRING));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::add(const char* data, size_t len)
{
size_t byteLength = len;
std::unique_ptr<char[]> buffer(new char[byteLength + sizeof(IPCByteArray)]);
IPCByteArray* s = reinterpret_cast<IPCByteArray*>(buffer.get());
s->length = len;
memcpy(s->content, data, byteLength);
s->content[byteLength] = '\0';
m_types.emplace_back(static_cast<uint32_t>(IPCType::BYTEARRAY));
m_datas.emplace_back(std::move(buffer));
}
void IPCSerializerImpl::add(const IPCByteArray* bytes) {
m_types.emplace_back(static_cast<uint32_t>(IPCType::BYTEARRAY));
// m_datas.emplace_back(std::move((std::unique_ptr<char[]>)bytes));
}
void IPCSerializerImpl::addJSUndefined()
{
m_types.emplace_back(static_cast<uint32_t>(IPCType::JSUNDEFINED));
m_datas.emplace_back();
}
void IPCSerializerImpl::addVoid()
{
m_types.emplace_back(static_cast<uint32_t>(IPCType::VOID));
m_datas.emplace_back();
}
std::unique_ptr<IPCBuffer> IPCSerializerImpl::finish()
{
IPC_DCHECK(m_types.size() > 0);
IPC_DCHECK(m_msg != MSG_NOT_SET);
std::ostringstream oss;
oss.write(reinterpret_cast<const char*>(&m_msg), sizeof(m_msg));
for (auto& type : m_types) {
oss.write(reinterpret_cast<const char*>(&type), sizeof(type));
}
uint32_t endOfType = static_cast<uint32_t>(IPCType::END);
oss.write(reinterpret_cast<const char*>(&endOfType), sizeof(endOfType));
int i = 0;
for (auto& data : m_datas) {
switch (static_cast<IPCType>(m_types[i])) {
case IPCType::INT32: {
oss.write(data.get(), sizeof(int32_t));
} break;
case IPCType::INT64: {
oss.write(data.get(), sizeof(int64_t));
} break;
case IPCType::FLOAT: {
oss.write(data.get(), sizeof(float));
} break;
case IPCType::DOUBLE: {
oss.write(data.get(), sizeof(double));
} break;
case IPCType::BYTEARRAY: {
IPCByteArray* a = reinterpret_cast<IPCByteArray*>(data.get());
size_t byteLength = a->length;
oss.write(reinterpret_cast<const char*>(&a->length), sizeof(a->length));
oss.write(reinterpret_cast<const char*>(a->content), byteLength);
} break;
case IPCType::JSONSTRING:
case IPCType::STRING: {
IPCString* s = reinterpret_cast<IPCString*>(data.get());
size_t byteLength = s->length * sizeof(uint16_t);
oss.write(reinterpret_cast<const char*>(&s->length), sizeof(s->length));
oss.write(reinterpret_cast<const char*>(s->content), byteLength);
} break;
case IPCType::JSUNDEFINED:
case IPCType::VOID:
break;
default:
IPC_UNREACHABLE();
}
++i;
}
m_types.clear();
m_datas.clear();
m_msg = MSG_NOT_SET;
std::unique_ptr<StringBasedIPCBufferImpl> bufferReturn(new StringBasedIPCBufferImpl(std::move(oss.str())));
return std::unique_ptr<IPCBuffer>(bufferReturn.release());
}
StringBasedIPCBufferImpl::StringBasedIPCBufferImpl(std::string&& s)
: m_str(std::move(s))
{
}
const void* StringBasedIPCBufferImpl::get()
{
return m_str.data();
}
size_t StringBasedIPCBufferImpl::length()
{
return m_str.length();
}
}
std::unique_ptr<IPCSerializer> createIPCSerializer()
{
return std::unique_ptr<IPCSerializer>(new IPCSerializerImpl);
}