1 /* 2 * Copyright (C) 2017 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 17 #ifndef CHRE_HOST_SOCKET_CLIENT_H_ 18 #define CHRE_HOST_SOCKET_CLIENT_H_ 19 20 #include <atomic> 21 #include <condition_variable> 22 #include <mutex> 23 #include <thread> 24 25 #include <cutils/sockets.h> 26 #include <utils/RefBase.h> 27 #include <utils/StrongPointer.h> 28 29 namespace android { 30 namespace chre { 31 32 class SocketClient { 33 public: 34 SocketClient(); 35 ~SocketClient(); 36 37 /** 38 * Represents the callback interface used for handling events that occur on 39 * the receive thread. Note that it is *not* safe to call connect(), 40 * connectInBackground(), or disconnect() from the context of these callbacks. 41 */ 42 class ICallbacks : public VirtualLightRefBase { 43 public: 44 /** 45 * Invoked from within the context of the read thread when a message is 46 * received on the socket. 47 * 48 * @param data Buffer containing received message data 49 * @param length Size of the message in bytes 50 */ 51 virtual void onMessageReceived(const void *data, size_t length) = 0; 52 53 /** 54 * Called when the socket is successfully (re-)connected. 55 */ onConnected()56 virtual void onConnected() {}; 57 58 /** 59 * Called when we have failed to (re-)connect the socket after many attempts 60 * and are giving up. 61 */ onConnectionAborted()62 virtual void onConnectionAborted() {}; 63 64 /** 65 * Invoked when the socket is disconnected, and this connection loss was not 66 * the result of an explicit call to disconnect(), i.e. the connection was 67 * terminated on the remote end. 68 */ onDisconnected()69 virtual void onDisconnected() {}; 70 }; 71 72 /** 73 * Synchronously attempts to connect to the Android reserved namespace socket 74 * with the given name. If this connection attempt is successful, starts a 75 * receive thread to handle messages received on the socket, and uses this 76 * thread to automatically reconnect if disconnected by the remote end. 77 * 78 * @param socketName Name of the Android domain socket to connect to 79 * @param callbacks 80 * 81 * @return true if the connection was successful 82 */ 83 bool connect(const char *socketName, 84 const ::android::sp<ICallbacks>& callbacks); 85 86 /** 87 * Starts up the receive thread and attempts to connect to the socket in the 88 * background. The onConnected() callback will be invoked when the socket is 89 * connected successfully, or onConnectionAborted() will be invoked if the 90 * connection could not be made after many retries and the client is giving 91 * up. 92 * 93 * @param socketName Name of the Android domain socket to connect to 94 * @param callbacks 95 * 96 * @return true if the receive thread was started and will attempt to connect 97 * the socket asynchronously 98 */ 99 bool connectInBackground(const char *socketName, 100 const ::android::sp<ICallbacks>& callbacks); 101 102 /** 103 * Performs graceful teardown of the socket. After this function returns, this 104 * object will no longer invoke any callbacks or hold a reference to the 105 * callbacks object provided to connect(). 106 */ 107 void disconnect(); 108 109 /** 110 * @return true if the socket is currently connected 111 */ 112 bool isConnected() const; 113 114 /** 115 * Send a message on the connected socket. Safe to call from any thread. 116 * 117 * @param data Buffer containing message data 118 * @param length Size of the message to send in bytes 119 * 120 * @return true if the message was successfully sent 121 */ 122 bool sendMessage(const void *data, size_t length); 123 124 private: 125 static constexpr size_t kMaxSocketNameLen = 64; 126 char mSocketName[kMaxSocketNameLen]; 127 sp<ICallbacks> mCallbacks; 128 129 std::atomic<int> mSockFd; 130 std::thread mRxThread; 131 132 //! Set to true when we initiate the graceful socket shutdown procedure, so we 133 //! know not to invoke onSocketDisconnectedByRemote() 134 std::atomic<bool> mGracefulShutdown; 135 136 //! Condition variable used as the method to wake the RX thread when we want 137 //! to disconnect, but it's trying to reconnect automatically 138 std::condition_variable mShutdownCond; 139 std::mutex mShutdownMutex; 140 141 bool doConnect(const char *socketName, 142 const ::android::sp<ICallbacks>& callbacks, 143 bool connectInBackground); 144 bool inReceiveThread() const; 145 void receiveThread(); 146 bool receiveThreadRunning() const; 147 bool reconnect(); 148 void startReceiveThread(); 149 bool tryConnect(bool suppressErrorLogs = false); 150 }; 151 152 } // namespace chre 153 } // namespace android 154 155 #endif // CHRE_HOST_SOCKET_CLIENT_H_ 156