| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 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 | */ | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 16 |  | 
| Steven Moreland | e780c45 | 2017-01-17 17:22:54 -0800 | [diff] [blame] | 17 | #define LOG_TAG "HidlStatus" | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 18 | #include <android-base/logging.h> | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 19 |  | 
|  | 20 | #include <hidl/Status.h> | 
|  | 21 |  | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 22 | #include <unordered_map> | 
| Steven Moreland | e780c45 | 2017-01-17 17:22:54 -0800 | [diff] [blame] | 23 |  | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 24 | namespace android { | 
|  | 25 | namespace hardware { | 
|  | 26 |  | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 27 | static std::string statusToString(status_t s) { | 
|  | 28 | const std::unordered_map<status_t, std::string> statusStrings{{ | 
|  | 29 | #define STATUS_TO_STRING_PAIR(STATUS) {STATUS, #STATUS} | 
|  | 30 | STATUS_TO_STRING_PAIR(OK), | 
|  | 31 | STATUS_TO_STRING_PAIR(UNKNOWN_ERROR), | 
|  | 32 | STATUS_TO_STRING_PAIR(NO_MEMORY), | 
|  | 33 | STATUS_TO_STRING_PAIR(INVALID_OPERATION), | 
|  | 34 | STATUS_TO_STRING_PAIR(BAD_VALUE), | 
|  | 35 | STATUS_TO_STRING_PAIR(BAD_TYPE), | 
|  | 36 | STATUS_TO_STRING_PAIR(NAME_NOT_FOUND), | 
|  | 37 | STATUS_TO_STRING_PAIR(PERMISSION_DENIED), | 
|  | 38 | STATUS_TO_STRING_PAIR(NO_INIT), | 
|  | 39 | STATUS_TO_STRING_PAIR(ALREADY_EXISTS), | 
|  | 40 | STATUS_TO_STRING_PAIR(DEAD_OBJECT), | 
|  | 41 | STATUS_TO_STRING_PAIR(FAILED_TRANSACTION), | 
|  | 42 | STATUS_TO_STRING_PAIR(BAD_INDEX), | 
|  | 43 | STATUS_TO_STRING_PAIR(NOT_ENOUGH_DATA), | 
|  | 44 | STATUS_TO_STRING_PAIR(WOULD_BLOCK), | 
|  | 45 | STATUS_TO_STRING_PAIR(TIMED_OUT), | 
|  | 46 | STATUS_TO_STRING_PAIR(UNKNOWN_TRANSACTION), | 
|  | 47 | STATUS_TO_STRING_PAIR(FDS_NOT_ALLOWED), | 
|  | 48 | STATUS_TO_STRING_PAIR(UNEXPECTED_NULL) | 
|  | 49 | }}; | 
|  | 50 | auto it = statusStrings.find(s); | 
|  | 51 | if (it != statusStrings.end()) { | 
|  | 52 | return it->second; | 
|  | 53 | } | 
|  | 54 | std::string str = std::to_string(s); | 
|  | 55 | char *err = strerror(-s); | 
| Stephen Hines | fd9ecee | 2017-09-27 18:52:52 -0700 | [diff] [blame] | 56 | if (err != nullptr) { | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 57 | str.append(1, ' ').append(err); | 
|  | 58 | } | 
|  | 59 | return str; | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | static std::string exceptionToString(int32_t ex) { | 
|  | 63 | const std::unordered_map<int32_t, std::string> exceptionStrings{{ | 
|  | 64 | #define EXCEPTION_TO_STRING_PAIR(EXCEPTION) {Status::Exception::EXCEPTION, #EXCEPTION} | 
|  | 65 | EXCEPTION_TO_STRING_PAIR(EX_NONE), | 
|  | 66 | EXCEPTION_TO_STRING_PAIR(EX_SECURITY), | 
|  | 67 | EXCEPTION_TO_STRING_PAIR(EX_BAD_PARCELABLE), | 
|  | 68 | EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_ARGUMENT), | 
|  | 69 | EXCEPTION_TO_STRING_PAIR(EX_NULL_POINTER), | 
|  | 70 | EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_STATE), | 
|  | 71 | EXCEPTION_TO_STRING_PAIR(EX_NETWORK_MAIN_THREAD), | 
|  | 72 | EXCEPTION_TO_STRING_PAIR(EX_UNSUPPORTED_OPERATION), | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 73 | EXCEPTION_TO_STRING_PAIR(EX_HAS_REPLY_HEADER), | 
|  | 74 | EXCEPTION_TO_STRING_PAIR(EX_TRANSACTION_FAILED) | 
|  | 75 | }}; | 
|  | 76 | auto it = exceptionStrings.find(ex); | 
|  | 77 | return it == exceptionStrings.end() ? std::to_string(ex) : it->second; | 
|  | 78 | } | 
|  | 79 |  | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 80 | Status Status::ok() { | 
|  | 81 | return Status(); | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | Status Status::fromExceptionCode(int32_t exceptionCode) { | 
|  | 85 | return Status(exceptionCode, OK); | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | Status Status::fromExceptionCode(int32_t exceptionCode, | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 89 | const char *message) { | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 90 | return Status(exceptionCode, OK, message); | 
|  | 91 | } | 
|  | 92 |  | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 93 | Status Status::fromStatusT(status_t status) { | 
|  | 94 | Status ret; | 
|  | 95 | ret.setFromStatusT(status); | 
|  | 96 | return ret; | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | Status::Status(int32_t exceptionCode, int32_t errorCode) | 
|  | 100 | : mException(exceptionCode), | 
|  | 101 | mErrorCode(errorCode) {} | 
|  | 102 |  | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 103 | Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message) | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 104 | : mException(exceptionCode), | 
|  | 105 | mErrorCode(errorCode), | 
|  | 106 | mMessage(message) {} | 
|  | 107 |  | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 108 | void Status::setException(int32_t ex, const char *message) { | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 109 | mException = ex; | 
|  | 110 | mErrorCode = NO_ERROR;  // an exception, not a transaction failure. | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 111 | mMessage = message; | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 112 | } | 
|  | 113 |  | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 114 | void Status::setFromStatusT(status_t status) { | 
|  | 115 | mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED; | 
|  | 116 | mErrorCode = status; | 
|  | 117 | mMessage.clear(); | 
|  | 118 | } | 
|  | 119 |  | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 120 | std::string Status::description() const { | 
|  | 121 | std::ostringstream oss; | 
|  | 122 | oss << (*this); | 
|  | 123 | return oss.str(); | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 124 | } | 
|  | 125 |  | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 126 | std::ostream& operator<< (std::ostream& stream, const Status& s) { | 
|  | 127 | if (s.exceptionCode() == Status::EX_NONE) { | 
|  | 128 | stream << "No error"; | 
|  | 129 | } else { | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 130 | stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '"; | 
| Steven Moreland | 72db40f | 2017-03-09 18:15:27 -0800 | [diff] [blame] | 131 | if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) { | 
| Yifan Hong | 2be9418 | 2017-03-03 19:07:38 -0800 | [diff] [blame] | 132 | stream << statusToString(s.transactionError()) << ": "; | 
| Yifan Hong | 43298f9 | 2016-12-20 16:42:39 -0800 | [diff] [blame] | 133 | } | 
|  | 134 | stream << s.exceptionMessage() << "'"; | 
|  | 135 | } | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 136 | return stream; | 
|  | 137 | } | 
|  | 138 |  | 
| Steven Moreland | e780c45 | 2017-01-17 17:22:54 -0800 | [diff] [blame] | 139 | namespace details { | 
| Yifan Hong | af4e43c | 2017-03-03 19:10:52 -0800 | [diff] [blame] | 140 | void return_status::assertOk() const { | 
| Steven Moreland | e780c45 | 2017-01-17 17:22:54 -0800 | [diff] [blame] | 141 | if (!isOk()) { | 
|  | 142 | LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description(); | 
|  | 143 | } | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | return_status::~return_status() { | 
|  | 147 | // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus | 
|  | 148 | if (!mCheckedStatus && !isOk()) { | 
|  | 149 | LOG(FATAL) << "Failed HIDL return status not checked: " << description(); | 
|  | 150 | } | 
|  | 151 | } | 
| Yifan Hong | af4e43c | 2017-03-03 19:10:52 -0800 | [diff] [blame] | 152 |  | 
|  | 153 | return_status &return_status::operator=(return_status &&other) { | 
|  | 154 | if (!mCheckedStatus && !isOk()) { | 
|  | 155 | LOG(FATAL) << "Failed HIDL return status not checked: " << description(); | 
|  | 156 | } | 
|  | 157 | std::swap(mStatus, other.mStatus); | 
|  | 158 | std::swap(mCheckedStatus, other.mCheckedStatus); | 
|  | 159 | return *this; | 
|  | 160 | } | 
|  | 161 |  | 
| Steven Moreland | e780c45 | 2017-01-17 17:22:54 -0800 | [diff] [blame] | 162 | }  // namespace details | 
|  | 163 |  | 
| Martijn Coenen | bb5e9bb | 2016-09-01 01:36:18 +0200 | [diff] [blame] | 164 | }  // namespace hardware | 
|  | 165 | }  // namespace android |