Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cdc1d07 authored by Steven Moreland's avatar Steven Moreland Committed by Gerrit Code Review
Browse files

Merge changes from topic "libbinder_ndk_aidl"

* changes:
  libbinder_ndk: Add C++ wrapper code.
  libbinder_ndk: add read/write string methods.
parents d8c1aa72 2648d202
Loading
Loading
Loading
Loading
+234 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

/**
 * @addtogroup NdkBinder
 * @{
 */

/**
 * @file binder_auto_utils.h
 * @brief These objects provide a more C++-like thin interface to the .
 */

#pragma once

#include <android/binder_ibinder.h>
#include <android/binder_parcel.h>
#include <android/binder_status.h>

#ifdef __cplusplus

#include <cstddef>

namespace android {

/**
 * Represents one strong pointer to an AIBinder object.
 */
class AutoAIBinder {
public:
    /**
     * Takes ownership of one strong refcount of binder.
     */
    explicit AutoAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {}

    /**
     * Convenience operator for implicitly constructing an AutoAIBinder from nullptr. This is not
     * explicit because it is not taking ownership of anything.
     */
    AutoAIBinder(std::nullptr_t) : AutoAIBinder() {}

    /**
     * This will delete the underlying object if it exists. See operator=.
     */
    AutoAIBinder(const AutoAIBinder& other) { *this = other; }

    /**
     * This deletes the underlying object if it exists. See set.
     */
    ~AutoAIBinder() { set(nullptr); }

    /**
     * This takes ownership of a binder from another AIBinder object but it does not affect the
     * ownership of that other object.
     */
    AutoAIBinder& operator=(const AutoAIBinder& other) {
        AIBinder_incStrong(other.mBinder);
        set(other.mBinder);
        return *this;
    }

    /**
     * Takes ownership of one strong refcount of binder
     */
    void set(AIBinder* binder) {
        if (mBinder != nullptr) AIBinder_decStrong(mBinder);
        mBinder = binder;
    }

    /**
     * This returns the underlying binder object for transactions. If it is used to create another
     * AutoAIBinder object, it should first be incremented.
     */
    AIBinder* get() const { return mBinder; }

    /**
     * This allows the value in this class to be set from beneath it. If you call this method and
     * then change the value of T*, you must take ownership of the value you are replacing and add
     * ownership to the object that is put in here.
     *
     * Recommended use is like this:
     *   AutoAIBinder a;  // will be nullptr
     *   SomeInitFunction(a.getR());  // value is initialized with refcount
     *
     * Other usecases are discouraged.
     *
     */
    AIBinder** getR() { return &mBinder; }

private:
    AIBinder* mBinder = nullptr;
};

/**
 * This baseclass owns a single object, used to make various classes RAII.
 */
template <typename T, void (*Destroy)(T*)>
class AutoA {
public:
    /**
     * Takes ownership of t.
     */
    explicit AutoA(T* t = nullptr) : mT(t) {}

    /**
     * This deletes the underlying object if it exists. See set.
     */
    ~AutoA() { set(nullptr); }

    /**
     * Takes ownership of t.
     */
    void set(T* t) {
        Destroy(mT);
        mT = t;
    }

    /**
     * This returns the underlying object to be modified but does not affect ownership.
     */
    T* get() { return mT; }

    /**
     * This returns the const underlying object but does not affect ownership.
     */
    const T* get() const { return mT; }

    /**
     * This allows the value in this class to be set from beneath it. If you call this method and
     * then change the value of T*, you must take ownership of the value you are replacing and add
     * ownership to the object that is put in here.
     *
     * Recommended use is like this:
     *   AutoA<T> a; // will be nullptr
     *   SomeInitFunction(a.getR()); // value is initialized with refcount
     *
     * Other usecases are discouraged.
     *
     */
    T** getR() { return &mT; }

    // copy-constructing, or move/copy assignment is disallowed
    AutoA(const AutoA&) = delete;
    AutoA& operator=(const AutoA&) = delete;
    AutoA& operator=(AutoA&&) = delete;

    // move-constructing is okay
    AutoA(AutoA&&) = default;

private:
    T* mT;
};

/**
 * Convenience wrapper. See AParcel.
 */
class AutoAParcel : public AutoA<AParcel, AParcel_delete> {
public:
    /**
     * Takes ownership of a.
     */
    explicit AutoAParcel(AParcel* a = nullptr) : AutoA(a) {}
    ~AutoAParcel() {}
    AutoAParcel(AutoAParcel&&) = default;
};

/**
 * Convenience wrapper. See AStatus.
 */
class AutoAStatus : public AutoA<AStatus, AStatus_delete> {
public:
    /**
     * Takes ownership of a.
     */
    explicit AutoAStatus(AStatus* a = nullptr) : AutoA(a) {}
    ~AutoAStatus() {}
    AutoAStatus(AutoAStatus&&) = default;

    /**
     * See AStatus_isOk.
     */
    bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
};

/**
 * Convenience wrapper. See AIBinder_DeathRecipient.
 */
class AutoAIBinder_DeathRecipient
      : public AutoA<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
public:
    /**
     * Takes ownership of a.
     */
    explicit AutoAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr) : AutoA(a) {}
    ~AutoAIBinder_DeathRecipient() {}
    AutoAIBinder_DeathRecipient(AutoAIBinder_DeathRecipient&&) = default;
};

/**
 * Convenience wrapper. See AIBinder_Weak.
 */
class AutoAIBinder_Weak : public AutoA<AIBinder_Weak, AIBinder_Weak_delete> {
public:
    /**
     * Takes ownership of a.
     */
    explicit AutoAIBinder_Weak(AIBinder_Weak* a = nullptr) : AutoA(a) {}
    ~AutoAIBinder_Weak() {}
    AutoAIBinder_Weak(AutoAIBinder_Weak&&) = default;

    /**
     * See AIBinder_Weak_promote.
     */
    AutoAIBinder promote() { return AutoAIBinder(AIBinder_Weak_promote(get())); }
};

} // namespace android

#endif // __cplusplus

/** @} */
+131 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

/**
 * @addtogroup NdkBinder
 * @{
 */

/**
 * @file binder_interface_utils.h
 * @brief This provides common C++ classes for common operations and as base classes for C++
 * interfaces.
 */

#pragma once

#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>

#ifdef __cplusplus

#include <memory>
#include <mutex>

namespace android {

// analog using std::shared_ptr for RefBase-like semantics
class SharedRefBase {
public:
    SharedRefBase() {}
    virtual ~SharedRefBase() {}

    std::shared_ptr<SharedRefBase> ref() {
        std::shared_ptr<SharedRefBase> thiz = mThis.lock();

        std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });

        return thiz;
    }

    template <typename CHILD>
    std::shared_ptr<CHILD> ref() {
        return std::static_pointer_cast<CHILD>(ref());
    }

private:
    std::once_flag mFlagThis;
    std::weak_ptr<SharedRefBase> mThis;
};

// wrapper analog to IInterface
class ICInterface : public SharedRefBase {
public:
    ICInterface() {}
    virtual ~ICInterface() {}

    // This either returns the single existing implementation or creates a new implementation.
    virtual AutoAIBinder asBinder() = 0;
};

// wrapper analog to BnInterface
template <typename INTERFACE>
class BnCInterface : public INTERFACE {
public:
    BnCInterface() {}
    virtual ~BnCInterface() {}

    AutoAIBinder asBinder() override;

protected:
    // This function should only be called by asBinder. Otherwise, there is a possibility of
    // multiple AIBinder* objects being created for the same instance of an object.
    virtual AutoAIBinder createBinder() = 0;

private:
    std::mutex mMutex; // for asBinder
    AutoAIBinder_Weak mWeakBinder;
};

// wrapper analog to BpInterfae
template <typename INTERFACE>
class BpCInterface : public INTERFACE {
public:
    BpCInterface(const AutoAIBinder& binder) : mBinder(binder) {}
    virtual ~BpCInterface() {}

    AutoAIBinder asBinder() override;

private:
    AutoAIBinder mBinder;
};

template <typename INTERFACE>
AutoAIBinder BnCInterface<INTERFACE>::asBinder() {
    std::lock_guard<std::mutex> l(mMutex);

    AutoAIBinder binder;
    if (mWeakBinder.get() != nullptr) {
        binder.set(AIBinder_Weak_promote(mWeakBinder.get()));
    }
    if (binder.get() == nullptr) {
        binder = createBinder();
        mWeakBinder.set(AIBinder_Weak_new(binder.get()));
    }

    return binder;
}

template <typename INTERFACE>
AutoAIBinder BpCInterface<INTERFACE>::asBinder() {
    return mBinder;
}

#endif // __cplusplus

} // namespace android

/** @} */
+37 −0
Original line number Diff line number Diff line
@@ -88,6 +88,43 @@ binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status
binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status)
        __INTRODUCED_IN(29);

/**
 * Writes string value to the next location in a non-null parcel.
 */
binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
        __INTRODUCED_IN(29);

/**
 * This is called to allocate a buffer
 *
 * The length here includes the space required to insert a '\0' for a properly formed c-str. If the
 * buffer returned from this function is retStr, it will be filled by AParcel_readString with the
 * data from the remote process, and it will be filled such that retStr[length] == '\0'.
 *
 * If allocation fails, null should be returned.
 */
typedef void* (*AParcel_string_reallocator)(void* stringData, size_t length);

/**
 * This is called to get the buffer from a stringData object.
 */
typedef char* (*AParcel_string_getter)(void* stringData);

/**
 * Reads and allocates string value from the next location in a non-null parcel.
 *
 * Data is passed to the string allocator once the string size is known. This data should be used to
 * point to some kind of string data. For instance, it could be a char*, and the string allocator
 * could be realloc. Then the getter would simply be a cast to char*. In more complicated cases,
 * stringData could be a structure containing additional string data.
 *
 * If this function returns a success, the buffer returned by allocator when passed stringData will
 * contain a null-terminated c-str read from the binder.
 */
binder_status_t AParcel_readString(const AParcel* parcel, AParcel_string_reallocator reallocator,
                                   AParcel_string_getter getter, void** stringData)
        __INTRODUCED_IN(29);

// @START
/**
 * Writes int32_t value to the next location in a non-null parcel.
+71 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

/**
 * @addtogroup NdkBinder
 * @{
 */

/**
 * @file binder_parcel_utils.h
 * @brief A collection of helper wrappers for AParcel.
 */

#pragma once

#include <android/binder_parcel.h>

#ifdef __cplusplus

#include <string>

/**
 * Takes a std::string and reallocates it to the specified length. For use with AParcel_readString.
 * See use below in AParcel_readString.
 */
static inline void* AParcel_std_string_reallocator(void* stringData, size_t length) {
    std::string* str = static_cast<std::string*>(stringData);
    str->resize(length - 1);
    return stringData;
}

/**
 * Takes a std::string and returns the inner char*.
 */
static inline char* AParcel_std_string_getter(void* stringData) {
    std::string* str = static_cast<std::string*>(stringData);
    return &(*str)[0];
}

/**
 * Convenience API for writing a std::string.
 */
static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
    return AParcel_writeString(parcel, str.c_str(), str.size());
}

/**
 * Convenience API for reading a std::string.
 */
static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
    void* stringData = static_cast<void*>(str);
    return AParcel_readString(parcel, AParcel_std_string_reallocator, AParcel_std_string_getter,
                              &stringData);
}

#endif // __cplusplus

/** @} */
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ LIBBINDER_NDK { # introduced=29
    AParcel_readInt64;
    AParcel_readNullableStrongBinder;
    AParcel_readStatusHeader;
    AParcel_readString;
    AParcel_readStrongBinder;
    AParcel_readUint32;
    AParcel_readUint64;
@@ -43,6 +44,7 @@ LIBBINDER_NDK { # introduced=29
    AParcel_writeInt32;
    AParcel_writeInt64;
    AParcel_writeStatusHeader;
    AParcel_writeString;
    AParcel_writeStrongBinder;
    AParcel_writeUint32;
    AParcel_writeUint64;
Loading