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 28 29 static std::string exceptionToString(int32_t ex) { 30 #define EXCEPTION_CASE(EXCEPTION) \ 31 case Status::Exception::EXCEPTION: \ 32 return #EXCEPTION 33 34 switch (ex) { 35 EXCEPTION_CASE(EX_NONE); 36 EXCEPTION_CASE(EX_SECURITY); 37 EXCEPTION_CASE(EX_BAD_PARCELABLE); 38 EXCEPTION_CASE(EX_ILLEGAL_ARGUMENT); 39 EXCEPTION_CASE(EX_NULL_POINTER); 40 EXCEPTION_CASE(EX_ILLEGAL_STATE); 41 EXCEPTION_CASE(EX_NETWORK_MAIN_THREAD); 42 EXCEPTION_CASE(EX_UNSUPPORTED_OPERATION); 43 EXCEPTION_CASE(EX_HAS_REPLY_HEADER); 44 EXCEPTION_CASE(EX_TRANSACTION_FAILED); 45 #undef EXCEPTION_CASE 46 } 47 return std::to_string(ex); 48 } 49 50 Status Status::ok() { 51 return Status(); 52 } 53 54 Status Status::fromExceptionCode(int32_t exceptionCode) { 55 if (exceptionCode == EX_TRANSACTION_FAILED) { 56 return Status(exceptionCode, FAILED_TRANSACTION); 57 } 58 return Status(exceptionCode, OK); 59 } 60 61 Status Status::fromExceptionCode(int32_t exceptionCode, 62 const char *message) { 63 if (exceptionCode == EX_TRANSACTION_FAILED) { 64 return Status(exceptionCode, FAILED_TRANSACTION, message); 65 } 66 return Status(exceptionCode, OK, message); 67 } 68 69 Status Status::fromStatusT(status_t status) { 70 Status ret; 71 ret.setFromStatusT(status); 72 return ret; 73 } 74 75 Status::Status(int32_t exceptionCode, int32_t errorCode) 76 : mException(exceptionCode), 77 mErrorCode(errorCode) {} 78 79 Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message) 80 : mException(exceptionCode), 81 mErrorCode(errorCode), 82 mMessage(message) {} 83 84 void Status::setException(int32_t ex, const char *message) { 85 mException = ex; 86 mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR; 87 mMessage = message; 88 } 89 90 void Status::setFromStatusT(status_t status) { 91 mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED; 92 mErrorCode = status; 93 mMessage.clear(); 94 } 95 96 std::string Status::description() const { 97 std::ostringstream oss; 98 oss << (*this); 99 return oss.str(); 100 } 101 102 std::ostream& operator<< (std::ostream& stream, const Status& s) { 103 if (s.exceptionCode() == Status::EX_NONE) { 104 stream << "No error"; 105 } else { 106 stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '"; 107 if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) { 108 stream << statusToString(s.transactionError()) << ": "; 109 } 110 stream << s.exceptionMessage() << "'"; 111 } 112 return stream; 113 } 114 115 static HidlReturnRestriction gReturnRestriction = HidlReturnRestriction::NONE; 116 void setProcessHidlReturnRestriction(HidlReturnRestriction restriction) { 117 gReturnRestriction = restriction; 118 } 119 120 namespace details { 121 void return_status::onValueRetrieval() const { 122 if (!isOk()) { 123 LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description(); 124 } 125 } 126 127 void return_status::onIgnored() const { 128 if (gReturnRestriction == HidlReturnRestriction::NONE) { 129 return; 130 } 131 132 if (gReturnRestriction == HidlReturnRestriction::ERROR_IF_UNCHECKED) { 133 LOG(ERROR) << "Failed to check status of HIDL Return."; 134 CallStack::logStack("unchecked HIDL return", CallStack::getCurrent(10).get(), 135 ANDROID_LOG_ERROR); 136 } else { 137 LOG(FATAL) << "Failed to check status of HIDL Return."; 138 } 139 } 140 141 void return_status::assertOk() const { 142 if (!isOk()) { 143 LOG(FATAL) << "Failed HIDL return status not checked. Usually this happens because of " 144 "a transport error (error parceling, binder driver, or from unparceling)" 145 ". If you see this in code calling into \"Bn\" classes in for a HAL " 146 "server process, then it is likely that the code there is returning " 147 "transport errors there (as opposed to errors defined within its " 148 "protocol). Error is: " << description(); 149 } 150 } 151 152 return_status::~return_status() { 153 // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus 154 if (mCheckedStatus) return; 155 156 assertOk(); 157 onIgnored(); 158 } 159 160 return_status& return_status::operator=(return_status&& other) noexcept { 161 if (!mCheckedStatus) { 162 assertOk(); 163 onIgnored(); 164 } 165 166 std::swap(mStatus, other.mStatus); 167 std::swap(mCheckedStatus, other.mCheckedStatus); 168 return *this; 169 } 170 171 } // namespace details 172 173 } // namespace hardware 174 } // namespace android 175