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