1 #include "pdx/client.h" 2 3 #define LOG_TAG "ServiceFramework" 4 #include <log/log.h> 5 6 #include <pdx/trace.h> 7 8 namespace android { 9 namespace pdx { 10 11 void Client::EnableAutoReconnect(int64_t reconnect_timeout_ms) { 12 if (channel_factory_) { 13 reconnect_timeout_ms_ = reconnect_timeout_ms; 14 auto_reconnect_enabled_ = true; 15 } 16 } 17 18 void Client::DisableAutoReconnect() { auto_reconnect_enabled_ = false; } 19 20 bool Client::IsConnected() const { return channel_.get() != nullptr; } 21 22 Status<void> Client::CheckReconnect() { 23 Status<void> ret; 24 bool was_disconnected = !IsConnected(); 25 if (auto_reconnect_enabled_ && was_disconnected && channel_factory_) { 26 auto status = channel_factory_->Connect(reconnect_timeout_ms_); 27 if (!status) { 28 error_ = -status.error(); 29 ret.SetError(status.error()); 30 return ret; 31 } 32 channel_ = status.take(); 33 } 34 35 if (!IsConnected()) { 36 ret.SetError(ESHUTDOWN); 37 } else { 38 // Call the subclass OnConnect handler. The subclass may choose to close the 39 // connection in the handler, in which case error_ will be non-zero. 40 if (was_disconnected) 41 OnConnect(); 42 if (!IsConnected()) 43 ret.SetError(-error_); 44 else 45 ret.SetValue(); 46 } 47 48 return ret; 49 } 50 51 bool Client::NeedToDisconnectChannel(int error) const { 52 return error == ESHUTDOWN && auto_reconnect_enabled_; 53 } 54 55 void Client::CheckDisconnect(int error) { 56 if (NeedToDisconnectChannel(error)) 57 Close(error); 58 } 59 60 Client::Client(std::unique_ptr<ClientChannel> channel) 61 : channel_{std::move(channel)} {} 62 63 Client::Client(std::unique_ptr<ClientChannelFactory> channel_factory, 64 int64_t timeout_ms) 65 : channel_factory_{std::move(channel_factory)} { 66 auto status = channel_factory_->Connect(timeout_ms); 67 if (!status) { 68 ALOGE("Client::Client: Failed to connect to service because: %s", 69 status.GetErrorMessage().c_str()); 70 error_ = -status.error(); 71 } else { 72 channel_ = status.take(); 73 } 74 } 75 76 bool Client::IsInitialized() const { 77 return IsConnected() || (channel_factory_ && auto_reconnect_enabled_); 78 } 79 80 void Client::OnConnect() {} 81 82 int Client::error() const { return error_; } 83 84 Status<void> Client::SendImpulse(int opcode) { 85 PDX_TRACE_NAME("Client::SendImpulse"); 86 87 auto status = CheckReconnect(); 88 if (!status) 89 return status; 90 91 status = channel_->SendImpulse(opcode, nullptr, 0); 92 CheckDisconnect(status); 93 return status; 94 } 95 96 Status<void> Client::SendImpulse(int opcode, const void* buffer, 97 size_t length) { 98 PDX_TRACE_NAME("Client::SendImpulse"); 99 100 auto status = CheckReconnect(); 101 if (!status) 102 return status; 103 104 status = channel_->SendImpulse(opcode, buffer, length); 105 CheckDisconnect(status); 106 return status; 107 } 108 109 void Client::Close(int error) { 110 channel_.reset(); 111 // Normalize error codes to negative integer space. 112 error_ = error <= 0 ? error : -error; 113 } 114 115 int Client::event_fd() const { 116 return IsConnected() ? channel_->event_fd() : -1; 117 } 118 119 LocalChannelHandle& Client::GetChannelHandle() { 120 return channel_->GetChannelHandle(); 121 } 122 123 ///////////////////////////// Transaction implementation ////////////////////// 124 125 Transaction::Transaction(Client& client) : client_{client} {} 126 127 Transaction::~Transaction() { 128 if (state_allocated_ && client_.GetChannel()) 129 client_.GetChannel()->FreeTransactionState(state_); 130 } 131 132 bool Transaction::EnsureStateAllocated() { 133 if (!state_allocated_ && client_.GetChannel()) { 134 state_ = client_.GetChannel()->AllocateTransactionState(); 135 state_allocated_ = true; 136 } 137 return state_allocated_; 138 } 139 140 void Transaction::SendTransaction(int opcode, Status<void>* ret, 141 const iovec* send_vector, size_t send_count, 142 const iovec* receive_vector, 143 size_t receive_count) { 144 *ret = client_.CheckReconnect(); 145 if (!*ret) 146 return; 147 148 if (!EnsureStateAllocated()) { 149 ret->SetError(ESHUTDOWN); 150 return; 151 } 152 153 auto status = client_.GetChannel()->SendWithInt( 154 state_, opcode, send_vector, send_count, receive_vector, receive_count); 155 156 if (status) { 157 ret->SetValue(); 158 } else { 159 ret->SetError(status.error()); 160 } 161 CheckDisconnect(status); 162 } 163 164 void Transaction::SendTransaction(int opcode, Status<int>* ret, 165 const iovec* send_vector, size_t send_count, 166 const iovec* receive_vector, 167 size_t receive_count) { 168 auto status = client_.CheckReconnect(); 169 if (!status) { 170 ret->SetError(status.error()); 171 return; 172 } 173 174 if (!EnsureStateAllocated()) { 175 ret->SetError(ESHUTDOWN); 176 return; 177 } 178 179 *ret = client_.GetChannel()->SendWithInt( 180 state_, opcode, send_vector, send_count, receive_vector, receive_count); 181 182 CheckDisconnect(*ret); 183 } 184 185 void Transaction::SendTransaction(int opcode, Status<LocalHandle>* ret, 186 const iovec* send_vector, size_t send_count, 187 const iovec* receive_vector, 188 size_t receive_count) { 189 auto status = client_.CheckReconnect(); 190 if (!status) { 191 ret->SetError(status.error()); 192 return; 193 } 194 195 if (!EnsureStateAllocated()) { 196 ret->SetError(ESHUTDOWN); 197 return; 198 } 199 200 *ret = client_.GetChannel()->SendWithFileHandle( 201 state_, opcode, send_vector, send_count, receive_vector, receive_count); 202 203 CheckDisconnect(*ret); 204 } 205 206 void Transaction::SendTransaction(int opcode, Status<LocalChannelHandle>* ret, 207 const iovec* send_vector, size_t send_count, 208 const iovec* receive_vector, 209 size_t receive_count) { 210 auto status = client_.CheckReconnect(); 211 if (!status) { 212 ret->SetError(status.error()); 213 return; 214 } 215 216 if (!EnsureStateAllocated()) { 217 ret->SetError(ESHUTDOWN); 218 return; 219 } 220 221 *ret = client_.GetChannel()->SendWithChannelHandle( 222 state_, opcode, send_vector, send_count, receive_vector, receive_count); 223 224 CheckDisconnect(*ret); 225 } 226 227 Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) { 228 if (client_.CheckReconnect() && EnsureStateAllocated()) 229 return client_.GetChannel()->PushFileHandle(state_, handle); 230 return ErrorStatus{ESHUTDOWN}; 231 } 232 233 Status<FileReference> Transaction::PushFileHandle( 234 const BorrowedHandle& handle) { 235 if (client_.CheckReconnect() && EnsureStateAllocated()) 236 return client_.GetChannel()->PushFileHandle(state_, handle); 237 return ErrorStatus{ESHUTDOWN}; 238 } 239 240 Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) { 241 return handle.Get(); 242 } 243 244 Status<ChannelReference> Transaction::PushChannelHandle( 245 const LocalChannelHandle& handle) { 246 if (client_.CheckReconnect() && EnsureStateAllocated()) 247 return client_.GetChannel()->PushChannelHandle(state_, handle); 248 return ErrorStatus{ESHUTDOWN}; 249 } 250 251 Status<ChannelReference> Transaction::PushChannelHandle( 252 const BorrowedChannelHandle& handle) { 253 if (client_.CheckReconnect() && EnsureStateAllocated()) 254 return client_.GetChannel()->PushChannelHandle(state_, handle); 255 return ErrorStatus{ESHUTDOWN}; 256 } 257 258 Status<ChannelReference> Transaction::PushChannelHandle( 259 const RemoteChannelHandle& handle) { 260 return handle.value(); 261 } 262 263 bool Transaction::GetFileHandle(FileReference ref, LocalHandle* handle) { 264 return client_.CheckReconnect() && EnsureStateAllocated() && 265 client_.GetChannel()->GetFileHandle(state_, ref, handle); 266 } 267 268 bool Transaction::GetChannelHandle(ChannelReference ref, 269 LocalChannelHandle* handle) { 270 return client_.CheckReconnect() && EnsureStateAllocated() && 271 client_.GetChannel()->GetChannelHandle(state_, ref, handle); 272 } 273 274 void Transaction::CheckDisconnect(int error) { 275 if (client_.NeedToDisconnectChannel(error)) { 276 if (state_allocated_) { 277 if (client_.GetChannel()) 278 client_.GetChannel()->FreeTransactionState(state_); 279 state_ = nullptr; 280 state_allocated_ = false; 281 } 282 client_.Close(error); 283 } 284 } 285 286 } // namespace pdx 287 } // namespace android 288