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
|
// 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 <variant>
#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"
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 = std::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_
|