Home | History | Annotate | Download | only in libpdx_uds
      1 #include "uds/channel_parcelable.h"
      2 
      3 #include <binder/Parcel.h>
      4 #include <uds/channel_manager.h>
      5 
      6 namespace android {
      7 namespace pdx {
      8 namespace uds {
      9 
     10 namespace {
     11 
     12 static constexpr uint32_t kUdsMagicParcelHeader = 0x7564736d;  // 'udsm'.
     13 
     14 }  // namespace
     15 
     16 ChannelParcelable::ChannelParcelable(LocalHandle data_fd,
     17                                      LocalHandle pollin_event_fd,
     18                                      LocalHandle pollhup_event_fd)
     19     : data_fd_{std::move(data_fd)},
     20       pollin_event_fd_{std::move(pollin_event_fd)},
     21       pollhup_event_fd_{std::move(pollhup_event_fd)} {}
     22 
     23 bool ChannelParcelable::IsValid() const {
     24   return !!data_fd_ && !!pollin_event_fd_ && !!pollhup_event_fd_;
     25 }
     26 
     27 LocalChannelHandle ChannelParcelable::TakeChannelHandle() {
     28   if (!IsValid()) {
     29     ALOGE("ChannelParcelable::TakeChannelHandle: Invalid channel parcel.");
     30     return {};  // Returns an empty channel handle.
     31   }
     32 
     33   return ChannelManager::Get().CreateHandle(std::move(data_fd_),
     34                                             std::move(pollin_event_fd_),
     35                                             std::move(pollhup_event_fd_));
     36 }
     37 
     38 status_t ChannelParcelable::writeToParcel(Parcel* parcel) const {
     39   status_t res = OK;
     40 
     41   if (!IsValid()) {
     42     ALOGE("ChannelParcelable::writeToParcel: Invalid channel parcel.");
     43     return BAD_VALUE;
     44   }
     45 
     46   res = parcel->writeUint32(kUdsMagicParcelHeader);
     47   if (res != OK) {
     48     ALOGE("ChannelParcelable::writeToParcel: Cannot write magic: res=%d.", res);
     49     return res;
     50   }
     51 
     52   res = parcel->writeFileDescriptor(data_fd_.Get());
     53   if (res != OK) {
     54     ALOGE("ChannelParcelable::writeToParcel: Cannot write data fd: res=%d.",
     55           res);
     56     return res;
     57   }
     58 
     59   res = parcel->writeFileDescriptor(pollin_event_fd_.Get());
     60   if (res != OK) {
     61     ALOGE(
     62         "ChannelParcelable::writeToParcel: Cannot write pollin event fd: "
     63         "res=%d.",
     64         res);
     65     return res;
     66   }
     67 
     68   res = parcel->writeFileDescriptor(pollhup_event_fd_.Get());
     69   if (res != OK) {
     70     ALOGE(
     71         "ChannelParcelable::writeToParcel: Cannot write pollhup event fd: "
     72         "res=%d.",
     73         res);
     74     return res;
     75   }
     76 
     77   return res;
     78 }
     79 
     80 status_t ChannelParcelable::readFromParcel(const Parcel* parcel) {
     81   uint32_t magic = 0;
     82   status_t res = OK;
     83 
     84   if (IsValid()) {
     85     ALOGE(
     86         "ChannelParcelable::readFromParcel: This channel parcel is already "
     87         "initailzied.");
     88     return ALREADY_EXISTS;
     89   }
     90 
     91   res = parcel->readUint32(&magic);
     92   if (res != OK) {
     93     ALOGE("ChannelParcelable::readFromParcel: Failed to read magic: res=%d.",
     94           res);
     95     return res;
     96   }
     97 
     98   if (magic != kUdsMagicParcelHeader) {
     99     ALOGE(
    100         "ChannelParcelable::readFromParcel: Unknown magic: 0x%x, epxected: "
    101         "0x%x",
    102         magic, kUdsMagicParcelHeader);
    103     return BAD_VALUE;
    104   }
    105 
    106   // TODO(b/69010509): We have to dup() the FD from android::Parcel as it
    107   // doesn't support taking out the FD's ownership. We can remove the dup() here
    108   // once android::Parcel support such operation.
    109   data_fd_.Reset(dup(parcel->readFileDescriptor()));
    110   pollin_event_fd_.Reset(dup(parcel->readFileDescriptor()));
    111   pollhup_event_fd_.Reset(dup(parcel->readFileDescriptor()));
    112   if (!IsValid()) {
    113     ALOGE(
    114         "ChannelParcelable::readFromParcel: Cannot read fd from parcel: "
    115         "data_fd=%d, pollin_event_fd=%d, pollhup_event_fd=%d.",
    116         data_fd_.Get(), pollin_event_fd_.Get(), pollhup_event_fd_.Get());
    117     return DEAD_OBJECT;
    118   }
    119 
    120   return res;
    121 }
    122 
    123 }  // namespace uds
    124 }  // namespace pdx
    125 }  // namespace android
    126