109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley/*
209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * Copyright (C) 2015 The Android Open Source Project
309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley *
409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * Licensed under the Apache License, Version 2.0 (the "License");
509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * you may not use this file except in compliance with the License.
609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * You may obtain a copy of the License at
709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley *
809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley *      http://www.apache.org/licenses/LICENSE-2.0
909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley *
1009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * Unless required by applicable law or agreed to in writing, software
1109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * distributed under the License is distributed on an "AS IS" BASIS,
1209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * See the License for the specific language governing permissions and
1409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley * limitations under the License.
1509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley */
1609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
1709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#ifndef ANDROID_BINDER_STATUS_H
1809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#define ANDROID_BINDER_STATUS_H
1909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#include <cstdint>
2109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#include <binder/Parcel.h>
2309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#include <utils/String8.h>
2409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileynamespace android {
2609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileynamespace binder {
2709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley// An object similar in function to a status_t except that it understands
2909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley// how exceptions are encoded in the prefix of a Parcel. Used like:
3009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//
3109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     Parcel data;
3209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     Parcel reply;
3309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     status_t status;
3409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     binder::Status remote_exception;
3509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
3609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         (status = data.writeInt32(function_input)) != OK) {
3709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // We failed to write into the memory of our local parcel?
3809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
3909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if ((status = remote()->transact(transaction, data, &reply)) != OK) {
4009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//        // Something has gone wrong in the binder driver or libbinder.
4109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
4209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if ((status = remote_exception.readFromParcel(reply)) != OK) {
4309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // The remote didn't correctly write the exception header to the
4409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // reply.
4509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
4609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if (!remote_exception.isOk()) {
4709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // The transaction went through correctly, but the remote reported an
4809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // exception during handling.
4909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
5009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//
5109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileyclass Status final {
5209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileypublic:
5309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Keep the exception codes in sync with android/os/Parcel.java.
5409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    enum Exception {
5509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_NONE = 0,
5609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_SECURITY = -1,
5709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_BAD_PARCELABLE = -2,
5809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_ILLEGAL_ARGUMENT = -3,
5909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_NULL_POINTER = -4,
6009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_ILLEGAL_STATE = -5,
6109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_NETWORK_MAIN_THREAD = -6,
6209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_UNSUPPORTED_OPERATION = -7,
63c1e491d5a4923298b612de919537d4293574b443Christopher Wiley        EX_SERVICE_SPECIFIC = -8,
6409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
6509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        // This is special and Java specific; see Parcel.java.
6609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_HAS_REPLY_HEADER = -128,
67cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        // This is special, and indicates to C++ binder proxies that the
68cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        // transaction has failed at a low level.
69cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        EX_TRANSACTION_FAILED = -129,
7009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    };
7109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
72cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // A more readable alias for the default constructor.
73cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    static Status ok();
74c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // Authors should explicitly pick whether their integer is:
75c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  - an exception code (EX_* above)
76c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  - service specific error code
77c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  - status_t
78c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //
79c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  Prefer a generic exception code when possible, then a service specific
80c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  code, and finally a status_t for low level failures or legacy support.
81c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  Exception codes and service specific errors map to nicer exceptions for
82c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  Java clients.
83cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    static Status fromExceptionCode(int32_t exceptionCode);
84cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    static Status fromExceptionCode(int32_t exceptionCode,
85cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley                                    const String8& message);
86c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
87c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
88c1e491d5a4923298b612de919537d4293574b443Christopher Wiley                                           const String8& message);
8909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    static Status fromStatusT(status_t status);
9009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
9109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status() = default;
92cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    ~Status() = default;
9309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
9409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Status objects are copyable and contain just simple data.
9509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status(const Status& status) = default;
9609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status(Status&& status) = default;
9709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status& operator=(const Status& status) = default;
9809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
9909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Bear in mind that if the client or service is a Java endpoint, this
10009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // is not the logic which will provide/interpret the data here.
10109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    status_t readFromParcel(const Parcel& parcel);
10209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    status_t writeToParcel(Parcel* parcel) const;
10309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
10409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Set one of the pre-defined exception types defined above.
10509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    void setException(int32_t ex, const String8& message);
106c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // Set a service specific exception with error code.
107c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    void setServiceSpecificError(int32_t errorCode, const String8& message);
108cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // Setting a |status| != OK causes generated code to return |status|
109cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // from Binder transactions, rather than writing an exception into the
110c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // reply Parcel.  This is the least preferable way of reporting errors.
11109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    void setFromStatusT(status_t status);
11209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
11309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Get information about an exception.
11409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    int32_t exceptionCode() const  { return mException; }
11509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    const String8& exceptionMessage() const { return mMessage; }
116cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    status_t transactionError() const {
117cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
118cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    }
119c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    int32_t serviceSpecificErrorCode() const {
120c1e491d5a4923298b612de919537d4293574b443Christopher Wiley        return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
121c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    }
12209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
12309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    bool isOk() const { return mException == EX_NONE; }
12409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
12509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // For logging.
12609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    String8 toString8() const;
12709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
12809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileyprivate:
129c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    Status(int32_t exceptionCode, int32_t errorCode);
130c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    Status(int32_t exceptionCode, int32_t errorCode, const String8& message);
131cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley
132cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // If |mException| == EX_TRANSACTION_FAILED, generated code will return
133cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // |mErrorCode| as the result of the transaction rather than write an
134cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // exception to the reply parcel.
135cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    //
136cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // Otherwise, we always write |mException| to the parcel.
137cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // If |mException| !=  EX_NONE, we write |mMessage| as well.
138c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
13909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    int32_t mException = EX_NONE;
140cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    int32_t mErrorCode = 0;
14109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    String8 mMessage;
14209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley};  // class Status
14309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
144bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala// For gtest output logging
145bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvalatemplate<typename T>
146bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville TalvalaT& operator<< (T& stream, const Status& s) {
147bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala    stream << s.toString8().string();
148bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala    return stream;
149bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala}
150bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala
15109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley}  // namespace binder
15209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley}  // namespace android
15309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
15409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#endif // ANDROID_BINDER_STATUS_H
155