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#include <hwbinder/Binder.h>
18
19#include <atomic>
20#include <utils/misc.h>
21#include <hwbinder/BpHwBinder.h>
22#include <hwbinder/IInterface.h>
23#include <hwbinder/Parcel.h>
24
25#include <sched.h>
26#include <stdio.h>
27
28namespace android {
29namespace hardware {
30
31// ---------------------------------------------------------------------------
32
33IBinder::IBinder()
34    : RefBase()
35{
36}
37
38IBinder::~IBinder()
39{
40}
41
42// ---------------------------------------------------------------------------
43
44BHwBinder* IBinder::localBinder()
45{
46    return NULL;
47}
48
49BpHwBinder* IBinder::remoteBinder()
50{
51    return NULL;
52}
53
54bool IBinder::checkSubclass(const void* /*subclassID*/) const
55{
56    return false;
57}
58
59// ---------------------------------------------------------------------------
60
61class BHwBinder::Extras
62{
63public:
64    Mutex mLock;
65    BpHwBinder::ObjectManager mObjects;
66};
67
68// ---------------------------------------------------------------------------
69
70BHwBinder::BHwBinder() : mSchedPolicy(SCHED_NORMAL), mSchedPriority(0), mExtras(nullptr)
71{
72}
73
74int BHwBinder::getMinSchedulingPolicy() {
75    return mSchedPolicy;
76}
77
78int BHwBinder::getMinSchedulingPriority() {
79    return mSchedPriority;
80}
81
82status_t BHwBinder::transact(
83    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback callback)
84{
85    data.setDataPosition(0);
86
87    status_t err = NO_ERROR;
88    switch (code) {
89        default:
90            err = onTransact(code, data, reply, flags,
91                    [&](auto &replyParcel) {
92                        replyParcel.setDataPosition(0);
93                        if (callback != NULL) {
94                            callback(replyParcel);
95                        }
96                    });
97            break;
98    }
99
100    return err;
101}
102
103status_t BHwBinder::linkToDeath(
104    const sp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
105    uint32_t /*flags*/)
106{
107    return INVALID_OPERATION;
108}
109
110status_t BHwBinder::unlinkToDeath(
111    const wp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
112    uint32_t /*flags*/, wp<DeathRecipient>* /*outRecipient*/)
113{
114    return INVALID_OPERATION;
115}
116
117void BHwBinder::attachObject(
118    const void* objectID, void* object, void* cleanupCookie,
119    object_cleanup_func func)
120{
121    Extras* e = mExtras.load(std::memory_order_acquire);
122
123    if (!e) {
124        e = new Extras;
125        Extras* expected = nullptr;
126        if (!mExtras.compare_exchange_strong(expected, e,
127                                             std::memory_order_release,
128                                             std::memory_order_acquire)) {
129            delete e;
130            e = expected;  // Filled in by CAS
131        }
132        if (e == 0) return; // out of memory
133    }
134
135    AutoMutex _l(e->mLock);
136    e->mObjects.attach(objectID, object, cleanupCookie, func);
137}
138
139void* BHwBinder::findObject(const void* objectID) const
140{
141    Extras* e = mExtras.load(std::memory_order_acquire);
142    if (!e) return NULL;
143
144    AutoMutex _l(e->mLock);
145    return e->mObjects.find(objectID);
146}
147
148void BHwBinder::detachObject(const void* objectID)
149{
150    Extras* e = mExtras.load(std::memory_order_acquire);
151    if (!e) return;
152
153    AutoMutex _l(e->mLock);
154    e->mObjects.detach(objectID);
155}
156
157BHwBinder* BHwBinder::localBinder()
158{
159    return this;
160}
161
162BHwBinder::~BHwBinder()
163{
164    Extras* e = mExtras.load(std::memory_order_relaxed);
165    if (e) delete e;
166}
167
168
169status_t BHwBinder::onTransact(
170    uint32_t /*code*/, const Parcel& /*data*/, Parcel* /*reply*/, uint32_t /*flags*/,
171    TransactCallback /*callback*/)
172{
173    return UNKNOWN_TRANSACTION;
174}
175
176// ---------------------------------------------------------------------------
177
178enum {
179    // This is used to transfer ownership of the remote binder from
180    // the BpHwRefBase object holding it (when it is constructed), to the
181    // owner of the BpHwRefBase object when it first acquires that BpHwRefBase.
182    kRemoteAcquired = 0x00000001
183};
184
185BpHwRefBase::BpHwRefBase(const sp<IBinder>& o)
186    : mRemote(o.get()), mRefs(NULL), mState(0)
187{
188    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
189
190    if (mRemote) {
191        mRemote->incStrong(this);           // Removed on first IncStrong().
192        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
193    }
194}
195
196BpHwRefBase::~BpHwRefBase()
197{
198    if (mRemote) {
199        if (!(mState.load(std::memory_order_relaxed)&kRemoteAcquired)) {
200            mRemote->decStrong(this);
201        }
202        mRefs->decWeak(this);
203    }
204}
205
206void BpHwRefBase::onFirstRef()
207{
208    mState.fetch_or(kRemoteAcquired, std::memory_order_relaxed);
209}
210
211void BpHwRefBase::onLastStrongRef(const void* /*id*/)
212{
213    if (mRemote) {
214        mRemote->decStrong(this);
215    }
216}
217
218bool BpHwRefBase::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
219{
220    return mRemote ? mRefs->attemptIncStrong(this) : false;
221}
222
223// ---------------------------------------------------------------------------
224
225}; // namespace hardware
226}; // namespace android
227