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

Commit dbcb647b authored by Steven Moreland's avatar Steven Moreland Committed by android-build-merger
Browse files

Merge "Initial C library for libbinder." am: a6aa0e79

am: 66f57430

Change-Id: I8d08db28865c1d4f5143bb4e69c121b8956cd05f
parents 38621c80 66f57430
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line 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.
 */

#include <android/binder_process.h>

#include <mutex>

#include <android-base/logging.h>
#include <binder/IPCThreadState.h>

using ::android::IPCThreadState;
using ::android::ProcessState;

void ABinderProcess_startThreadPool() {
    ProcessState::self()->startThreadPool();
    ProcessState::self()->giveThreadPoolName();
}
bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads) {
    return ProcessState::self()->setThreadPoolMaxThreadCount(numThreads) == 0;
}
void ABinderProcess_joinThreadPool() {
    IPCThreadState::self()->joinThreadPool();
}
+345 −0
Original line number Original line 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.
 */

#include <android/binder_ibinder.h>
#include "AIBinder_internal.h"

#include <android/binder_status.h>
#include "AParcel_internal.h"

#include <android-base/logging.h>

using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;
using ::android::String16;
using ::android::wp;

AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}

sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
    using ::android::String8;

    if (clazz == nullptr) return nullptr;
    if (mClazz == clazz) return this;

    String8 newDescriptor(clazz->getInterfaceDescriptor());

    if (mClazz != nullptr) {
        String8 currentDescriptor(mClazz->getInterfaceDescriptor());
        if (newDescriptor == currentDescriptor) {
            LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
                       << "' match during associateClass, but they are different class objects. "
                          "Class descriptor collision?";
            return nullptr;
        }

        LOG(ERROR) << __func__
                   << ": Class cannot be associated on object which already has a class. Trying to "
                      "associate to '"
                   << newDescriptor.c_str() << "' but already set to '" << currentDescriptor.c_str()
                   << "'.";
        return nullptr;
    }

    String8 descriptor(getBinder()->getInterfaceDescriptor());
    if (descriptor != newDescriptor) {
        LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
                   << "' but descriptor is actually '" << descriptor.c_str() << "'.";
        return nullptr;
    }

    // The descriptor matches, so if it is local, this is guaranteed to be the libbinder_ndk class.
    // An error here can occur if there is a conflict between descriptors (two unrelated classes
    // define the same descriptor), but this should never happen.

    // if this is a local ABBinder, mClazz should be non-null
    CHECK(asABBinder() == nullptr);
    CHECK(asABpBinder() != nullptr);

    if (!isRemote()) {
        // ABpBinder but proxy to a local object. Therefore that local object must be an ABBinder.
        ABBinder* binder = static_cast<ABBinder*>(getBinder().get());
        return binder;
    }

    // This is a remote object
    mClazz = clazz;

    return this;
}

ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
      : AIBinder(clazz), BBinder(), mUserData(userData) {
    CHECK(clazz != nullptr);
}
ABBinder::~ABBinder() {
    getClass()->onDestroy(mUserData);
}

const String16& ABBinder::getInterfaceDescriptor() const {
    return getClass()->getInterfaceDescriptor();
}

binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
                                     binder_flags_t flags) {
    if (isUserCommand(code)) {
        if (!data.checkInterface(this)) {
            return EX_ILLEGAL_STATE;
        }

        const AParcel in = AParcel::readOnly(this, &data);
        AParcel out = AParcel(this, reply, false /*owns*/);

        return getClass()->onTransact(this, code, &in, &out);
    } else {
        return BBinder::onTransact(code, data, reply, flags);
    }
}

ABpBinder::ABpBinder(::android::sp<::android::IBinder> binder)
      : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
    CHECK(binder != nullptr);
}
ABpBinder::~ABpBinder() {}

struct AIBinder_Weak {
    wp<AIBinder> binder;
};
AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
    if (binder == nullptr) return nullptr;
    return new AIBinder_Weak{wp<AIBinder>(binder)};
}
void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
    delete weakBinder;
}
AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
    if (weakBinder == nullptr) return nullptr;
    sp<AIBinder> binder = weakBinder->binder.promote();
    AIBinder_incStrong(binder.get());
    return binder.get();
}

AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
                               AIBinder_Class_onDestroy onDestroy,
                               AIBinder_Class_onTransact onTransact)
      : onCreate(onCreate),
        onDestroy(onDestroy),
        onTransact(onTransact),
        mInterfaceDescriptor(interfaceDescriptor) {}

AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
                                      AIBinder_Class_onCreate onCreate,
                                      AIBinder_Class_onDestroy onDestroy,
                                      AIBinder_Class_onTransact onTransact) {
    if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr ||
        onTransact == nullptr) {
        return nullptr;
    }

    return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
}

AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
    if (clazz == nullptr) {
        LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
        return nullptr;
    }

    void* userData = clazz->onCreate(args);

    AIBinder* ret = new ABBinder(clazz, userData);
    AIBinder_incStrong(ret);
    return ret;
}

bool AIBinder_isRemote(AIBinder* binder) {
    if (binder == nullptr) {
        return true;
    }

    return binder->isRemote();
}

void AIBinder_incStrong(AIBinder* binder) {
    if (binder == nullptr) {
        LOG(ERROR) << __func__ << ": on null binder";
        return;
    }

    binder->incStrong(nullptr);
}
void AIBinder_decStrong(AIBinder* binder) {
    if (binder == nullptr) {
        LOG(ERROR) << __func__ << ": on null binder";
        return;
    }

    binder->decStrong(nullptr);
}
int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
    if (binder == nullptr) {
        LOG(ERROR) << __func__ << ": on null binder";
        return -1;
    }

    return binder->getStrongCount();
}

void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz) {
    if (binder == nullptr || *binder == nullptr) {
        return;
    }

    sp<AIBinder> result = (*binder)->associateClass(clazz);

    // This function takes one refcount of 'binder' and delivers one refcount of 'result' to the
    // callee. First we give the callee their refcount and then take it away from binder. This is
    // done in this order in order to handle the case that the result and the binder are the same
    // object.
    if (result != nullptr) {
        AIBinder_incStrong(result.get());
    }
    AIBinder_decStrong(*binder);

    *binder = result.get(); // Maybe no-op
}

const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
    if (binder == nullptr) {
        return nullptr;
    }

    return binder->getClass();
}

void* AIBinder_getUserData(AIBinder* binder) {
    if (binder == nullptr) {
        return nullptr;
    }

    ABBinder* bBinder = binder->asABBinder();
    if (bBinder == nullptr) {
        return nullptr;
    }

    return bBinder->getUserData();
}

binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
    if (binder == nullptr || in == nullptr) {
        LOG(ERROR) << __func__ << ": requires non-null parameters.";
        return EX_NULL_POINTER;
    }
    const AIBinder_Class* clazz = binder->getClass();
    if (clazz == nullptr) {
        LOG(ERROR) << __func__
                   << ": Class must be defined for a remote binder transaction. See "
                      "AIBinder_associateClass.";
        return EX_ILLEGAL_STATE;
    }

    *in = new AParcel(binder);
    binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
    if (status != EX_NONE) {
        delete *in;
        *in = nullptr;
    }

    return status;
}

using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
static void destroy_parcel(AParcel** parcel) {
    delete *parcel;
    *parcel = nullptr;
}

binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
                                  AParcel** out, binder_flags_t flags) {
    if (in == nullptr) {
        LOG(ERROR) << __func__ << ": requires non-null in parameter";
        return EX_NULL_POINTER;
    }

    // This object is the input to the transaction. This function takes ownership of it and deletes
    // it.
    AutoParcelDestroyer forIn(in, destroy_parcel);

    if (!isUserCommand(code)) {
        LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
        return EX_UNSUPPORTED_OPERATION;
    }

    if ((flags & ~FLAG_ONEWAY) != 0) {
        LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
        return EX_ILLEGAL_ARGUMENT;
    }

    if (binder == nullptr || *in == nullptr || out == nullptr) {
        LOG(ERROR) << __func__ << ": requires non-null parameters.";
        return EX_NULL_POINTER;
    }

    if ((*in)->getBinder() != binder) {
        LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
                   << " but called with " << (*in)->getBinder();
        return EX_ILLEGAL_STATE;
    }

    *out = new AParcel(binder);

    binder_status_t parcelStatus =
            binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags);

    if (parcelStatus != EX_NONE) {
        delete *out;
        *out = nullptr;
    }

    return parcelStatus;
}

binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out) {
    if (out == nullptr) {
        LOG(ERROR) << __func__ << ": requires non-null out parameter";
        return EX_NULL_POINTER;
    }

    // This object is the input to the transaction. This function takes ownership of it and deletes
    // it.
    AutoParcelDestroyer forOut(out, destroy_parcel);

    if (binder == nullptr || *out == nullptr) {
        LOG(ERROR) << __func__ << ": requires non-null parameters.";
        return EX_NULL_POINTER;
    }

    if ((*out)->getBinder() != binder) {
        LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
                   << " but called with " << (*out)->getBinder();
        return EX_ILLEGAL_STATE;
    }

    if ((**out)->dataAvail() != 0) {
        LOG(ERROR) << __func__
                   << ": Only part of this transaction was read. There is remaining data left.";
        return EX_ILLEGAL_STATE;
    }

    return EX_NONE;
}
+109 −0
Original line number Original line 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.
 */

#pragma once

#include <android/binder_ibinder.h>
#include "AIBinder_internal.h"

#include <atomic>

#include <binder/Binder.h>
#include <binder/IBinder.h>

inline bool isUserCommand(transaction_code_t code) {
    return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION;
}

struct ABBinder;
struct ABpBinder;

struct AIBinder : public virtual ::android::RefBase {
    AIBinder(const AIBinder_Class* clazz);
    virtual ~AIBinder();

    // This returns an AIBinder object with this class associated. If the class is already
    // associated, 'this' will be returned. If there is a local AIBinder implementation, that will
    // be returned. If this is a remote object, the class will be associated and this will be ready
    // to be used for transactions.
    ::android::sp<AIBinder> associateClass(const AIBinder_Class* clazz);
    const AIBinder_Class* getClass() const { return mClazz; }

    // This does not create the binder if it does not exist in the process.
    virtual ::android::sp<::android::IBinder> getBinder() = 0;
    virtual ABBinder* asABBinder() { return nullptr; }
    virtual ABpBinder* asABpBinder() { return nullptr; }

    bool isRemote() {
        auto binder = getBinder();
        // if the binder is nullptr, then it is a local object which hasn't been sent out of process
        // yet.
        return binder != nullptr && binder->remoteBinder() != nullptr;
    }

private:
    // AIBinder instance is instance of this class for a local object. In order to transact on a
    // remote object, this also must be set for simplicity (although right now, only the
    // interfaceDescriptor from it is used).
    const AIBinder_Class* mClazz;
};

// This is a local AIBinder object with a known class.
struct ABBinder : public AIBinder, public ::android::BBinder {
    ABBinder(const AIBinder_Class* clazz, void* userData);
    virtual ~ABBinder();

    void* getUserData() { return mUserData; }

    ::android::sp<::android::IBinder> getBinder() override { return this; }
    ABBinder* asABBinder() override { return this; }

    const ::android::String16& getInterfaceDescriptor() const override;
    binder_status_t onTransact(uint32_t code, const ::android::Parcel& data,
                               ::android::Parcel* reply, binder_flags_t flags) override;

private:
    // Can contain implementation if this is a local binder. This can still be nullptr for a local
    // binder. If it is nullptr, the implication is the implementation state is entirely external to
    // this object and the functionality provided in the AIBinder_Class is sufficient.
    void* mUserData;
};

// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
// a class.
struct ABpBinder : public AIBinder, public ::android::BpRefBase {
    ABpBinder(::android::sp<::android::IBinder> binder);
    virtual ~ABpBinder();

    ::android::sp<::android::IBinder> getBinder() override { return remote(); }
    ABpBinder* asABpBinder() override { return this; }
};

struct AIBinder_Class {
    AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
                   AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);

    const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }

    const AIBinder_Class_onCreate onCreate;
    const AIBinder_Class_onDestroy onDestroy;
    const AIBinder_Class_onTransact onTransact;

private:
    // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
    // one.
    const ::android::String16 mInterfaceDescriptor;
};
+127 −0
Original line number Original line 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.
 */

#include <android/binder_parcel.h>
#include "AParcel_internal.h"

#include "AIBinder_internal.h"

#include <binder/Parcel.h>

using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;

binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
    return (*parcel)->writeStrongBinder(binder->getBinder());
}
binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
    sp<IBinder> readBinder = nullptr;
    binder_status_t status = (*parcel)->readStrongBinder(&readBinder);
    if (status != EX_NONE) {
        return status;
    }
    *binder = new ABpBinder(readBinder);
    AIBinder_incStrong(*binder);
    return status;
}
binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
    sp<IBinder> readBinder = nullptr;
    binder_status_t status = (*parcel)->readNullableStrongBinder(&readBinder);
    if (status != EX_NONE) {
        return status;
    }
    *binder = new ABpBinder(readBinder);
    AIBinder_incStrong(*binder);
    return status;
}

// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
// libbinder and this library.
// @START
binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
    return (*parcel)->writeInt32(value);
}

binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
    return (*parcel)->writeUint32(value);
}

binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
    return (*parcel)->writeInt64(value);
}

binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
    return (*parcel)->writeUint64(value);
}

binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
    return (*parcel)->writeFloat(value);
}

binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
    return (*parcel)->writeDouble(value);
}

binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
    return (*parcel)->writeBool(value);
}

binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
    return (*parcel)->writeChar(value);
}

binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
    return (*parcel)->writeByte(value);
}

binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
    return (*parcel)->readInt32(value);
}

binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
    return (*parcel)->readUint32(value);
}

binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
    return (*parcel)->readInt64(value);
}

binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
    return (*parcel)->readUint64(value);
}

binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
    return (*parcel)->readFloat(value);
}

binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
    return (*parcel)->readDouble(value);
}

binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
    return (*parcel)->readBool(value);
}

binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
    return (*parcel)->readChar(value);
}

binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
    return (*parcel)->readByte(value);
}

// @END
+53 −0
Original line number Original line 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.
 */

#pragma once

#include <android/binder_parcel.h>

#include <sys/cdefs.h>

#include <binder/Parcel.h>
#include "AIBinder_internal.h"

struct AParcel {
    const ::android::Parcel* operator->() const { return mParcel; }
    ::android::Parcel* operator->() { return mParcel; }

    AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
    AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
          : mBinder(binder), mParcel(parcel), mOwns(owns) {}

    ~AParcel() {
        if (mOwns) {
            delete mParcel;
        }
    }

    static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
        return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
    }

    const AIBinder* getBinder() { return mBinder; }

private:
    // This object is associated with a calls to a specific AIBinder object. This is used for sanity
    // checking to make sure that a parcel is one that is expected.
    const AIBinder* mBinder;

    ::android::Parcel* mParcel;
    bool mOwns;
};
Loading