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>
2100cb980fcb6032f3a5ae124dc64ee2df8fb79a31Ralph Nathan#include <sstream>
2209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#include <binder/Parcel.h>
2409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#include <utils/String8.h>
2509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileynamespace android {
2709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileynamespace binder {
2809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
2909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley// An object similar in function to a status_t except that it understands
3009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley// how exceptions are encoded in the prefix of a Parcel. Used like:
3109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//
3209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     Parcel data;
3309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     Parcel reply;
3409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     status_t status;
3509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     binder::Status remote_exception;
3609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
3709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         (status = data.writeInt32(function_input)) != OK) {
3809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // We failed to write into the memory of our local parcel?
3909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
4009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if ((status = remote()->transact(transaction, data, &reply)) != OK) {
4109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//        // Something has gone wrong in the binder driver or libbinder.
4209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
4309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if ((status = remote_exception.readFromParcel(reply)) != OK) {
4409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // The remote didn't correctly write the exception header to the
4509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // reply.
4609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
4709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     if (!remote_exception.isOk()) {
4809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // The transaction went through correctly, but the remote reported an
4909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//         // exception during handling.
5009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//     }
5109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley//
5209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileyclass Status final {
5309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileypublic:
5409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Keep the exception codes in sync with android/os/Parcel.java.
5509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    enum Exception {
5609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_NONE = 0,
5709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_SECURITY = -1,
5809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_BAD_PARCELABLE = -2,
5909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_ILLEGAL_ARGUMENT = -3,
6009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_NULL_POINTER = -4,
6109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_ILLEGAL_STATE = -5,
6209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_NETWORK_MAIN_THREAD = -6,
6309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_UNSUPPORTED_OPERATION = -7,
64c1e491d5a4923298b612de919537d4293574b443Christopher Wiley        EX_SERVICE_SPECIFIC = -8,
65c8dc4f0af9f8847be9cdd2b9cbb5b8a7767982c4Jeff Sharkey        EX_PARCELABLE = -9,
6609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
6709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        // This is special and Java specific; see Parcel.java.
6809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley        EX_HAS_REPLY_HEADER = -128,
69cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        // This is special, and indicates to C++ binder proxies that the
70cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        // transaction has failed at a low level.
71cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        EX_TRANSACTION_FAILED = -129,
7209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    };
7309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
74cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // A more readable alias for the default constructor.
75cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    static Status ok();
761651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley
77c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // Authors should explicitly pick whether their integer is:
78c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  - an exception code (EX_* above)
79c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  - service specific error code
80c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  - status_t
81c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //
82c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  Prefer a generic exception code when possible, then a service specific
83c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  code, and finally a status_t for low level failures or legacy support.
84c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  Exception codes and service specific errors map to nicer exceptions for
85c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    //  Java clients.
86cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    static Status fromExceptionCode(int32_t exceptionCode);
87cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    static Status fromExceptionCode(int32_t exceptionCode,
88cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley                                    const String8& message);
891651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley    static Status fromExceptionCode(int32_t exceptionCode,
901651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley                                    const char* message);
911651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley
92c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
93c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
94c1e491d5a4923298b612de919537d4293574b443Christopher Wiley                                           const String8& message);
951651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
961651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley                                           const char* message);
971651ced6a84b3ba5b62917e88b981e6bac3e7e3fChristopher Wiley
9809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    static Status fromStatusT(status_t status);
9909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
10009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status() = default;
101cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    ~Status() = default;
10209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
10309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Status objects are copyable and contain just simple data.
10409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status(const Status& status) = default;
10509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status(Status&& status) = default;
10609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    Status& operator=(const Status& status) = default;
10709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
10809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Bear in mind that if the client or service is a Java endpoint, this
10909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // is not the logic which will provide/interpret the data here.
11009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    status_t readFromParcel(const Parcel& parcel);
11109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    status_t writeToParcel(Parcel* parcel) const;
11209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
11309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Set one of the pre-defined exception types defined above.
11409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    void setException(int32_t ex, const String8& message);
115c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // Set a service specific exception with error code.
116c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    void setServiceSpecificError(int32_t errorCode, const String8& message);
117cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // Setting a |status| != OK causes generated code to return |status|
118cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // from Binder transactions, rather than writing an exception into the
119c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // reply Parcel.  This is the least preferable way of reporting errors.
12009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    void setFromStatusT(status_t status);
12109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
12209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // Get information about an exception.
12309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    int32_t exceptionCode() const  { return mException; }
12409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    const String8& exceptionMessage() const { return mMessage; }
125cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    status_t transactionError() const {
126cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley        return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
127cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    }
128c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    int32_t serviceSpecificErrorCode() const {
129c1e491d5a4923298b612de919537d4293574b443Christopher Wiley        return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
130c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    }
13109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
13209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    bool isOk() const { return mException == EX_NONE; }
13309eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
13409eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    // For logging.
13509eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    String8 toString8() const;
13609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
13709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wileyprivate:
138c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    Status(int32_t exceptionCode, int32_t errorCode);
139c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    Status(int32_t exceptionCode, int32_t errorCode, const String8& message);
140cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley
141cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // If |mException| == EX_TRANSACTION_FAILED, generated code will return
142cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // |mErrorCode| as the result of the transaction rather than write an
143cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // exception to the reply parcel.
144cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    //
145cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // Otherwise, we always write |mException| to the parcel.
146cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    // If |mException| !=  EX_NONE, we write |mMessage| as well.
147c1e491d5a4923298b612de919537d4293574b443Christopher Wiley    // If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
14809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    int32_t mException = EX_NONE;
149cff7f175c1a4f790fdc64a56695c5b4b08b6bb6eChristopher Wiley    int32_t mErrorCode = 0;
15009eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley    String8 mMessage;
15109eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley};  // class Status
15209eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
153bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala// For gtest output logging
15400cb980fcb6032f3a5ae124dc64ee2df8fb79a31Ralph Nathanstd::stringstream& operator<< (std::stringstream& stream, const Status& s);
155bbab196fe58e5657d90f6f40a19fb93c2a91a8acEino-Ville Talvala
15609eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley}  // namespace binder
15709eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley}  // namespace android
15809eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley
15909eb749704afd9e226e1347cb20c90be2016cd21Christopher Wiley#endif // ANDROID_BINDER_STATUS_H
160