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
30namespace android {
31namespace hardware {
32
33// ---------------------------------------------------------------------------
34
35BpHwBinder::ObjectManager::ObjectManager()
36{
37}
38
39BpHwBinder::ObjectManager::~ObjectManager()
40{
41    kill();
42}
43
44void 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
62void* BpHwBinder::ObjectManager::find(const void* objectID) const
63{
64    const ssize_t i = mObjects.indexOfKey(objectID);
65    if (i < 0) return NULL;
66    return mObjects.valueAt(i).object;
67}
68
69void BpHwBinder::ObjectManager::detach(const void* objectID)
70{
71    mObjects.removeItem(objectID);
72}
73
74void 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 != NULL) {
81            e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
82        }
83    }
84
85    mObjects.clear();
86}
87
88// ---------------------------------------------------------------------------
89
90BpHwBinder::BpHwBinder(int32_t handle)
91    : mHandle(handle)
92    , mAlive(1)
93    , mObitsSent(0)
94    , mObituaries(NULL)
95{
96    ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
97
98    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
99    IPCThreadState::self()->incWeakHandle(handle);
100}
101
102status_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        if (status == DEAD_OBJECT) mAlive = 0;
110        return status;
111    }
112
113    return DEAD_OBJECT;
114}
115
116status_t BpHwBinder::linkToDeath(
117    const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
118{
119    Obituary ob;
120    ob.recipient = recipient;
121    ob.cookie = cookie;
122    ob.flags = flags;
123
124    LOG_ALWAYS_FATAL_IF(recipient == NULL,
125                        "linkToDeath(): recipient must be non-NULL");
126
127    {
128        AutoMutex _l(mLock);
129
130        if (!mObitsSent) {
131            if (!mObituaries) {
132                mObituaries = new Vector<Obituary>;
133                if (!mObituaries) {
134                    return NO_MEMORY;
135                }
136                ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
137                getWeakRefs()->incWeak(this);
138                IPCThreadState* self = IPCThreadState::self();
139                self->requestDeathNotification(mHandle, this);
140                self->flushCommands();
141            }
142            ssize_t res = mObituaries->add(ob);
143            return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
144        }
145    }
146
147    return DEAD_OBJECT;
148}
149
150status_t BpHwBinder::unlinkToDeath(
151    const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
152    wp<DeathRecipient>* outRecipient)
153{
154    AutoMutex _l(mLock);
155
156    if (mObitsSent) {
157        return DEAD_OBJECT;
158    }
159
160    const size_t N = mObituaries ? mObituaries->size() : 0;
161    for (size_t i=0; i<N; i++) {
162        const Obituary& obit = mObituaries->itemAt(i);
163        if ((obit.recipient == recipient
164                    || (recipient == NULL && obit.cookie == cookie))
165                && obit.flags == flags) {
166            if (outRecipient != NULL) {
167                *outRecipient = mObituaries->itemAt(i).recipient;
168            }
169            mObituaries->removeAt(i);
170            if (mObituaries->size() == 0) {
171                ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
172                IPCThreadState* self = IPCThreadState::self();
173                self->clearDeathNotification(mHandle, this);
174                self->flushCommands();
175                delete mObituaries;
176                mObituaries = NULL;
177            }
178            return NO_ERROR;
179        }
180    }
181
182    return NAME_NOT_FOUND;
183}
184
185void BpHwBinder::sendObituary()
186{
187    ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
188        this, mHandle, mObitsSent ? "true" : "false");
189
190    mAlive = 0;
191    if (mObitsSent) return;
192
193    mLock.lock();
194    Vector<Obituary>* obits = mObituaries;
195    if(obits != NULL) {
196        ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
197        IPCThreadState* self = IPCThreadState::self();
198        self->clearDeathNotification(mHandle, this);
199        self->flushCommands();
200        mObituaries = NULL;
201    }
202    mObitsSent = 1;
203    mLock.unlock();
204
205    ALOGV("Reporting death of proxy %p for %zu recipients\n",
206        this, obits ? obits->size() : 0U);
207
208    if (obits != NULL) {
209        const size_t N = obits->size();
210        for (size_t i=0; i<N; i++) {
211            reportOneDeath(obits->itemAt(i));
212        }
213
214        delete obits;
215    }
216}
217
218void BpHwBinder::reportOneDeath(const Obituary& obit)
219{
220    sp<DeathRecipient> recipient = obit.recipient.promote();
221    ALOGV("Reporting death to recipient: %p\n", recipient.get());
222    if (recipient == NULL) return;
223
224    recipient->binderDied(this);
225}
226
227
228void BpHwBinder::attachObject(
229    const void* objectID, void* object, void* cleanupCookie,
230    object_cleanup_func func)
231{
232    AutoMutex _l(mLock);
233    ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
234    mObjects.attach(objectID, object, cleanupCookie, func);
235}
236
237void* BpHwBinder::findObject(const void* objectID) const
238{
239    AutoMutex _l(mLock);
240    return mObjects.find(objectID);
241}
242
243void BpHwBinder::detachObject(const void* objectID)
244{
245    AutoMutex _l(mLock);
246    mObjects.detach(objectID);
247}
248
249BpHwBinder* BpHwBinder::remoteBinder()
250{
251    return this;
252}
253
254BpHwBinder::~BpHwBinder()
255{
256    ALOGV("Destroying BpHwBinder %p handle %d\n", this, mHandle);
257
258    IPCThreadState* ipc = IPCThreadState::self();
259
260    mLock.lock();
261    Vector<Obituary>* obits = mObituaries;
262    if(obits != NULL) {
263        if (ipc) ipc->clearDeathNotification(mHandle, this);
264        mObituaries = NULL;
265    }
266    mLock.unlock();
267
268    if (obits != NULL) {
269        // XXX Should we tell any remaining DeathRecipient
270        // objects that the last strong ref has gone away, so they
271        // are no longer linked?
272        delete obits;
273    }
274
275    if (ipc) {
276        ipc->expungeHandle(mHandle, this);
277        ipc->decWeakHandle(mHandle);
278    }
279}
280
281void BpHwBinder::onFirstRef()
282{
283    ALOGV("onFirstRef BpHwBinder %p handle %d\n", this, mHandle);
284    IPCThreadState* ipc = IPCThreadState::self();
285    if (ipc) ipc->incStrongHandle(mHandle);
286}
287
288void BpHwBinder::onLastStrongRef(const void* /*id*/)
289{
290    ALOGV("onLastStrongRef BpHwBinder %p handle %d\n", this, mHandle);
291    IF_ALOGV() {
292        printRefs();
293    }
294    IPCThreadState* ipc = IPCThreadState::self();
295    if (ipc) {
296        ipc->decStrongHandle(mHandle);
297        ipc->flushCommands();
298    }
299}
300
301bool BpHwBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
302{
303    ALOGV("onIncStrongAttempted BpHwBinder %p handle %d\n", this, mHandle);
304    IPCThreadState* ipc = IPCThreadState::self();
305    return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
306}
307
308// ---------------------------------------------------------------------------
309
310}; // namespace hardware
311}; // namespace android
312