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
mojo / core / channel_binder.h [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_CORE_CHANNEL_BINDER_H_
#define MOJO_CORE_CHANNEL_BINDER_H_
#include <cstdint>
#include <vector>
#include "base/android/binder.h"
#include "base/containers/circular_deque.h"
#include "base/containers/span.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/thread_annotations.h"
#include "mojo/core/channel.h"
#include "mojo/core/connection_params.h"
#include "mojo/core/system_impl_export.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace mojo::core {
// A Binder-based Channel implementation.
class MOJO_SYSTEM_IMPL_EXPORT ChannelBinder : public Channel {
public:
ChannelBinder(Delegate* delegate,
ConnectionParams connection_params,
HandlePolicy handle_policy,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
private:
DEFINE_BINDER_CLASS(ReceiverInterface);
friend class Receiver;
class Receiver : public base::android::SupportsBinder<ReceiverInterface> {
public:
using Proxy = ReceiverInterface::BinderRef;
explicit Receiver(scoped_refptr<ChannelBinder> channel);
void ShutDown();
// base::android::SupportsBinder<ReceiverInterface>:
base::android::BinderStatusOr<void> OnBinderTransaction(
transaction_code_t code,
const base::android::ParcelReader& in,
const base::android::ParcelWriter& out) override;
void OnBinderDestroyed() override;
private:
~Receiver() override;
base::Lock lock_;
scoped_refptr<ChannelBinder> channel_ GUARDED_BY(lock_);
};
~ChannelBinder() override;
// Channel:
void Start() override;
void ShutDownImpl() override;
void Write(MessagePtr message) override;
void LeakHandle() override;
bool GetReadPlatformHandles(const void* payload,
size_t payload_size,
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
std::vector<PlatformHandle>* handles,
bool* deferred) override;
bool GetReadPlatformHandlesForIpcz(
size_t num_handles,
std::vector<PlatformHandle>& handles) override;
base::android::BinderStatusOr<void> WriteOrEnqueue(MessagePtr message);
base::android::BinderStatusOr<void> FlushOutgoingMessages()
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void SetPeerReceiver(base::android::BinderRef receiver);
void Receive(base::span<const uint8_t> bytes,
std::vector<PlatformHandle> handles);
void OnDisconnect();
static base::android::BinderStatusOr<void> SendMessageToReceiver(
Receiver::Proxy& receiver,
MessagePtr message);
// Peer state begins as PendingExchange at ChannelBinder construction time.
//
// When Start() is called, a binder exchange is initiated and we enter the
// PendingConnection state while awaiting a SetPeerReceiver() callback from
// the exchange.
//
// Once we have the peer binder we adopt it as a Receiver::Proxy, and this
// is retained by `peer_` indefinitely or until disconnection.
//
// At any point after Start(), if our own Receiver becomes disconnected (i.e.
// its binder ref count drops to zero), `peer_` enters a permanent
// Disconnected state.
struct PendingExchange {
base::android::BinderRef binder;
};
struct PendingConnection {};
enum class Disconnected {};
using Peer = absl::variant<PendingExchange,
PendingConnection,
Receiver::Proxy,
Disconnected>;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
base::Lock lock_;
// Indicates whether LeakHandle() was called by the Channel owner, requiring
// us to avoid clean destruction of our peer binder once connected.
bool leak_peer_ GUARDED_BY(lock_) = false;
// Indicates that writes are no longer accepted on the Channel and that all
// subsequent outgoing messages will be dropped. This is set permanently once
// any write fails.
bool reject_writes_ GUARDED_BY(lock_) = false;
// The object receiving incoming parcels from our remote peer. Ownership of
// this object is shared by this ChannelBinder and the peer ChannelBinder (via
// a binder ref.)
scoped_refptr<Receiver> receiver_ GUARDED_BY(lock_);
// The state of our connection to the peer ChannelBinder. In a steady
// connected state this is the Receiver::Proxy we use to transmit messages to
// the peer.
Peer peer_ GUARDED_BY(lock_);
// A queue of outgoing messages which can accumulate either before connection
// or while another thread is already actively writing or flushing messages
// across the channel.
base::circular_deque<MessagePtr> outgoing_messages_ GUARDED_BY(lock_);
// Indicates whether a thread is currently writing or flushing messages across
// the channel. Only one thread may do this at a time.
bool is_writing_ GUARDED_BY(lock_) = false;
};
} // namespace mojo::core
#endif // MOJO_CORE_CHANNEL_BINDER_H_