| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef CHRE_HOST_SOCKET_CLIENT_H_ |
| #define CHRE_HOST_SOCKET_CLIENT_H_ |
| |
| #include <atomic> |
| #include <condition_variable> |
| #include <mutex> |
| #include <thread> |
| |
| #include <cutils/sockets.h> |
| #include <utils/RefBase.h> |
| #include <utils/StrongPointer.h> |
| |
| namespace android { |
| namespace chre { |
| |
| class SocketClient { |
| public: |
| SocketClient(); |
| ~SocketClient(); |
| |
| /** |
| * Represents the callback interface used for handling events that occur on |
| * the receive thread. Note that it is *not* safe to call connect(), |
| * connectInBackground(), or disconnect() from the context of these callbacks. |
| */ |
| class ICallbacks : public VirtualLightRefBase { |
| public: |
| /** |
| * Invoked from within the context of the read thread when a message is |
| * received on the socket. |
| * |
| * @param data Buffer containing received message data |
| * @param length Size of the message in bytes |
| */ |
| virtual void onMessageReceived(const void *data, size_t length) = 0; |
| |
| /** |
| * Called when the socket is successfully (re-)connected. |
| */ |
| virtual void onConnected() {}; |
| |
| /** |
| * Called when we have failed to (re-)connect the socket after many attempts |
| * and are giving up. |
| */ |
| virtual void onConnectionAborted() {}; |
| |
| /** |
| * Invoked when the socket is disconnected, and this connection loss was not |
| * the result of an explicit call to disconnect(), i.e. the connection was |
| * terminated on the remote end. |
| */ |
| virtual void onDisconnected() {}; |
| }; |
| |
| /** |
| * Synchronously attempts to connect to the Android reserved namespace socket |
| * with the given name. If this connection attempt is successful, starts a |
| * receive thread to handle messages received on the socket, and uses this |
| * thread to automatically reconnect if disconnected by the remote end. |
| * |
| * @param socketName Name of the Android domain socket to connect to |
| * @param callbacks |
| * |
| * @return true if the connection was successful |
| */ |
| bool connect(const char *socketName, |
| const ::android::sp<ICallbacks>& callbacks); |
| |
| /** |
| * Starts up the receive thread and attempts to connect to the socket in the |
| * background. The onConnected() callback will be invoked when the socket is |
| * connected successfully, or onConnectionAborted() will be invoked if the |
| * connection could not be made after many retries and the client is giving |
| * up. |
| * |
| * @param socketName Name of the Android domain socket to connect to |
| * @param callbacks |
| * |
| * @return true if the receive thread was started and will attempt to connect |
| * the socket asynchronously |
| */ |
| bool connectInBackground(const char *socketName, |
| const ::android::sp<ICallbacks>& callbacks); |
| |
| /** |
| * Performs graceful teardown of the socket. After this function returns, this |
| * object will no longer invoke any callbacks or hold a reference to the |
| * callbacks object provided to connect(). |
| */ |
| void disconnect(); |
| |
| /** |
| * @return true if the socket is currently connected |
| */ |
| bool isConnected() const; |
| |
| /** |
| * Send a message on the connected socket. Safe to call from any thread. |
| * |
| * @param data Buffer containing message data |
| * @param length Size of the message to send in bytes |
| * |
| * @return true if the message was successfully sent |
| */ |
| bool sendMessage(const void *data, size_t length); |
| |
| private: |
| static constexpr size_t kMaxSocketNameLen = 64; |
| char mSocketName[kMaxSocketNameLen]; |
| sp<ICallbacks> mCallbacks; |
| |
| std::atomic<int> mSockFd; |
| std::thread mRxThread; |
| |
| //! Set to true when we initiate the graceful socket shutdown procedure, so we |
| //! know not to invoke onSocketDisconnectedByRemote() |
| std::atomic<bool> mGracefulShutdown; |
| |
| //! Condition variable used as the method to wake the RX thread when we want |
| //! to disconnect, but it's trying to reconnect automatically |
| std::condition_variable mShutdownCond; |
| std::mutex mShutdownMutex; |
| |
| bool doConnect(const char *socketName, |
| const ::android::sp<ICallbacks>& callbacks, |
| bool connectInBackground); |
| bool inReceiveThread() const; |
| void receiveThread(); |
| bool receiveThreadRunning() const; |
| bool reconnect(); |
| void startReceiveThread(); |
| bool tryConnect(bool suppressErrorLogs = false); |
| }; |
| |
| } // namespace chre |
| } // namespace android |
| |
| #endif // CHRE_HOST_SOCKET_CLIENT_H_ |