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