1 /*
2  * Copyright (C) 2005 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 #define LOG_TAG "hw-BpHwBinder"
18 //#define LOG_NDEBUG 0
19 
20 #include <hwbinder/BpHwBinder.h>
21 
22 #include <hwbinder/IPCThreadState.h>
23 #include <utils/Log.h>
24 
25 #include <stdio.h>
26 
27 //#undef ALOGV
28 //#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
29 
30 namespace android {
31 namespace hardware {
32 
33 // ---------------------------------------------------------------------------
34 
ObjectManager()35 BpHwBinder::ObjectManager::ObjectManager()
36 {
37 }
38 
~ObjectManager()39 BpHwBinder::ObjectManager::~ObjectManager()
40 {
41     kill();
42 }
43 
attach(const void * objectID,void * object,void * cleanupCookie,IBinder::object_cleanup_func func)44 void BpHwBinder::ObjectManager::attach(
45     const void* objectID, void* object, void* cleanupCookie,
46     IBinder::object_cleanup_func func)
47 {
48     entry_t e;
49     e.object = object;
50     e.cleanupCookie = cleanupCookie;
51     e.func = func;
52 
53     if (mObjects.indexOfKey(objectID) >= 0) {
54         ALOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
55                 objectID, this,  object);
56         return;
57     }
58 
59     mObjects.add(objectID, e);
60 }
61 
find(const void * objectID) const62 void* BpHwBinder::ObjectManager::find(const void* objectID) const
63 {
64     const ssize_t i = mObjects.indexOfKey(objectID);
65     if (i < 0) return nullptr;
66     return mObjects.valueAt(i).object;
67 }
68 
detach(const void * objectID)69 void BpHwBinder::ObjectManager::detach(const void* objectID)
70 {
71     mObjects.removeItem(objectID);
72 }
73 
kill()74 void BpHwBinder::ObjectManager::kill()
75 {
76     const size_t N = mObjects.size();
77     ALOGV("Killing %zu objects in manager %p", N, this);
78     for (size_t i=0; i<N; i++) {
79         const entry_t& e = mObjects.valueAt(i);
80         if (e.func != nullptr) {
81             e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
82         }
83     }
84 
85     mObjects.clear();
86 }
87 
88 // ---------------------------------------------------------------------------
89 
BpHwBinder(int32_t handle)90 BpHwBinder::BpHwBinder(int32_t handle)
91     : mHandle(handle)
92     , mAlive(1)
93     , mObitsSent(0)
94     , mObituaries(nullptr)
95 {
96     ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
97 
98     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
99     IPCThreadState::self()->incWeakHandle(handle, this);
100 }
101 
transact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags,TransactCallback callback)102 status_t BpHwBinder::transact(
103     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback callback)
104 {
105     // Once a binder has died, it will never come back to life.
106     if (mAlive) {
107         status_t status = IPCThreadState::self()->transact(
108             mHandle, code, data, reply, flags);
109 
110         if (status == ::android::OK && callback != nullptr) {
111             callback(*reply);
112         }
113 
114         if (status == DEAD_OBJECT) mAlive = 0;
115         return status;
116     }
117 
118     return DEAD_OBJECT;
119 }
120 
linkToDeath(const sp<DeathRecipient> & recipient,void * cookie,uint32_t flags)121 status_t BpHwBinder::linkToDeath(
122     const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
123 {
124     Obituary ob;
125     ob.recipient = recipient;
126     ob.cookie = cookie;
127     ob.flags = flags;
128 
129     LOG_ALWAYS_FATAL_IF(recipient == nullptr,
130                         "linkToDeath(): recipient must be non-NULL");
131 
132     {
133         AutoMutex _l(mLock);
134 
135         if (!mObitsSent) {
136             if (!mObituaries) {
137                 mObituaries = new Vector<Obituary>;
138                 if (!mObituaries) {
139                     return NO_MEMORY;
140                 }
141                 ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
142                 getWeakRefs()->incWeak(this);
143                 IPCThreadState* self = IPCThreadState::self();
144                 self->requestDeathNotification(mHandle, this);
145                 self->flushCommands();
146             }
147             ssize_t res = mObituaries->add(ob);
148             return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
149         }
150     }
151 
152     return DEAD_OBJECT;
153 }
154 
unlinkToDeath(const wp<DeathRecipient> & recipient,void * cookie,uint32_t flags,wp<DeathRecipient> * outRecipient)155 status_t BpHwBinder::unlinkToDeath(
156     const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
157     wp<DeathRecipient>* outRecipient)
158 {
159     AutoMutex _l(mLock);
160 
161     if (mObitsSent) {
162         return DEAD_OBJECT;
163     }
164 
165     const size_t N = mObituaries ? mObituaries->size() : 0;
166     for (size_t i=0; i<N; i++) {
167         const Obituary& obit = mObituaries->itemAt(i);
168         if ((obit.recipient == recipient
169                     || (recipient == nullptr && obit.cookie == cookie))
170                 && obit.flags == flags) {
171             if (outRecipient != nullptr) {
172                 *outRecipient = mObituaries->itemAt(i).recipient;
173             }
174             mObituaries->removeAt(i);
175             if (mObituaries->size() == 0) {
176                 ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
177                 IPCThreadState* self = IPCThreadState::self();
178                 self->clearDeathNotification(mHandle, this);
179                 self->flushCommands();
180                 delete mObituaries;
181                 mObituaries = nullptr;
182             }
183             return NO_ERROR;
184         }
185     }
186 
187     return NAME_NOT_FOUND;
188 }
189 
sendObituary()190 void BpHwBinder::sendObituary()
191 {
192     ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
193         this, mHandle, mObitsSent ? "true" : "false");
194 
195     mAlive = 0;
196     if (mObitsSent) return;
197 
198     mLock.lock();
199     Vector<Obituary>* obits = mObituaries;
200     if(obits != nullptr) {
201         ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
202         IPCThreadState* self = IPCThreadState::self();
203         self->clearDeathNotification(mHandle, this);
204         self->flushCommands();
205         mObituaries = nullptr;
206     }
207     mObitsSent = 1;
208     mLock.unlock();
209 
210     ALOGV("Reporting death of proxy %p for %zu recipients\n",
211         this, obits ? obits->size() : 0U);
212 
213     if (obits != nullptr) {
214         const size_t N = obits->size();
215         for (size_t i=0; i<N; i++) {
216             reportOneDeath(obits->itemAt(i));
217         }
218 
219         delete obits;
220     }
221 }
222 
223 // Returns the strong refcount on the object this proxy points to, or
224 // -1 in case of failure.
getNodeStrongRefCount()225 ssize_t BpHwBinder::getNodeStrongRefCount()
226 {
227     return ProcessState::self()->getStrongRefCountForNodeByHandle(mHandle);
228 }
229 
reportOneDeath(const Obituary & obit)230 void BpHwBinder::reportOneDeath(const Obituary& obit)
231 {
232     sp<DeathRecipient> recipient = obit.recipient.promote();
233     ALOGV("Reporting death to recipient: %p\n", recipient.get());
234     if (recipient == nullptr) return;
235 
236     recipient->binderDied(this);
237 }
238 
239 
attachObject(const void * objectID,void * object,void * cleanupCookie,object_cleanup_func func)240 void BpHwBinder::attachObject(
241     const void* objectID, void* object, void* cleanupCookie,
242     object_cleanup_func func)
243 {
244     AutoMutex _l(mLock);
245     ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
246     mObjects.attach(objectID, object, cleanupCookie, func);
247 }
248 
findObject(const void * objectID) const249 void* BpHwBinder::findObject(const void* objectID) const
250 {
251     AutoMutex _l(mLock);
252     return mObjects.find(objectID);
253 }
254 
detachObject(const void * objectID)255 void BpHwBinder::detachObject(const void* objectID)
256 {
257     AutoMutex _l(mLock);
258     mObjects.detach(objectID);
259 }
260 
remoteBinder()261 BpHwBinder* BpHwBinder::remoteBinder()
262 {
263     return this;
264 }
265 
~BpHwBinder()266 BpHwBinder::~BpHwBinder()
267 {
268     ALOGV("Destroying BpHwBinder %p handle %d\n", this, mHandle);
269 
270     IPCThreadState* ipc = IPCThreadState::self();
271 
272     if (ipc) {
273         ipc->expungeHandle(mHandle, this);
274         ipc->decWeakHandle(mHandle);
275     }
276 }
277 
onFirstRef()278 void BpHwBinder::onFirstRef()
279 {
280     ALOGV("onFirstRef BpHwBinder %p handle %d\n", this, mHandle);
281     IPCThreadState* ipc = IPCThreadState::self();
282     if (ipc) ipc->incStrongHandle(mHandle, this);
283 }
284 
onLastStrongRef(const void *)285 void BpHwBinder::onLastStrongRef(const void* /*id*/)
286 {
287     ALOGV("onLastStrongRef BpHwBinder %p handle %d\n", this, mHandle);
288     IF_ALOGV() {
289         printRefs();
290     }
291     IPCThreadState* ipc = IPCThreadState::self();
292     if (ipc) {
293         ipc->decStrongHandle(mHandle);
294         ipc->flushCommands();
295     }
296 
297     mLock.lock();
298     Vector<Obituary>* obits = mObituaries;
299     if(obits != nullptr) {
300         if (!obits->isEmpty()) {
301             ALOGI("onLastStrongRef automatically unlinking death recipients");
302         }
303 
304         if (ipc) ipc->clearDeathNotification(mHandle, this);
305         mObituaries = nullptr;
306     }
307     mLock.unlock();
308 
309     if (obits != nullptr) {
310         // XXX Should we tell any remaining DeathRecipient
311         // objects that the last strong ref has gone away, so they
312         // are no longer linked?
313         delete obits;
314         obits = nullptr;
315     }
316 }
317 
onIncStrongAttempted(uint32_t,const void *)318 bool BpHwBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
319 {
320     ALOGV("onIncStrongAttempted BpHwBinder %p handle %d\n", this, mHandle);
321     IPCThreadState* ipc = IPCThreadState::self();
322     return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
323 }
324 
325 // ---------------------------------------------------------------------------
326 
327 } // namespace hardware
328 } // namespace android
329