Status.h revision bb5e9bb1c982a029ebc82e82f3838b6beeb2d108
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 */ 16bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 17bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#ifndef ANDROID_HARDWARE_BINDER_STATUS_H 18bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#define ANDROID_HARDWARE_BINDER_STATUS_H 19bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 20bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#include <cstdint> 21bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#include <sstream> 22bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 23bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#include <hwbinder/Parcel.h> 24bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#include <utils/String8.h> 25bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#include <android-base/macros.h> 26bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 27bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenennamespace android { 28bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenennamespace hardware { 29bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 30bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// An object similar in function to a status_t except that it understands 31bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// how exceptions are encoded in the prefix of a Parcel. Used like: 32bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// 33bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// Parcel data; 34bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// Parcel reply; 35bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// status_t status; 36bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// binder::Status remote_exception; 37bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// if ((status = data.writeInterfaceToken(interface_descriptor)) != OK || 38bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// (status = data.writeInt32(function_input)) != OK) { 39bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// // We failed to write into the memory of our local parcel? 40bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// } 41bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// if ((status = remote()->transact(transaction, data, &reply)) != OK) { 42bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// // Something has gone wrong in the binder driver or libbinder. 43bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// } 44bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// if ((status = remote_exception.readFromParcel(reply)) != OK) { 45bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// // The remote didn't correctly write the exception header to the 46bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// // reply. 47bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// } 48bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// if (!remote_exception.isOk()) { 49bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// // The transaction went through correctly, but the remote reported an 50bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// // exception during handling. 51bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// } 52bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// 53bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenclass Status final { 54bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenpublic: 55bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Keep the exception codes in sync with android/os/Parcel.java. 56bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen enum Exception { 57bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_NONE = 0, 58bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_SECURITY = -1, 59bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_BAD_PARCELABLE = -2, 60bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_ILLEGAL_ARGUMENT = -3, 61bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_NULL_POINTER = -4, 62bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_ILLEGAL_STATE = -5, 63bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_NETWORK_MAIN_THREAD = -6, 64bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_UNSUPPORTED_OPERATION = -7, 65bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_SERVICE_SPECIFIC = -8, 66bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 67bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // This is special and Java specific; see Parcel.java. 68bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_HAS_REPLY_HEADER = -128, 69bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // This is special, and indicates to C++ binder proxies that the 70bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // transaction has failed at a low level. 71bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen EX_TRANSACTION_FAILED = -129, 72bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen }; 73bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 74bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // A more readable alias for the default constructor. 75bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen static Status ok(); 76bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Authors should explicitly pick whether their integer is: 77bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // - an exception code (EX_* above) 78bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // - service specific error code 79bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // - status_t 80bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // 81bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Prefer a generic exception code when possible, then a service specific 82bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // code, and finally a status_t for low level failures or legacy support. 83bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Exception codes and service specific errors map to nicer exceptions for 84bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Java clients. 85bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen static Status fromExceptionCode(int32_t exceptionCode); 86bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen static Status fromExceptionCode(int32_t exceptionCode, 87bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen const String8& message); 88bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode); 89bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode, 90bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen const String8& message); 91bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen static Status fromStatusT(status_t status); 92bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 93bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status() = default; 94bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen ~Status() = default; 95bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 96bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Status objects are copyable and contain just simple data. 97bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status(const Status& status) = default; 98bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status(Status&& status) = default; 99bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status& operator=(const Status& status) = default; 100bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 101bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Bear in mind that if the client or service is a Java endpoint, this 102bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // is not the logic which will provide/interpret the data here. 103bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen status_t readFromParcel(const Parcel& parcel); 104bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen status_t writeToParcel(Parcel* parcel) const; 105bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 106bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Set one of the pre-defined exception types defined above. 107bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen void setException(int32_t ex, const String8& message); 108bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Set a service specific exception with error code. 109bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen void setServiceSpecificError(int32_t errorCode, const String8& message); 110bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Setting a |status| != OK causes generated code to return |status| 111bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // from Binder transactions, rather than writing an exception into the 112bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // reply Parcel. This is the least preferable way of reporting errors. 113bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen void setFromStatusT(status_t status); 114bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 115bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Get information about an exception. 116bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen int32_t exceptionCode() const { return mException; } 117bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen const String8& exceptionMessage() const { return mMessage; } 118bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen status_t transactionError() const { 119bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK; 120bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } 121bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen int32_t serviceSpecificErrorCode() const { 122bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0; 123bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } 124bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 125bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen bool isOk() const { return mException == EX_NONE; } 126bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 127bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // For logging. 128bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen String8 toString8() const; 129bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 130bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenprivate: 131bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status(int32_t exceptionCode, int32_t errorCode); 132bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status(int32_t exceptionCode, int32_t errorCode, const String8& message); 133bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 134bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // If |mException| == EX_TRANSACTION_FAILED, generated code will return 135bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // |mErrorCode| as the result of the transaction rather than write an 136bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // exception to the reply parcel. 137bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // 138bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // Otherwise, we always write |mException| to the parcel. 139bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // If |mException| != EX_NONE, we write |mMessage| as well. 140bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well. 141bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen int32_t mException = EX_NONE; 142bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen int32_t mErrorCode = 0; 143bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen String8 mMessage; 144bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen}; // class Status 145bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 146bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen// For gtest output logging 147bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenstd::stringstream& operator<< (std::stringstream& stream, const Status& s); 148bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 149bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenentemplate<typename T> class Return { 150bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenpublic: 151bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen T val; 152bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Status status; 153bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenenpublic: 154bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Return(T v) : val(v), status(Status::ok()) { } 155bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen Return(Status s) : status(s) { 156bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // TODO(malchev): Spew a LOG error here 157bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } 158bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen ~Return() { 159bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen // TODO(malchev): Assert that status isOk() if it hasn't been checked 160bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen } 161bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen operator T() { return val; } 162bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen}; 163bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 164bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} // namespace hardware 165bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen} // namespace android 166bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen 167bb5e9bb1c982a029ebc82e82f3838b6beeb2d108Martijn Coenen#endif // ANDROID_HARDWARE_BINDER_STATUS_H 168