You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.6 KiB
187 lines
5.6 KiB
/*
|
|
* 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-base/logging.h>
|
|
#include <android/binder_manager.h>
|
|
#include <iface/iface.h>
|
|
|
|
#include <android/binder_auto_utils.h>
|
|
|
|
using ::android::sp;
|
|
using ::android::wp;
|
|
|
|
const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
|
|
const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
|
|
const char* IFoo::kIFooDescriptor = "my-special-IFoo-class";
|
|
|
|
struct IFoo_Class_Data {
|
|
sp<IFoo> foo;
|
|
};
|
|
|
|
void* IFoo_Class_onCreate(void* args) {
|
|
IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
|
|
// This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
|
|
// coupled with this.
|
|
return static_cast<void*>(foo);
|
|
}
|
|
|
|
void IFoo_Class_onDestroy(void* userData) {
|
|
delete static_cast<IFoo_Class_Data*>(userData);
|
|
}
|
|
|
|
binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
|
|
AParcel* out) {
|
|
binder_status_t stat = STATUS_FAILED_TRANSACTION;
|
|
|
|
sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
|
|
CHECK(foo != nullptr) << "Transaction made on already deleted object";
|
|
|
|
switch (code) {
|
|
case IFoo::DOFOO: {
|
|
int32_t valueIn;
|
|
int32_t valueOut;
|
|
stat = AParcel_readInt32(in, &valueIn);
|
|
if (stat != STATUS_OK) break;
|
|
stat = foo->doubleNumber(valueIn, &valueOut);
|
|
if (stat != STATUS_OK) break;
|
|
stat = AParcel_writeInt32(out, valueOut);
|
|
break;
|
|
}
|
|
case IFoo::DIE: {
|
|
stat = foo->die();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return stat;
|
|
}
|
|
|
|
AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
|
|
IFoo_Class_onDestroy, IFoo_Class_onTransact);
|
|
|
|
class BpFoo : public IFoo {
|
|
public:
|
|
explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
|
|
virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
|
|
|
|
virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
|
|
binder_status_t stat = STATUS_OK;
|
|
|
|
AParcel* parcelIn;
|
|
stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
|
|
if (stat != STATUS_OK) return stat;
|
|
|
|
stat = AParcel_writeInt32(parcelIn, in);
|
|
if (stat != STATUS_OK) return stat;
|
|
|
|
::ndk::ScopedAParcel parcelOut;
|
|
stat = AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, parcelOut.getR(), 0 /*flags*/);
|
|
if (stat != STATUS_OK) return stat;
|
|
|
|
stat = AParcel_readInt32(parcelOut.get(), out);
|
|
if (stat != STATUS_OK) return stat;
|
|
|
|
return stat;
|
|
}
|
|
|
|
virtual binder_status_t die() {
|
|
binder_status_t stat = STATUS_OK;
|
|
|
|
AParcel* parcelIn;
|
|
stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
|
|
|
|
::ndk::ScopedAParcel parcelOut;
|
|
stat = AIBinder_transact(mBinder, IFoo::DIE, &parcelIn, parcelOut.getR(), 0 /*flags*/);
|
|
|
|
return stat;
|
|
}
|
|
|
|
private:
|
|
// Always assumes one refcount
|
|
AIBinder* mBinder;
|
|
};
|
|
|
|
IFoo::~IFoo() {
|
|
AIBinder_Weak_delete(mWeakBinder);
|
|
}
|
|
|
|
AIBinder* IFoo::getBinder() {
|
|
AIBinder* binder = nullptr;
|
|
|
|
if (mWeakBinder != nullptr) {
|
|
// one strong ref count of binder
|
|
binder = AIBinder_Weak_promote(mWeakBinder);
|
|
}
|
|
if (binder == nullptr) {
|
|
// or one strong refcount here
|
|
binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
|
|
if (mWeakBinder != nullptr) {
|
|
AIBinder_Weak_delete(mWeakBinder);
|
|
}
|
|
mWeakBinder = AIBinder_Weak_new(binder);
|
|
|
|
// WARNING: it is important that this class does not implement debug or
|
|
// shell functions because it does not use special C++ wrapper
|
|
// functions, and so this is how we test those functions.
|
|
}
|
|
|
|
return binder;
|
|
}
|
|
|
|
binder_status_t IFoo::addService(const char* instance) {
|
|
AIBinder* binder = getBinder();
|
|
|
|
binder_status_t status = AServiceManager_addService(binder, instance);
|
|
// Strong references we care about kept by remote process
|
|
AIBinder_decStrong(binder);
|
|
return status;
|
|
}
|
|
|
|
sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
|
|
AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
|
|
if (binder == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!AIBinder_associateClass(binder, IFoo::kClass)) {
|
|
AIBinder_decStrong(binder);
|
|
return nullptr;
|
|
}
|
|
|
|
if (outBinder != nullptr) {
|
|
AIBinder_incStrong(binder);
|
|
*outBinder = binder;
|
|
}
|
|
|
|
if (AIBinder_isRemote(binder)) {
|
|
sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
|
|
return ret;
|
|
}
|
|
|
|
IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
|
|
|
|
CHECK(data != nullptr); // always created with non-null data
|
|
|
|
sp<IFoo> ret = data->foo;
|
|
|
|
AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
|
|
CHECK(held == binder);
|
|
AIBinder_decStrong(held);
|
|
|
|
AIBinder_decStrong(binder);
|
|
return ret;
|
|
}
|