| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2018 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #include <android-base/logging.h> | 
|  | 18 | #include <android/binder_manager.h> | 
|  | 19 | #include <iface/iface.h> | 
|  | 20 |  | 
|  | 21 | using ::android::sp; | 
|  | 22 | using ::android::wp; | 
|  | 23 |  | 
|  | 24 | const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo"; | 
|  | 25 | const char* kIFooDescriptor = "my-special-IFoo-class"; | 
|  | 26 |  | 
|  | 27 | struct IFoo_Class_Data { | 
|  | 28 | sp<IFoo> foo; | 
|  | 29 | }; | 
|  | 30 |  | 
|  | 31 | void* IFoo_Class_onCreate(void* args) { | 
|  | 32 | IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args); | 
|  | 33 | // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is | 
|  | 34 | // coupled with this. | 
|  | 35 | return static_cast<void*>(foo); | 
|  | 36 | } | 
|  | 37 |  | 
|  | 38 | void IFoo_Class_onDestroy(void* userData) { | 
|  | 39 | delete static_cast<IFoo_Class_Data*>(userData); | 
|  | 40 | } | 
|  | 41 |  | 
|  | 42 | binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in, | 
|  | 43 | AParcel* out) { | 
| Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 44 | binder_status_t stat = STATUS_FAILED_TRANSACTION; | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 45 |  | 
|  | 46 | sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo; | 
|  | 47 | CHECK(foo != nullptr) << "Transaction made on already deleted object"; | 
|  | 48 |  | 
|  | 49 | switch (code) { | 
|  | 50 | case IFoo::DOFOO: { | 
|  | 51 | int32_t valueIn; | 
|  | 52 | stat = AParcel_readInt32(in, &valueIn); | 
| Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 53 | if (stat != STATUS_OK) break; | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 54 | int32_t valueOut = foo->doubleNumber(valueIn); | 
|  | 55 | stat = AParcel_writeInt32(out, valueOut); | 
|  | 56 | break; | 
|  | 57 | } | 
|  | 58 | } | 
|  | 59 |  | 
|  | 60 | return stat; | 
|  | 61 | } | 
|  | 62 |  | 
|  | 63 | AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate, | 
|  | 64 | IFoo_Class_onDestroy, IFoo_Class_onTransact); | 
|  | 65 |  | 
|  | 66 | class BpFoo : public IFoo { | 
|  | 67 | public: | 
|  | 68 | BpFoo(AIBinder* binder) : mBinder(binder) {} | 
|  | 69 | virtual ~BpFoo() { AIBinder_decStrong(mBinder); } | 
|  | 70 |  | 
|  | 71 | virtual int32_t doubleNumber(int32_t in) { | 
|  | 72 | AParcel* parcelIn; | 
| Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 73 | CHECK(STATUS_OK == AIBinder_prepareTransaction(mBinder, &parcelIn)); | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 74 |  | 
| Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 75 | CHECK(STATUS_OK == AParcel_writeInt32(parcelIn, in)); | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 76 |  | 
|  | 77 | AParcel* parcelOut; | 
| Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 78 | CHECK(STATUS_OK == | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 79 | AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, &parcelOut, 0 /*flags*/)); | 
|  | 80 |  | 
|  | 81 | int32_t out; | 
| Steven Moreland | 5d62e44 | 2018-09-13 15:01:02 -0700 | [diff] [blame] | 82 | CHECK(STATUS_OK == AParcel_readInt32(parcelOut, &out)); | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 83 |  | 
| Steven Moreland | caa776c | 2018-09-04 13:48:11 -0700 | [diff] [blame] | 84 | AParcel_delete(&parcelOut); | 
|  | 85 |  | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 86 | return out; | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | private: | 
|  | 90 | // Always assumes one refcount | 
|  | 91 | AIBinder* mBinder; | 
|  | 92 | }; | 
|  | 93 |  | 
|  | 94 | IFoo::~IFoo() { | 
| Steven Moreland | 5ccb70f | 2018-09-04 16:30:21 -0700 | [diff] [blame] | 95 | AIBinder_Weak_delete(&mWeakBinder); | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 96 | } | 
|  | 97 |  | 
|  | 98 | binder_status_t IFoo::addService(const char* instance) { | 
|  | 99 | AIBinder* binder = nullptr; | 
|  | 100 |  | 
|  | 101 | if (mWeakBinder != nullptr) { | 
|  | 102 | // one strong ref count of binder | 
|  | 103 | binder = AIBinder_Weak_promote(mWeakBinder); | 
|  | 104 | } | 
|  | 105 | if (binder == nullptr) { | 
|  | 106 | // or one strong refcount here | 
|  | 107 | binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this})); | 
|  | 108 | if (mWeakBinder != nullptr) { | 
| Steven Moreland | 5ccb70f | 2018-09-04 16:30:21 -0700 | [diff] [blame] | 109 | AIBinder_Weak_delete(&mWeakBinder); | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 110 | } | 
|  | 111 | mWeakBinder = AIBinder_Weak_new(binder); | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | binder_status_t status = AServiceManager_addService(binder, instance); | 
|  | 115 | // Strong references we care about kept by remote process | 
|  | 116 | AIBinder_decStrong(binder); | 
|  | 117 | return status; | 
|  | 118 | } | 
|  | 119 |  | 
|  | 120 | sp<IFoo> IFoo::getService(const char* instance) { | 
|  | 121 | AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 122 | if (binder == nullptr) { | 
|  | 123 | return nullptr; | 
|  | 124 | } | 
|  | 125 |  | 
| Steven Moreland | 71cddc3 | 2018-08-30 23:39:22 -0700 | [diff] [blame] | 126 | if (!AIBinder_associateClass(binder, IFoo::kClass)) { | 
|  | 127 | AIBinder_decStrong(binder); | 
|  | 128 | return nullptr; | 
|  | 129 | } | 
|  | 130 |  | 
| Steven Moreland | 2e87adc | 2018-08-20 19:47:00 -0700 | [diff] [blame] | 131 | if (AIBinder_isRemote(binder)) { | 
|  | 132 | sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder | 
|  | 133 | return ret; | 
|  | 134 | } | 
|  | 135 |  | 
|  | 136 | IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder)); | 
|  | 137 |  | 
|  | 138 | CHECK(data != nullptr); // always created with non-null data | 
|  | 139 |  | 
|  | 140 | sp<IFoo> ret = data->foo; | 
|  | 141 |  | 
|  | 142 | AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder); | 
|  | 143 | CHECK(held == binder); | 
|  | 144 | AIBinder_decStrong(held); | 
|  | 145 |  | 
|  | 146 | // IFoo only keeps a weak reference to AIBinder, so we can drop this | 
|  | 147 | AIBinder_decStrong(binder); | 
|  | 148 | return ret; | 
|  | 149 | } |