summaryrefslogtreecommitdiff
path: root/libs/binder/include/binder/BpBinder.h
blob: 89a4d273ad8a00c8ceb73015bea7e2f8640b6513 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
 * Copyright (C) 2005 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <binder/IBinder.h>
#include <binder/RpcThreads.h>
#include <binder/unique_fd.h>

#include <map>
#include <optional>
#include <unordered_map>
#include <variant>

// ---------------------------------------------------------------------------
namespace android {

class RpcSession;
class RpcState;
namespace internal {
class Stability;
}
class ProcessState;

using binder_proxy_limit_callback = void(*)(int);

class BpBinder : public IBinder
{
public:
    /**
     * Return value:
     * true - this is associated with a socket RpcSession
     * false - (usual) binder over e.g. /dev/binder
     */
    bool isRpcBinder() const;

    virtual const String16&    getInterfaceDescriptor() const;
    virtual bool        isBinderAlive() const;
    virtual status_t    pingBinder();
    virtual status_t    dump(int fd, const Vector<String16>& args);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0) final;

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
                                    void* cookie = nullptr,
                                    uint32_t flags = 0);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    unlinkToDeath(  const wp<DeathRecipient>& recipient,
                                        void* cookie = nullptr,
                                        uint32_t flags = 0,
                                        wp<DeathRecipient>* outRecipient = nullptr);

    virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie,
                               object_cleanup_func func) final;
    virtual void*       findObject(const void* objectID) const final;
    virtual void* detachObject(const void* objectID) final;
    void withLock(const std::function<void()>& doWithLock);
    sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
                                   const void* makeArgs);

    virtual BpBinder*   remoteBinder();

            void        sendObituary();

    static uint32_t     getBinderProxyCount(uint32_t uid);
    static void         getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
    static void         enableCountByUid();
    static void         disableCountByUid();
    static void         setCountByUidEnabled(bool enable);
    static void         setLimitCallback(binder_proxy_limit_callback cb);
    static void         setBinderProxyCountWatermarks(int high, int low);
    static uint32_t     getBinderProxyCount();

    std::optional<int32_t> getDebugBinderHandle() const;

    // Start recording transactions to the unique_fd.
    // See RecordedTransaction.h for more details.
    status_t startRecordingBinder(const binder::unique_fd& fd);
    // Stop the current recording.
    status_t stopRecordingBinder();

    class ObjectManager {
    public:
        ObjectManager();
        ~ObjectManager();

        void* attach(const void* objectID, void* object, void* cleanupCookie,
                     IBinder::object_cleanup_func func);
        void* find(const void* objectID) const;
        void* detach(const void* objectID);
        sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
                                       const void* makeArgs);

        void kill();

    private:
        ObjectManager(const ObjectManager&);
        ObjectManager& operator=(const ObjectManager&);

        struct entry_t {
            void* object = nullptr;
            void* cleanupCookie = nullptr;
            IBinder::object_cleanup_func func = nullptr;
        };

        std::map<const void*, entry_t> mObjects;
    };

    class PrivateAccessor {
    private:
        friend class BpBinder;
        friend class ::android::Parcel;
        friend class ::android::ProcessState;
        friend class ::android::RpcSession;
        friend class ::android::RpcState;
        explicit PrivateAccessor(const BpBinder* binder) : mBinder(binder) {}

        static sp<BpBinder> create(int32_t handle) { return BpBinder::create(handle); }
        static sp<BpBinder> create(const sp<RpcSession>& session, uint64_t address) {
            return BpBinder::create(session, address);
        }

        // valid if !isRpcBinder
        int32_t binderHandle() const { return mBinder->binderHandle(); }

        // valid if isRpcBinder
        uint64_t rpcAddress() const { return mBinder->rpcAddress(); }
        const sp<RpcSession>& rpcSession() const { return mBinder->rpcSession(); }

        const BpBinder* mBinder;
    };
    const PrivateAccessor getPrivateAccessor() const { return PrivateAccessor(this); }

private:
    friend PrivateAccessor;
    friend class sp<BpBinder>;

    static sp<BpBinder> create(int32_t handle);
    static sp<BpBinder> create(const sp<RpcSession>& session, uint64_t address);

    struct BinderHandle {
        int32_t handle;
    };
    struct RpcHandle {
        sp<RpcSession> session;
        uint64_t address;
    };
    using Handle = std::variant<BinderHandle, RpcHandle>;

    int32_t binderHandle() const;
    uint64_t rpcAddress() const;
    const sp<RpcSession>& rpcSession() const;

    explicit BpBinder(Handle&& handle);
    BpBinder(BinderHandle&& handle, int32_t trackedUid);
    explicit BpBinder(RpcHandle&& handle);

    virtual             ~BpBinder();
    virtual void        onFirstRef();
    virtual void        onLastStrongRef(const void* id);
    virtual bool        onIncStrongAttempted(uint32_t flags, const void* id);

    friend ::android::internal::Stability;

    int32_t mStability;
    Handle mHandle;

    struct Obituary {
        wp<DeathRecipient> recipient;
        void* cookie;
        uint32_t flags;
    };

            void                reportOneDeath(const Obituary& obit);
            bool                isDescriptorCached() const;

    mutable RpcMutex            mLock;
            volatile int32_t    mAlive;
            volatile int32_t    mObitsSent;
            Vector<Obituary>*   mObituaries;
            ObjectManager       mObjects;
    mutable String16            mDescriptorCache;
            int32_t             mTrackedUid;

    static RpcMutex                             sTrackingLock;
    static std::unordered_map<int32_t,uint32_t> sTrackingMap;
    static int                                  sNumTrackedUids;
    static std::atomic_bool                     sCountByUidEnabled;
    static binder_proxy_limit_callback          sLimitCallback;
    static uint32_t                             sBinderProxyCountHighWatermark;
    static uint32_t                             sBinderProxyCountLowWatermark;
    static bool                                 sBinderProxyThrottleCreate;
    static std::unordered_map<int32_t,uint32_t> sLastLimitCallbackMap;
    static std::atomic<uint32_t>                sBinderProxyCount;
    static std::atomic<uint32_t>                sBinderProxyCountWarned;
};

} // namespace android

// ---------------------------------------------------------------------------