blob: c2060187293f39f13c38c7954cc3661f503a0acc [file] [log] [blame]
Yifan Hong7f97f442016-11-14 18:31:05 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "HidlSupport"
18
19#include <hidl/HidlBinderSupport.h>
20
21#ifdef LIBHIDL_TARGET_DEBUGGABLE
22#include <android-base/logging.h>
23#endif
24
25namespace android {
26namespace hardware {
27
28std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap{};
29
30// static
31const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer);
32
33status_t readEmbeddedFromParcel(hidl_string * /* string */,
34 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
35 const void *ptr = parcel.readEmbeddedBuffer(
36 nullptr /* buffer_handle */,
37 parentHandle,
38 parentOffset + hidl_string::kOffsetOfBuffer);
39
40 return ptr != NULL ? OK : UNKNOWN_ERROR;
41}
42
43status_t writeEmbeddedToParcel(const hidl_string &string,
44 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
45 return parcel->writeEmbeddedBuffer(
46 string.c_str(),
47 string.size() + 1,
48 nullptr /* handle */,
49 parentHandle,
50 parentOffset + hidl_string::kOffsetOfBuffer);
51}
52
53android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) {
54 return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor());
55}
56
57hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
58 uint32_t version;
59 android::status_t status = parcel.readUint32(&version);
60 if (status != OK) {
61 return nullptr;
62 } else {
63 return new hidl_version(version >> 16, version & 0xFFFF);
64 }
65}
66
67status_t readFromParcel(Status *s, const Parcel& parcel) {
68 int32_t exception;
69 int32_t errorCode;
70 status_t status = parcel.readInt32(&exception);
71 if (status != OK) {
72 s->setFromStatusT(status);
73 return status;
74 }
75
76 // Skip over fat response headers. Not used (or propagated) in native code.
77 if (exception == Status::EX_HAS_REPLY_HEADER) {
78 // Note that the header size includes the 4 byte size field.
79 const int32_t header_start = parcel.dataPosition();
80 int32_t header_size;
81 status = parcel.readInt32(&header_size);
82 if (status != OK) {
83 s->setFromStatusT(status);
84 return status;
85 }
86 parcel.setDataPosition(header_start + header_size);
87 // And fat response headers are currently only used when there are no
88 // exceptions, so act like there was no error.
89 exception = Status::EX_NONE;
90 }
91
92 if (exception == Status::EX_NONE) {
93 *s = Status::ok();
94 return status;
95 }
96
97 // The remote threw an exception. Get the message back.
98 String16 message;
99 status = parcel.readString16(&message);
100 if (status != OK) {
101 s->setFromStatusT(status);
102 return status;
103 }
104
105 if (exception == Status::EX_SERVICE_SPECIFIC) {
106 status = parcel.readInt32(&errorCode);
107 }
108 if (status != OK) {
109 s->setFromStatusT(status);
110 return status;
111 }
112
113 if (exception == Status::EX_SERVICE_SPECIFIC) {
114 s->setServiceSpecificError(errorCode, String8(message));
115 } else {
116 s->setException(exception, String8(message));
117 }
118
119 return status;
120}
121
122status_t writeToParcel(const Status &s, Parcel* parcel) {
123 // Something really bad has happened, and we're not going to even
124 // try returning rich error data.
125 if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
126 return s.transactionError();
127 }
128
129 status_t status = parcel->writeInt32(s.exceptionCode());
130 if (status != OK) { return status; }
131 if (s.exceptionCode() == Status::EX_NONE) {
132 // We have no more information to write.
133 return status;
134 }
135 status = parcel->writeString16(String16(s.exceptionMessage()));
136 if (s.exceptionCode() != Status::EX_SERVICE_SPECIFIC) {
137 // We have no more information to write.
138 return status;
139 }
140 status = parcel->writeInt32(s.serviceSpecificErrorCode());
141 return status;
142}
143
144} // namespace hardware
145} // namespace android