• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 "HidlStatus"
18 #include <android-base/logging.h>
19 
20 #include <hidl/Status.h>
21 #include <utils/CallStack.h>
22 
23 #include <unordered_map>
24 
25 namespace android {
26 namespace hardware {
27 
statusToString(status_t s)28 static std::string statusToString(status_t s) {
29     const std::unordered_map<status_t, std::string> statusStrings{{
30         #define STATUS_TO_STRING_PAIR(STATUS) {STATUS, #STATUS}
31         STATUS_TO_STRING_PAIR(OK),
32         STATUS_TO_STRING_PAIR(UNKNOWN_ERROR),
33         STATUS_TO_STRING_PAIR(NO_MEMORY),
34         STATUS_TO_STRING_PAIR(INVALID_OPERATION),
35         STATUS_TO_STRING_PAIR(BAD_VALUE),
36         STATUS_TO_STRING_PAIR(BAD_TYPE),
37         STATUS_TO_STRING_PAIR(NAME_NOT_FOUND),
38         STATUS_TO_STRING_PAIR(PERMISSION_DENIED),
39         STATUS_TO_STRING_PAIR(NO_INIT),
40         STATUS_TO_STRING_PAIR(ALREADY_EXISTS),
41         STATUS_TO_STRING_PAIR(DEAD_OBJECT),
42         STATUS_TO_STRING_PAIR(FAILED_TRANSACTION),
43         STATUS_TO_STRING_PAIR(BAD_INDEX),
44         STATUS_TO_STRING_PAIR(NOT_ENOUGH_DATA),
45         STATUS_TO_STRING_PAIR(WOULD_BLOCK),
46         STATUS_TO_STRING_PAIR(TIMED_OUT),
47         STATUS_TO_STRING_PAIR(UNKNOWN_TRANSACTION),
48         STATUS_TO_STRING_PAIR(FDS_NOT_ALLOWED),
49         STATUS_TO_STRING_PAIR(UNEXPECTED_NULL)
50     }};
51     auto it = statusStrings.find(s);
52     if (it != statusStrings.end()) {
53         return it->second;
54     }
55     std::string str = std::to_string(s);
56     char *err = strerror(-s);
57     if (err != nullptr) {
58         str.append(1, ' ').append(err);
59     }
60     return str;
61 }
62 
exceptionToString(int32_t ex)63 static std::string exceptionToString(int32_t ex) {
64     const std::unordered_map<int32_t, std::string> exceptionStrings{{
65         #define EXCEPTION_TO_STRING_PAIR(EXCEPTION) {Status::Exception::EXCEPTION, #EXCEPTION}
66         EXCEPTION_TO_STRING_PAIR(EX_NONE),
67         EXCEPTION_TO_STRING_PAIR(EX_SECURITY),
68         EXCEPTION_TO_STRING_PAIR(EX_BAD_PARCELABLE),
69         EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_ARGUMENT),
70         EXCEPTION_TO_STRING_PAIR(EX_NULL_POINTER),
71         EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_STATE),
72         EXCEPTION_TO_STRING_PAIR(EX_NETWORK_MAIN_THREAD),
73         EXCEPTION_TO_STRING_PAIR(EX_UNSUPPORTED_OPERATION),
74         EXCEPTION_TO_STRING_PAIR(EX_HAS_REPLY_HEADER),
75         EXCEPTION_TO_STRING_PAIR(EX_TRANSACTION_FAILED)
76     }};
77     auto it = exceptionStrings.find(ex);
78     return it == exceptionStrings.end() ? std::to_string(ex) : it->second;
79 }
80 
ok()81 Status Status::ok() {
82     return Status();
83 }
84 
fromExceptionCode(int32_t exceptionCode)85 Status Status::fromExceptionCode(int32_t exceptionCode) {
86     if (exceptionCode == EX_TRANSACTION_FAILED) {
87         return Status(exceptionCode, FAILED_TRANSACTION);
88     }
89     return Status(exceptionCode, OK);
90 }
91 
fromExceptionCode(int32_t exceptionCode,const char * message)92 Status Status::fromExceptionCode(int32_t exceptionCode,
93                                  const char *message) {
94     if (exceptionCode == EX_TRANSACTION_FAILED) {
95         return Status(exceptionCode, FAILED_TRANSACTION, message);
96     }
97     return Status(exceptionCode, OK, message);
98 }
99 
fromStatusT(status_t status)100 Status Status::fromStatusT(status_t status) {
101     Status ret;
102     ret.setFromStatusT(status);
103     return ret;
104 }
105 
Status(int32_t exceptionCode,int32_t errorCode)106 Status::Status(int32_t exceptionCode, int32_t errorCode)
107     : mException(exceptionCode),
108       mErrorCode(errorCode) {}
109 
Status(int32_t exceptionCode,int32_t errorCode,const char * message)110 Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message)
111     : mException(exceptionCode),
112       mErrorCode(errorCode),
113       mMessage(message) {}
114 
setException(int32_t ex,const char * message)115 void Status::setException(int32_t ex, const char *message) {
116     mException = ex;
117     mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
118     mMessage = message;
119 }
120 
setFromStatusT(status_t status)121 void Status::setFromStatusT(status_t status) {
122     mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
123     mErrorCode = status;
124     mMessage.clear();
125 }
126 
description() const127 std::string Status::description() const {
128     std::ostringstream oss;
129     oss << (*this);
130     return oss.str();
131 }
132 
operator <<(std::ostream & stream,const Status & s)133 std::ostream& operator<< (std::ostream& stream, const Status& s) {
134     if (s.exceptionCode() == Status::EX_NONE) {
135         stream << "No error";
136     } else {
137         stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '";
138         if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
139             stream << statusToString(s.transactionError()) << ": ";
140         }
141         stream << s.exceptionMessage() << "'";
142     }
143     return stream;
144 }
145 
146 static HidlReturnRestriction gReturnRestriction = HidlReturnRestriction::NONE;
setProcessHidlReturnRestriction(HidlReturnRestriction restriction)147 void setProcessHidlReturnRestriction(HidlReturnRestriction restriction) {
148     gReturnRestriction = restriction;
149 }
150 
151 namespace details {
assertOk() const152     void return_status::assertOk() const {
153         if (!isOk()) {
154             LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description();
155         }
156     }
157 
~return_status()158     return_status::~return_status() {
159         // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
160         if (mCheckedStatus) return;
161 
162         if (!isOk()) {
163             LOG(FATAL) << "Failed HIDL return status not checked: " << description();
164         }
165 
166         if (gReturnRestriction == HidlReturnRestriction::NONE) {
167             return;
168         }
169 
170         if (gReturnRestriction == HidlReturnRestriction::ERROR_IF_UNCHECKED) {
171             LOG(ERROR) << "Failed to check status of HIDL Return.";
172             CallStack::logStack("unchecked HIDL return", CallStack::getCurrent(10).get(), ANDROID_LOG_ERROR);
173         } else {
174             LOG(FATAL) << "Failed to check status of HIDL Return.";
175         }
176     }
177 
operator =(return_status && other)178     return_status& return_status::operator=(return_status&& other) noexcept {
179         if (!mCheckedStatus && !isOk()) {
180             LOG(FATAL) << "Failed HIDL return status not checked: " << description();
181         }
182         std::swap(mStatus, other.mStatus);
183         std::swap(mCheckedStatus, other.mCheckedStatus);
184         return *this;
185     }
186 
187 }  // namespace details
188 
189 }  // namespace hardware
190 }  // namespace android
191