blob: e7bce270458c09bd88f001d65af18a307016da73 [file] [log] [blame]
#include "uds/channel_parcelable.h"
#include <binder/Parcel.h>
#include <uds/channel_manager.h>
namespace android {
namespace pdx {
namespace uds {
namespace {
static constexpr uint32_t kUdsMagicParcelHeader = 0x7564736d; // 'udsm'.
} // namespace
ChannelParcelable::ChannelParcelable(LocalHandle data_fd,
LocalHandle pollin_event_fd,
LocalHandle pollhup_event_fd)
: data_fd_{std::move(data_fd)},
pollin_event_fd_{std::move(pollin_event_fd)},
pollhup_event_fd_{std::move(pollhup_event_fd)} {}
bool ChannelParcelable::IsValid() const {
return !!data_fd_ && !!pollin_event_fd_ && !!pollhup_event_fd_;
}
LocalChannelHandle ChannelParcelable::TakeChannelHandle() {
if (!IsValid()) {
ALOGE("ChannelParcelable::TakeChannelHandle: Invalid channel parcel.");
return {}; // Returns an empty channel handle.
}
return ChannelManager::Get().CreateHandle(std::move(data_fd_),
std::move(pollin_event_fd_),
std::move(pollhup_event_fd_));
}
status_t ChannelParcelable::writeToParcel(Parcel* parcel) const {
status_t res = NO_ERROR;
if (!IsValid()) {
ALOGE("ChannelParcelable::writeToParcel: Invalid channel parcel.");
return BAD_VALUE;
}
res = parcel->writeUint32(kUdsMagicParcelHeader);
if (res != NO_ERROR) {
ALOGE("ChannelParcelable::writeToParcel: Cannot write magic: res=%d.", res);
return res;
}
res = parcel->writeFileDescriptor(data_fd_.Get());
if (res != NO_ERROR) {
ALOGE("ChannelParcelable::writeToParcel: Cannot write data fd: res=%d.",
res);
return res;
}
res = parcel->writeFileDescriptor(pollin_event_fd_.Get());
if (res != NO_ERROR) {
ALOGE(
"ChannelParcelable::writeToParcel: Cannot write pollin event fd: "
"res=%d.",
res);
return res;
}
res = parcel->writeFileDescriptor(pollhup_event_fd_.Get());
if (res != NO_ERROR) {
ALOGE(
"ChannelParcelable::writeToParcel: Cannot write pollhup event fd: "
"res=%d.",
res);
return res;
}
return res;
}
status_t ChannelParcelable::readFromParcel(const Parcel* parcel) {
uint32_t magic = 0;
status_t res = NO_ERROR;
if (IsValid()) {
ALOGE(
"ChannelParcelable::readFromParcel: This channel parcel is already "
"initailzied.");
return ALREADY_EXISTS;
}
res = parcel->readUint32(&magic);
if (res != NO_ERROR) {
ALOGE("ChannelParcelable::readFromParcel: Failed to read magic: res=%d.",
res);
return res;
}
if (magic != kUdsMagicParcelHeader) {
ALOGE(
"ChannelParcelable::readFromParcel: Unknown magic: 0x%x, epxected: "
"0x%x",
magic, kUdsMagicParcelHeader);
return BAD_VALUE;
}
// TODO(b/69010509): We have to dup() the FD from android::Parcel as it
// doesn't support taking out the FD's ownership. We can remove the dup() here
// once android::Parcel support such operation.
data_fd_.Reset(dup(parcel->readFileDescriptor()));
pollin_event_fd_.Reset(dup(parcel->readFileDescriptor()));
pollhup_event_fd_.Reset(dup(parcel->readFileDescriptor()));
if (!IsValid()) {
ALOGE(
"ChannelParcelable::readFromParcel: Cannot read fd from parcel: "
"data_fd=%d, pollin_event_fd=%d, pollhup_event_fd=%d.",
data_fd_.Get(), pollin_event_fd_.Get(), pollhup_event_fd_.Get());
return DEAD_OBJECT;
}
return res;
}
} // namespace uds
} // namespace pdx
} // namespace android