1bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen/* 2bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * Copyright (C) 2015 The Android Open Source Project 3bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * 4bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License"); 5bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * you may not use this file except in compliance with the License. 6bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * You may obtain a copy of the License at 7bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * 8bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * http://www.apache.org/licenses/LICENSE-2.0 9bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * 10bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * Unless required by applicable law or agreed to in writing, software 11bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS, 12bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * See the License for the specific language governing permissions and 14bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen * limitations under the License. 15bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen */ 162be9418963c8d36bb1425093d224256e2a94b277Yifan Hong 17e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland#define LOG_TAG "HidlStatus" 182be9418963c8d36bb1425093d224256e2a94b277Yifan Hong#include <android-base/logging.h> 19bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 20bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#include <hidl/Status.h> 21bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 222be9418963c8d36bb1425093d224256e2a94b277Yifan Hong#include <unordered_map> 23e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland 24bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenennamespace android { 25bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenennamespace hardware { 26bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 272be9418963c8d36bb1425093d224256e2a94b277Yifan Hongstatic std::string statusToString(status_t s) { 282be9418963c8d36bb1425093d224256e2a94b277Yifan Hong const std::unordered_map<status_t, std::string> statusStrings{{ 292be9418963c8d36bb1425093d224256e2a94b277Yifan Hong #define STATUS_TO_STRING_PAIR(STATUS) {STATUS, #STATUS} 302be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(OK), 312be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(UNKNOWN_ERROR), 322be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(NO_MEMORY), 332be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(INVALID_OPERATION), 342be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(BAD_VALUE), 352be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(BAD_TYPE), 362be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(NAME_NOT_FOUND), 372be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(PERMISSION_DENIED), 382be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(NO_INIT), 392be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(ALREADY_EXISTS), 402be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(DEAD_OBJECT), 412be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(FAILED_TRANSACTION), 422be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(BAD_INDEX), 432be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(NOT_ENOUGH_DATA), 442be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(WOULD_BLOCK), 452be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(TIMED_OUT), 462be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(UNKNOWN_TRANSACTION), 472be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(FDS_NOT_ALLOWED), 482be9418963c8d36bb1425093d224256e2a94b277Yifan Hong STATUS_TO_STRING_PAIR(UNEXPECTED_NULL) 492be9418963c8d36bb1425093d224256e2a94b277Yifan Hong }}; 502be9418963c8d36bb1425093d224256e2a94b277Yifan Hong auto it = statusStrings.find(s); 512be9418963c8d36bb1425093d224256e2a94b277Yifan Hong if (it != statusStrings.end()) { 522be9418963c8d36bb1425093d224256e2a94b277Yifan Hong return it->second; 532be9418963c8d36bb1425093d224256e2a94b277Yifan Hong } 542be9418963c8d36bb1425093d224256e2a94b277Yifan Hong std::string str = std::to_string(s); 552be9418963c8d36bb1425093d224256e2a94b277Yifan Hong char *err = strerror(-s); 562be9418963c8d36bb1425093d224256e2a94b277Yifan Hong if (err != NULL) { 572be9418963c8d36bb1425093d224256e2a94b277Yifan Hong str.append(1, ' ').append(err); 582be9418963c8d36bb1425093d224256e2a94b277Yifan Hong } 592be9418963c8d36bb1425093d224256e2a94b277Yifan Hong return str; 602be9418963c8d36bb1425093d224256e2a94b277Yifan Hong} 612be9418963c8d36bb1425093d224256e2a94b277Yifan Hong 622be9418963c8d36bb1425093d224256e2a94b277Yifan Hongstatic std::string exceptionToString(int32_t ex) { 632be9418963c8d36bb1425093d224256e2a94b277Yifan Hong const std::unordered_map<int32_t, std::string> exceptionStrings{{ 642be9418963c8d36bb1425093d224256e2a94b277Yifan Hong #define EXCEPTION_TO_STRING_PAIR(EXCEPTION) {Status::Exception::EXCEPTION, #EXCEPTION} 652be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_NONE), 662be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_SECURITY), 672be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_BAD_PARCELABLE), 682be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_ARGUMENT), 692be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_NULL_POINTER), 702be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_STATE), 712be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_NETWORK_MAIN_THREAD), 722be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_UNSUPPORTED_OPERATION), 732be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_HAS_REPLY_HEADER), 742be9418963c8d36bb1425093d224256e2a94b277Yifan Hong EXCEPTION_TO_STRING_PAIR(EX_TRANSACTION_FAILED) 752be9418963c8d36bb1425093d224256e2a94b277Yifan Hong }}; 762be9418963c8d36bb1425093d224256e2a94b277Yifan Hong auto it = exceptionStrings.find(ex); 772be9418963c8d36bb1425093d224256e2a94b277Yifan Hong return it == exceptionStrings.end() ? std::to_string(ex) : it->second; 782be9418963c8d36bb1425093d224256e2a94b277Yifan Hong} 792be9418963c8d36bb1425093d224256e2a94b277Yifan Hong 80bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn CoenenStatus Status::ok() { 81bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return Status(); 82bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 83bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 84bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn CoenenStatus Status::fromExceptionCode(int32_t exceptionCode) { 85bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return Status(exceptionCode, OK); 86bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 87bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 88bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn CoenenStatus Status::fromExceptionCode(int32_t exceptionCode, 8943298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong const char *message) { 90bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return Status(exceptionCode, OK, message); 91bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 92bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 93bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn CoenenStatus Status::fromStatusT(status_t status) { 94bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status ret; 95bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen ret.setFromStatusT(status); 96bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return ret; 97bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 98bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 99bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn CoenenStatus::Status(int32_t exceptionCode, int32_t errorCode) 100bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen : mException(exceptionCode), 101bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mErrorCode(errorCode) {} 102bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 10343298f90efb47e1ae3589df56b12e9e53f16c53eYifan HongStatus::Status(int32_t exceptionCode, int32_t errorCode, const char *message) 104bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen : mException(exceptionCode), 105bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mErrorCode(errorCode), 106bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mMessage(message) {} 107bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 10843298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hongvoid Status::setException(int32_t ex, const char *message) { 109bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mException = ex; 110bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mErrorCode = NO_ERROR; // an exception, not a transaction failure. 11143298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong mMessage = message; 112bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 113bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 114bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenvoid Status::setFromStatusT(status_t status) { 115bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED; 116bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mErrorCode = status; 117bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen mMessage.clear(); 118bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 119bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 12043298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hongstd::string Status::description() const { 12143298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong std::ostringstream oss; 12243298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong oss << (*this); 12343298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong return oss.str(); 12443298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong} 12543298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong 12643298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hongstd::ostream& operator<< (std::ostream& stream, const Status& s) { 12743298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong if (s.exceptionCode() == Status::EX_NONE) { 12843298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong stream << "No error"; 129bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } else { 1302be9418963c8d36bb1425093d224256e2a94b277Yifan Hong stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '"; 13172db40f4a612d04187ae2fc1f9a3766933264bdfSteven Moreland if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) { 1322be9418963c8d36bb1425093d224256e2a94b277Yifan Hong stream << statusToString(s.transactionError()) << ": "; 133bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } 13443298f90efb47e1ae3589df56b12e9e53f16c53eYifan Hong stream << s.exceptionMessage() << "'"; 135bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } 136bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return stream; 137bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} 138bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 139e780c45b31a03f318db85b9940bf20f93ac50395Steven Morelandnamespace details { 140af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong void return_status::assertOk() const { 141e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland if (!isOk()) { 142e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description(); 143e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland } 144e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland } 145e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland 146e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland return_status::~return_status() { 147e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus 148e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland if (!mCheckedStatus && !isOk()) { 149e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland LOG(FATAL) << "Failed HIDL return status not checked: " << description(); 150e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland } 151e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland } 152af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong 153af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong return_status &return_status::operator=(return_status &&other) { 154af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong if (!mCheckedStatus && !isOk()) { 155af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong LOG(FATAL) << "Failed HIDL return status not checked: " << description(); 156af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong } 157af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong std::swap(mStatus, other.mStatus); 158af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong std::swap(mCheckedStatus, other.mCheckedStatus); 159af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong return *this; 160af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong } 161af4e43cc5b2eacbfe600f9ab0e459f09c35c0c3fYifan Hong 162e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland} // namespace details 163e780c45b31a03f318db85b9940bf20f93ac50395Steven Moreland 164bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} // namespace hardware 165bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} // namespace android 166