Home | History | Annotate | Download | only in chre_host
      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      */
     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      */
     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      */
     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