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 22#include <unordered_map> 23 24namespace android { 25namespace hardware { 26 27static 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); 56 if (err != NULL) { 57 str.append(1, ' ').append(err); 58 } 59 return str; 60} 61 62static 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), 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 80Status Status::ok() { 81 return Status(); 82} 83 84Status Status::fromExceptionCode(int32_t exceptionCode) { 85 return Status(exceptionCode, OK); 86} 87 88Status Status::fromExceptionCode(int32_t exceptionCode, 89 const char *message) { 90 return Status(exceptionCode, OK, message); 91} 92 93Status Status::fromStatusT(status_t status) { 94 Status ret; 95 ret.setFromStatusT(status); 96 return ret; 97} 98 99Status::Status(int32_t exceptionCode, int32_t errorCode) 100 : mException(exceptionCode), 101 mErrorCode(errorCode) {} 102 103Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message) 104 : mException(exceptionCode), 105 mErrorCode(errorCode), 106 mMessage(message) {} 107 108void Status::setException(int32_t ex, const char *message) { 109 mException = ex; 110 mErrorCode = NO_ERROR; // an exception, not a transaction failure. 111 mMessage = message; 112} 113 114void Status::setFromStatusT(status_t status) { 115 mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED; 116 mErrorCode = status; 117 mMessage.clear(); 118} 119 120std::string Status::description() const { 121 std::ostringstream oss; 122 oss << (*this); 123 return oss.str(); 124} 125 126std::ostream& operator<< (std::ostream& stream, const Status& s) { 127 if (s.exceptionCode() == Status::EX_NONE) { 128 stream << "No error"; 129 } else { 130 stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '"; 131 if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) { 132 stream << statusToString(s.transactionError()) << ": "; 133 } 134 stream << s.exceptionMessage() << "'"; 135 } 136 return stream; 137} 138 139namespace details { 140 void return_status::assertOk() const { 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 } 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 162} // namespace details 163 164} // namespace hardware 165} // namespace android 166