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 #include <android/binder_auto_utils.h>
22
23 using ::android::sp;
24 using ::android::wp;
25
26 const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
27 const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
28 const char* IFoo::kIFooDescriptor = "my-special-IFoo-class";
29
30 struct IFoo_Class_Data {
31 sp<IFoo> foo;
32 };
33
IFoo_Class_onCreate(void * args)34 void* IFoo_Class_onCreate(void* args) {
35 IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
36 // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
37 // coupled with this.
38 return static_cast<void*>(foo);
39 }
40
IFoo_Class_onDestroy(void * userData)41 void IFoo_Class_onDestroy(void* userData) {
42 delete static_cast<IFoo_Class_Data*>(userData);
43 }
44
IFoo_Class_onTransact(AIBinder * binder,transaction_code_t code,const AParcel * in,AParcel * out)45 binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
46 AParcel* out) {
47 binder_status_t stat = STATUS_FAILED_TRANSACTION;
48
49 sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
50 CHECK(foo != nullptr) << "Transaction made on already deleted object";
51
52 switch (code) {
53 case IFoo::DOFOO: {
54 int32_t valueIn;
55 int32_t valueOut;
56 stat = AParcel_readInt32(in, &valueIn);
57 if (stat != STATUS_OK) break;
58 stat = foo->doubleNumber(valueIn, &valueOut);
59 if (stat != STATUS_OK) break;
60 stat = AParcel_writeInt32(out, valueOut);
61 break;
62 }
63 case IFoo::DIE: {
64 stat = foo->die();
65 break;
66 }
67 }
68
69 return stat;
70 }
71
72 AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
73 IFoo_Class_onDestroy, IFoo_Class_onTransact);
74
75 // Defines the same class. Ordinarly, you would never want to do this, but it's done here
76 // to simulate what would happen when multiple linker namespaces interact.
77 AIBinder_Class* IFoo::kClassDupe = AIBinder_Class_define(
78 kIFooDescriptor, IFoo_Class_onCreate, IFoo_Class_onDestroy, IFoo_Class_onTransact);
79
80 class BpFoo : public IFoo {
81 public:
BpFoo(AIBinder * binder)82 explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
~BpFoo()83 virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
84
doubleNumber(int32_t in,int32_t * out)85 virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
86 binder_status_t stat = STATUS_OK;
87
88 AParcel* parcelIn;
89 stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
90 if (stat != STATUS_OK) return stat;
91
92 stat = AParcel_writeInt32(parcelIn, in);
93 if (stat != STATUS_OK) return stat;
94
95 ::ndk::ScopedAParcel parcelOut;
96 stat = AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, parcelOut.getR(), 0 /*flags*/);
97 if (stat != STATUS_OK) return stat;
98
99 stat = AParcel_readInt32(parcelOut.get(), out);
100 if (stat != STATUS_OK) return stat;
101
102 return stat;
103 }
104
die()105 virtual binder_status_t die() {
106 binder_status_t stat = STATUS_OK;
107
108 AParcel* parcelIn;
109 stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
110
111 ::ndk::ScopedAParcel parcelOut;
112 stat = AIBinder_transact(mBinder, IFoo::DIE, &parcelIn, parcelOut.getR(), 0 /*flags*/);
113
114 return stat;
115 }
116
117 private:
118 // Always assumes one refcount
119 AIBinder* mBinder;
120 };
121
~IFoo()122 IFoo::~IFoo() {
123 AIBinder_Weak_delete(mWeakBinder);
124 }
125
getBinder()126 AIBinder* IFoo::getBinder() {
127 AIBinder* binder = nullptr;
128
129 if (mWeakBinder != nullptr) {
130 // one strong ref count of binder
131 binder = AIBinder_Weak_promote(mWeakBinder);
132 }
133 if (binder == nullptr) {
134 // or one strong refcount here
135 binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
136 if (mWeakBinder != nullptr) {
137 AIBinder_Weak_delete(mWeakBinder);
138 }
139 mWeakBinder = AIBinder_Weak_new(binder);
140
141 // WARNING: it is important that this class does not implement debug or
142 // shell functions because it does not use special C++ wrapper
143 // functions, and so this is how we test those functions.
144 }
145
146 return binder;
147 }
148
addService(const char * instance)149 binder_status_t IFoo::addService(const char* instance) {
150 AIBinder* binder = getBinder();
151
152 binder_status_t status = AServiceManager_addService(binder, instance);
153 // Strong references we care about kept by remote process
154 AIBinder_decStrong(binder);
155 return status;
156 }
157
getService(const char * instance,AIBinder ** outBinder)158 sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
159 AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
160 if (binder == nullptr) {
161 return nullptr;
162 }
163
164 if (!AIBinder_associateClass(binder, IFoo::kClass)) {
165 AIBinder_decStrong(binder);
166 return nullptr;
167 }
168
169 if (outBinder != nullptr) {
170 AIBinder_incStrong(binder);
171 *outBinder = binder;
172 }
173
174 if (AIBinder_isRemote(binder)) {
175 sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
176 return ret;
177 }
178
179 IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
180
181 CHECK(data != nullptr); // always created with non-null data
182
183 sp<IFoo> ret = data->foo;
184
185 AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
186 CHECK(held == binder);
187 AIBinder_decStrong(held);
188
189 AIBinder_decStrong(binder);
190 return ret;
191 }
192