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* 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 class BpFoo : public IFoo {
76    public:
BpFoo(AIBinder * binder)77     explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
~BpFoo()78     virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
79 
doubleNumber(int32_t in,int32_t * out)80     virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
81         binder_status_t stat = STATUS_OK;
82 
83         AParcel* parcelIn;
84         stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
85         if (stat != STATUS_OK) return stat;
86 
87         stat = AParcel_writeInt32(parcelIn, in);
88         if (stat != STATUS_OK) return stat;
89 
90         ::ndk::ScopedAParcel parcelOut;
91         stat = AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, parcelOut.getR(), 0 /*flags*/);
92         if (stat != STATUS_OK) return stat;
93 
94         stat = AParcel_readInt32(parcelOut.get(), out);
95         if (stat != STATUS_OK) return stat;
96 
97         return stat;
98     }
99 
die()100     virtual binder_status_t die() {
101         binder_status_t stat = STATUS_OK;
102 
103         AParcel* parcelIn;
104         stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
105 
106         ::ndk::ScopedAParcel parcelOut;
107         stat = AIBinder_transact(mBinder, IFoo::DIE, &parcelIn, parcelOut.getR(), 0 /*flags*/);
108 
109         return stat;
110     }
111 
112    private:
113     // Always assumes one refcount
114     AIBinder* mBinder;
115 };
116 
~IFoo()117 IFoo::~IFoo() {
118     AIBinder_Weak_delete(mWeakBinder);
119 }
120 
addService(const char * instance)121 binder_status_t IFoo::addService(const char* instance) {
122     AIBinder* binder = nullptr;
123 
124     if (mWeakBinder != nullptr) {
125         // one strong ref count of binder
126         binder = AIBinder_Weak_promote(mWeakBinder);
127     }
128     if (binder == nullptr) {
129         // or one strong refcount here
130         binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
131         if (mWeakBinder != nullptr) {
132             AIBinder_Weak_delete(mWeakBinder);
133         }
134         mWeakBinder = AIBinder_Weak_new(binder);
135     }
136 
137     binder_status_t status = AServiceManager_addService(binder, instance);
138     // Strong references we care about kept by remote process
139     AIBinder_decStrong(binder);
140     return status;
141 }
142 
getService(const char * instance,AIBinder ** outBinder)143 sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
144     AIBinder* binder = AServiceManager_getService(instance);  // maybe nullptr
145     if (binder == nullptr) {
146         return nullptr;
147     }
148 
149     if (!AIBinder_associateClass(binder, IFoo::kClass)) {
150         AIBinder_decStrong(binder);
151         return nullptr;
152     }
153 
154     if (outBinder != nullptr) {
155         AIBinder_incStrong(binder);
156         *outBinder = binder;
157     }
158 
159     if (AIBinder_isRemote(binder)) {
160         sp<IFoo> ret = new BpFoo(binder);  // takes ownership of binder
161         return ret;
162     }
163 
164     IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
165 
166     CHECK(data != nullptr);  // always created with non-null data
167 
168     sp<IFoo> ret = data->foo;
169 
170     AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
171     CHECK(held == binder);
172     AIBinder_decStrong(held);
173 
174     AIBinder_decStrong(binder);
175     return ret;
176 }
177