1 /* 2 * Copyright (C) 2020 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 #pragma once 17 18 #include <android-base/unique_fd.h> 19 #include <binder/IBinder.h> 20 #include <binder/RpcAddress.h> 21 #include <utils/Errors.h> 22 #include <utils/RefBase.h> 23 24 #include <map> 25 #include <optional> 26 #include <thread> 27 #include <vector> 28 29 // WARNING: This is a feature which is still in development, and it is subject 30 // to radical change. Any production use of this may subject your code to any 31 // number of problems. 32 33 namespace android { 34 35 class Parcel; 36 class RpcServer; 37 class RpcSocketAddress; 38 class RpcState; 39 40 /** 41 * This represents a session (group of connections) between a client 42 * and a server. Multiple connections are needed for multiple parallel "binder" 43 * calls which may also have nested calls. 44 */ 45 class RpcSession final : public virtual RefBase { 46 public: 47 static sp<RpcSession> make(); 48 49 /** 50 * This should be called once per thread, matching 'join' in the remote 51 * process. 52 */ 53 [[nodiscard]] bool setupUnixDomainClient(const char* path); 54 55 /** 56 * Connects to an RPC server at the CVD & port. 57 */ 58 [[nodiscard]] bool setupVsockClient(unsigned int cvd, unsigned int port); 59 60 /** 61 * Connects to an RPC server at the given address and port. 62 */ 63 [[nodiscard]] bool setupInetClient(const char* addr, unsigned int port); 64 65 /** 66 * For debugging! 67 * 68 * Sets up an empty connection. All queries to this connection which require a 69 * response will never be satisfied. All data sent here will be 70 * unceremoniously cast down the bottomless pit, /dev/null. 71 */ 72 [[nodiscard]] bool addNullDebuggingClient(); 73 74 /** 75 * Query the other side of the session for the root object hosted by that 76 * process's RpcServer (if one exists) 77 */ 78 sp<IBinder> getRootObject(); 79 80 /** 81 * Query the other side of the session for the maximum number of threads 82 * it supports (maximum number of concurrent non-nested synchronous transactions) 83 */ 84 status_t getRemoteMaxThreads(size_t* maxThreads); 85 86 [[nodiscard]] status_t transact(const RpcAddress& address, uint32_t code, const Parcel& data, 87 Parcel* reply, uint32_t flags); 88 [[nodiscard]] status_t sendDecStrong(const RpcAddress& address); 89 90 ~RpcSession(); 91 92 wp<RpcServer> server(); 93 94 // internal only state()95 const std::unique_ptr<RpcState>& state() { return mState; } 96 97 class PrivateAccessorForId { 98 private: 99 friend class RpcSession; 100 friend class RpcState; PrivateAccessorForId(const RpcSession * session)101 explicit PrivateAccessorForId(const RpcSession* session) : mSession(session) {} 102 get()103 const std::optional<int32_t> get() { return mSession->mId; } 104 105 const RpcSession* mSession; 106 }; getPrivateAccessorForId()107 PrivateAccessorForId getPrivateAccessorForId() const { return PrivateAccessorForId(this); } 108 109 private: 110 friend PrivateAccessorForId; 111 friend sp<RpcSession>; 112 friend RpcServer; 113 RpcSession(); 114 115 status_t readId(); 116 117 // transfer ownership of thread 118 void preJoin(std::thread thread); 119 // join on thread passed to preJoin 120 void join(base::unique_fd client); 121 void terminateLocked(); 122 123 struct RpcConnection : public RefBase { 124 base::unique_fd fd; 125 126 // whether this or another thread is currently using this fd to make 127 // or receive transactions. 128 std::optional<pid_t> exclusiveTid; 129 }; 130 131 bool setupSocketClient(const RpcSocketAddress& address); 132 bool setupOneSocketClient(const RpcSocketAddress& address, int32_t sessionId); 133 void addClientConnection(base::unique_fd fd); 134 void setForServer(const wp<RpcServer>& server, int32_t sessionId); 135 sp<RpcConnection> assignServerToThisThread(base::unique_fd fd); 136 bool removeServerConnection(const sp<RpcConnection>& connection); 137 138 enum class ConnectionUse { 139 CLIENT, 140 CLIENT_ASYNC, 141 CLIENT_REFCOUNT, 142 }; 143 144 // RAII object for session connection 145 class ExclusiveConnection { 146 public: 147 explicit ExclusiveConnection(const sp<RpcSession>& session, ConnectionUse use); 148 ~ExclusiveConnection(); fd()149 const base::unique_fd& fd() { return mConnection->fd; } 150 151 private: 152 static void findConnection(pid_t tid, sp<RpcConnection>* exclusive, 153 sp<RpcConnection>* available, 154 std::vector<sp<RpcConnection>>& sockets, 155 size_t socketsIndexHint); 156 157 sp<RpcSession> mSession; // avoid deallocation 158 sp<RpcConnection> mConnection; 159 160 // whether this is being used for a nested transaction (being on the same 161 // thread guarantees we won't write in the middle of a message, the way 162 // the wire protocol is constructed guarantees this is safe). 163 bool mReentrant = false; 164 }; 165 166 // On the other side of a session, for each of mClientConnections here, there should 167 // be one of mServerConnections on the other side (and vice versa). 168 // 169 // For the simplest session, a single server with one client, you would 170 // have: 171 // - the server has a single 'mServerConnections' and a thread listening on this 172 // - the client has a single 'mClientConnections' and makes calls to this 173 // - here, when the client makes a call, the server can call back into it 174 // (nested calls), but outside of this, the client will only ever read 175 // calls from the server when it makes a call itself. 176 // 177 // For a more complicated case, the client might itself open up a thread to 178 // serve calls to the server at all times (e.g. if it hosts a callback) 179 180 wp<RpcServer> mForServer; // maybe null, for client sessions 181 182 // TODO(b/183988761): this shouldn't be guessable 183 std::optional<int32_t> mId; 184 185 std::unique_ptr<RpcState> mState; 186 187 std::mutex mMutex; // for all below 188 189 std::condition_variable mAvailableConnectionCv; // for mWaitingThreads 190 size_t mWaitingThreads = 0; 191 // hint index into clients, ++ when sending an async transaction 192 size_t mClientConnectionsOffset = 0; 193 std::vector<sp<RpcConnection>> mClientConnections; 194 std::vector<sp<RpcConnection>> mServerConnections; 195 196 // TODO(b/185167543): use for reverse sessions (allow client to also 197 // serve calls on a session). 198 // TODO(b/185167543): allow sharing between different sessions in a 199 // process? (or combine with mServerConnections) 200 std::map<std::thread::id, std::thread> mThreads; 201 bool mTerminated = false; 202 }; 203 204 } // namespace android 205