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 
ChannelParcelable(LocalHandle data_fd,LocalHandle pollin_event_fd,LocalHandle pollhup_event_fd)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 
IsValid() const23 bool ChannelParcelable::IsValid() const {
24   return !!data_fd_ && !!pollin_event_fd_ && !!pollhup_event_fd_;
25 }
26 
TakeChannelHandle()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 
writeToParcel(Parcel * parcel) const38 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 
readFromParcel(const Parcel * parcel)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