1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_BINDER_STATUS_H
#define ANDROID_BINDER_STATUS_H
#include <cstdint>
#include <sstream> // historical
#include <ostream>
#include <binder/Common.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <string>
namespace android {
namespace binder {
// An object similar in function to a status_t except that it understands
// how exceptions are encoded in the prefix of a Parcel. Used like:
//
// Parcel data;
// Parcel reply;
// status_t status;
// binder::Status remote_exception;
// if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
// (status = data.writeInt32(function_input)) != OK) {
// // We failed to write into the memory of our local parcel?
// }
// if ((status = remote()->transact(transaction, data, &reply)) != OK) {
// // Something has gone wrong in the binder driver or libbinder.
// }
// if ((status = remote_exception.readFromParcel(reply)) != OK) {
// // The remote didn't correctly write the exception header to the
// // reply.
// }
// if (!remote_exception.isOk()) {
// // The transaction went through correctly, but the remote reported an
// // exception during handling.
// }
//
class LIBBINDER_EXPORTED Status final {
public:
// Keep the exception codes in sync with android/os/Parcel.java.
enum Exception {
EX_NONE = 0,
EX_SECURITY = -1,
EX_BAD_PARCELABLE = -2,
EX_ILLEGAL_ARGUMENT = -3,
EX_NULL_POINTER = -4,
EX_ILLEGAL_STATE = -5,
EX_NETWORK_MAIN_THREAD = -6,
EX_UNSUPPORTED_OPERATION = -7,
EX_SERVICE_SPECIFIC = -8,
EX_PARCELABLE = -9,
// This is special and Java specific; see Parcel.java.
EX_HAS_REPLY_HEADER = -128,
// This is special, and indicates to C++ binder proxies that the
// transaction has failed at a low level.
EX_TRANSACTION_FAILED = -129,
};
// A more readable alias for the default constructor.
static Status ok();
// Authors should explicitly pick whether their integer is:
// - an exception code (EX_* above)
// - service specific error code
// - status_t
//
// Prefer a generic exception code when possible, then a service specific
// code, and finally a status_t for low level failures or legacy support.
// Exception codes and service specific errors map to nicer exceptions for
// Java clients.
static Status fromExceptionCode(int32_t exceptionCode);
static Status fromExceptionCode(int32_t exceptionCode,
const String8& message);
static Status fromExceptionCode(int32_t exceptionCode,
const char* message);
// warning: this is still considered an error if it is constructed with a
// zero value error code. Please use Status::ok() instead and avoid zero
// error codes
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const String8& message);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const char* message);
static Status fromStatusT(status_t status);
static std::string exceptionToString(status_t exceptionCode);
Status() = default;
~Status() = default;
// Status objects are copyable and contain just simple data.
Status(const Status& status) = default;
Status(Status&& status) = default;
Status& operator=(const Status& status) = default;
// Bear in mind that if the client or service is a Java endpoint, this
// is not the logic which will provide/interpret the data here.
status_t readFromParcel(const Parcel& parcel);
status_t writeToParcel(Parcel* parcel) const;
// Convenience API to replace a Parcel with a status value, w/o requiring
// calling multiple APIs (makes generated code smaller).
status_t writeOverParcel(Parcel* parcel) const;
// Set one of the pre-defined exception types defined above.
void setException(int32_t ex, const String8& message);
// Set a service specific exception with error code.
void setServiceSpecificError(int32_t errorCode, const String8& message);
// Setting a |status| != OK causes generated code to return |status|
// from Binder transactions, rather than writing an exception into the
// reply Parcel. This is the least preferable way of reporting errors.
void setFromStatusT(status_t status);
// Get information about an exception.
int32_t exceptionCode() const { return mException; }
const String8& exceptionMessage() const { return mMessage; }
status_t transactionError() const {
return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
}
int32_t serviceSpecificErrorCode() const {
return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
}
bool isOk() const { return mException == EX_NONE; }
// For logging.
String8 toString8() const;
private:
Status(int32_t exceptionCode, int32_t errorCode);
Status(int32_t exceptionCode, int32_t errorCode, const String8& message);
// If |mException| == EX_TRANSACTION_FAILED, generated code will return
// |mErrorCode| as the result of the transaction rather than write an
// exception to the reply parcel.
//
// Otherwise, we always write |mException| to the parcel.
// If |mException| != EX_NONE, we write |mMessage| as well.
// If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
int32_t mException = EX_NONE;
int32_t mErrorCode = 0;
String8 mMessage;
}; // class Status
static inline std::ostream& operator<< (std::ostream& o, const Status& s) {
return o << s.toString8();
}
} // namespace binder
} // namespace android
#endif // ANDROID_BINDER_STATUS_H
|