Xtra client interfacing with LocNetIface in LE

Interfacing LocnetIface with Xtra client for wwan/supl call
setup and teardown.
- XtraSystemStatusObserver must listen to connect/teardown wwan
call requests from xtra-daemon on the HAL side socket. This
request is then processed by libloc_net_iface module on LE.
- Caching the connect and disconnect backhaul requests received
before framework action request object is obtained.

Change-Id: I7cb6751efc64b27726b5d28be9a3df7b1bfb3d76
CRs-Fixed: 2092215
diff --git a/core/Makefile.am b/core/Makefile.am
index 4258668..92aaded 100644
--- a/core/Makefile.am
+++ b/core/Makefile.am
@@ -1,5 +1,6 @@
 AM_CFLAGS = -I./ \
             -I../utils \
+            -I../gnss \
             -I../location \
             -I./data-items \
             -I./data-items/common \
diff --git a/core/SystemStatusOsObserver.cpp b/core/SystemStatusOsObserver.cpp
index 319f1d7..dc08a76 100644
--- a/core/SystemStatusOsObserver.cpp
+++ b/core/SystemStatusOsObserver.cpp
@@ -41,6 +41,9 @@
 {
 SystemStatusOsObserver::SystemStatusOsObserver(const MsgTask* msgTask) :
     mAddress("SystemStatusOsObserver"),
+#ifdef USE_GLIB
+    mBackHaulConnectReqCount(0),
+#endif
     mClientIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createClientIndex()),
     mDataItemIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createDataItemIndex())
 {
@@ -506,6 +509,65 @@
     }
 }
 
+#ifdef USE_GLIB
+bool SystemStatusOsObserver::connectBackhaul()
+{
+    bool result = false;
+
+    if (mContext.mFrameworkActionReqObj != NULL) {
+        struct HandleConnectBackhaul : public LocMsg {
+            HandleConnectBackhaul(IFrameworkActionReq* fwkActReq) :
+                    mFwkActionReqObj(fwkActReq) {}
+            virtual ~HandleConnectBackhaul() {}
+            void proc() const {
+                LOC_LOGD("HandleConnectBackhaul");
+                mFwkActionReqObj->connectBackhaul();
+            }
+            IFrameworkActionReq* mFwkActionReqObj;
+        };
+        mContext.mMsgTask->sendMsg(
+                new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj));
+        result = true;
+    }
+    else {
+        ++mBackHaulConnectReqCount;
+        LOC_LOGE("Framework action request object is NULL.Caching connect request: %d",
+                        mBackHaulConnectReqCount);
+        result = false;
+    }
+    return result;
+
+}
+
+bool SystemStatusOsObserver::disconnectBackhaul()
+{
+    bool result = false;
+
+    if (mContext.mFrameworkActionReqObj != NULL) {
+        struct HandleDisconnectBackhaul : public LocMsg {
+            HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq) :
+                    mFwkActionReqObj(fwkActReq) {}
+            virtual ~HandleDisconnectBackhaul() {}
+            void proc() const {
+                LOC_LOGD("HandleDisconnectBackhaul");
+                mFwkActionReqObj->disconnectBackhaul();
+            }
+            IFrameworkActionReq* mFwkActionReqObj;
+        };
+        mContext.mMsgTask->sendMsg(
+                new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj));
+    }
+    else {
+        if (mBackHaulConnectReqCount > 0) {
+            --mBackHaulConnectReqCount;
+        }
+        LOC_LOGE("Framework action request object is NULL.Caching disconnect request: %d",
+                        mBackHaulConnectReqCount);
+        result = false;
+    }
+    return result;
+}
+#endif
 /******************************************************************************
  Helpers
 ******************************************************************************/
diff --git a/core/SystemStatusOsObserver.h b/core/SystemStatusOsObserver.h
index 985e5c9..6892f22 100644
--- a/core/SystemStatusOsObserver.h
+++ b/core/SystemStatusOsObserver.h
@@ -85,6 +85,12 @@
     // To set the framework action request object
     inline void setFrameworkActionReqObj(IFrameworkActionReq* frameworkActionReqObj) {
         mContext.mFrameworkActionReqObj = frameworkActionReqObj;
+#ifdef USE_GLIB
+        if (mBackHaulConnectReqCount > 0) {
+            connectBackhaul();
+            mBackHaulConnectReqCount = 0;
+        }
+#endif
     }
 
     // IDataItemSubscription Overrides
@@ -103,6 +109,10 @@
     // IFrameworkActionReq Overrides
     virtual void turnOn(DataItemId dit, int timeOut = 0);
     virtual void turnOff(DataItemId dit);
+#ifdef USE_GLIB
+    virtual bool connectBackhaul();
+    virtual bool disconnectBackhaul();
+#endif
 
 private:
     SystemContext                                    mContext;
@@ -117,6 +127,10 @@
     ObserverReqCache mReqDataCache;
     void cacheObserverRequest(ObserverReqCache& reqCache,
             const list<DataItemId>& l, IDataItemObserver* client);
+#ifdef USE_GLIB
+    // Cache the framework action request for connect/disconnect
+    int         mBackHaulConnectReqCount;
+#endif
 
     // Helpers
     void sendFirstResponse(const list<DataItemId>& l, IDataItemObserver* to);
diff --git a/core/observer/IFrameworkActionReq.h b/core/observer/IFrameworkActionReq.h
index c7b3ebd..4be947f 100644
--- a/core/observer/IFrameworkActionReq.h
+++ b/core/observer/IFrameworkActionReq.h
@@ -70,6 +70,24 @@
      */
     virtual void turnOff (DataItemId dit) = 0;
 
+#ifdef USE_GLIB
+    /**
+     * @brief Setup WWAN backhaul
+     * @details  Setup WWAN backhaul
+     *
+     * @param None
+     */
+    virtual bool connectBackhaul() = 0;
+
+    /**
+     * @brief Disconnects the WWANbackhaul
+     * @details Disconnects the WWANbackhaul, only if it was setup by us
+     *
+     * @param None
+     */
+    virtual bool disconnectBackhaul() = 0;
+#endif
+
     /**
      * @brief Destructor
      * @details Destructor
diff --git a/core/observer/IOsObserver.h b/core/observer/IOsObserver.h
index 3db8a85..40d7671 100644
--- a/core/observer/IOsObserver.h
+++ b/core/observer/IOsObserver.h
@@ -90,6 +90,10 @@
     // IFrameworkActionReq Overrides
     inline virtual void turnOn (DataItemId /*dit*/, int /*timeOut*/){}
     inline virtual void turnOff (DataItemId /*dit*/) {}
+#ifdef USE_GLIB
+    inline virtual bool connectBackhaul() {}
+    inline virtual bool disconnectBackhaul() {}
+#endif
 
     /**
      * @brief Destructor
diff --git a/gnss/XtraSystemStatusObserver.cpp b/gnss/XtraSystemStatusObserver.cpp
index ce08f64..ac40220 100644
--- a/gnss/XtraSystemStatusObserver.cpp
+++ b/gnss/XtraSystemStatusObserver.cpp
@@ -231,4 +231,128 @@
     mMsgTask->sendMsg(new (nothrow) handleOsObserverUpdateMsg(this, dlist));
 }
 
+#ifdef USE_GLIB
+bool XtraSystemStatusObserver::connectBackhaul()
+{
+    return mSystemStatusObsrvr->connectBackhaul();
+}
 
+bool XtraSystemStatusObserver::disconnectBackhaul()
+{
+    return mSystemStatusObsrvr->disconnectBackhaul();
+}
+
+// XtraHalListenerSocket class
+// TBD - this will be removed once bidirectional socket changes in
+// xtra-daemon will be implemented
+void XtraHalListenerSocket::receiveData(const int socketFd) {
+    string data;
+    array<char, 128> buf;
+    const char* bin_msg_conn_backhaul = "connectBackhaul";
+    const char* bin_msg_disconn_backhaul = "disconnectBackhaul";
+
+    while (true) {
+        ssize_t len = recv(socketFd, buf.data(), buf.size(), 0);
+        if (len > 0) {
+            LOC_LOGd("received %lu bytes", len);
+            data.append(buf.data(), len);
+
+            size_t pos = data.find("\n");
+            if (pos == string::npos) {
+                continue;
+            }
+
+            if (!strncmp(data.c_str(), bin_msg_conn_backhaul,
+                                       sizeof(bin_msg_conn_backhaul) - 1)) {
+                mSystemStatusObsrvr->connectBackhaul();
+            } else if (!strncmp(data.c_str(), bin_msg_disconn_backhaul,
+                                            sizeof(bin_msg_disconn_backhaul) - 1)) {
+                mSystemStatusObsrvr->disconnectBackhaul();
+            }
+            else {
+                LOC_LOGw("unknown event: %s", data.c_str());
+            }
+            break;
+
+        } else {
+            LOC_LOGd("XtraHalListenerSocket connection broken.");
+            break;
+        }
+    }
+}
+
+void XtraHalListenerSocket::startListenerThread() {
+    mThread = new (std::nothrow) LocThread();
+    if (!mThread) {
+        LOC_LOGe("create thread failed");
+    }
+    mRunning = true;
+    if (!mThread->start("XtraHalListenerSocketThread", this, true)) {
+        delete mThread;
+        mThread = NULL;
+    }
+
+    LOC_LOGd("Create listener socket in XtraHalListenerSocket");
+    // create socket
+    int socketFd;
+    if ((socketFd = ::socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+        LOC_LOGe("create socket error. reason:%s", strerror(errno));
+        return;
+    }
+
+    const char* socketPath = "/data/vendor/location/xtra/socket_xtra_locnetiface";
+    unlink(socketPath);
+
+    struct sockaddr_un addr = { .sun_family = AF_UNIX };
+    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketPath);
+
+    umask(0157);
+
+    if (::bind(socketFd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+        LOC_LOGe("bind socket error. reason:%s", strerror(errno));
+        return;
+    }
+
+    // set up connection
+    if (::listen(socketFd, 5/*backlog*/) < 0) {
+        LOC_LOGe("cannot bind socket. reason:%s", strerror(errno));
+        return;
+    }
+    mSocketFd = socketFd;
+
+}
+
+bool XtraHalListenerSocket::run() {
+    // infinite while loop till mRunning is false when stopListenXtraDaemon
+    // is called
+    while (mRunning) {
+        int clientFd = -1;
+        LOC_LOGd("XtraHalListenerSocket - waiting for msg...");
+        if ( (clientFd = ::accept(mSocketFd, NULL, NULL)) < 0) {
+            LOC_LOGe("connection error. reason:%s", strerror(errno));
+        } else {
+            LOC_LOGd("XtraHalListenerSocket - receiving data ...");
+            receiveData(clientFd);
+            if (::close(clientFd)) {
+                LOC_LOGe("close connection fail.");
+            }
+            clientFd = -1;
+        }
+    }
+
+    // return false once we reach there
+    return false;
+}
+
+void XtraHalListenerSocket::stopListenXtraDaemon() {
+    if (mSocketFd >= 0) {
+        if (::close(mSocketFd)) {
+            LOC_LOGe("close hal connection fail.");
+        }
+        mSocketFd = -1;
+    }
+    mRunning = false;
+    mThread->stop();
+}
+
+#endif
diff --git a/gnss/XtraSystemStatusObserver.h b/gnss/XtraSystemStatusObserver.h
index 42f49b5..6a001d9 100644
--- a/gnss/XtraSystemStatusObserver.h
+++ b/gnss/XtraSystemStatusObserver.h
@@ -31,17 +31,72 @@
 
 #include <cinttypes>
 #include <MsgTask.h>
+#ifdef USE_GLIB
+#include <LocThread.h>
+#endif
 
 using namespace std;
 using loc_core::IOsObserver;
 using loc_core::IDataItemObserver;
 using loc_core::IDataItemCore;
 
+#ifdef USE_GLIB
+// XtraHalListenerSocket class
+// listener socket for getting msgs from xtra-daemon in LE for invoking
+// LocNetIface functions
+// TBD - this will be removed once bidirectional socket changes in
+// xtra-daemon will be implemented
+class XtraHalListenerSocket: public LocRunnable {
+public :
+    // constructor & destructor
+    XtraHalListenerSocket(IOsObserver* sysStatObs) :
+            mThread(NULL),
+            mRunning(false) {
+        mSystemStatusObsrvr = sysStatObs;
+        mRunning = true;
+        // create listener socket in a thread
+        startListenerThread();
+    }
+    XtraHalListenerSocket() {}
+    inline virtual ~XtraHalListenerSocket() {
+        if (mThread) {
+            stopListenXtraDaemon();
+            delete mThread;
+            mThread = NULL;
+        }
+    }
+
+    // Overrides of LocRunnable methods
+    // This method will be repeated called until it returns false; or
+    // until thread is stopped.
+    virtual bool run();
+
+    // The method to be run before thread loop (conditionally repeatedly)
+    // calls run()
+    inline virtual void prerun() {}
+
+    // The method to be run after thread loop (conditionally repeatedly)
+    // calls run()
+    inline virtual void postrun() {}
+
+private:
+    IOsObserver*    mSystemStatusObsrvr;
+    int mSocketFd;
+    LocThread* mThread;
+    bool mRunning;
+    void startListenerThread();
+    void stopListenXtraDaemon();
+    void receiveData(const int socketFd);
+};
+#endif
 
 class XtraSystemStatusObserver : public IDataItemObserver {
 public :
     // constructor & destructor
     inline XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask):
+#ifdef USE_GLIB
+            mHalListenerSocket(sysStatObs),
+#endif
             mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask) {
         subscribe(true);
     }
@@ -52,6 +107,12 @@
     inline virtual void getName(string& name);
     virtual void notify(const list<IDataItemCore*>& dlist);
 
+#ifdef USE_GLIB
+    // IFrameworkActionReq functions reqd
+    virtual bool connectBackhaul();
+    virtual bool disconnectBackhaul();
+#endif
+
     bool updateLockStatus(uint32_t lock);
     bool updateConnectionStatus(bool connected, uint32_t type);
     bool updateTac(const string& tac);
@@ -65,6 +126,12 @@
     bool sendEvent(const stringstream& event);
     IOsObserver*    mSystemStatusObsrvr;
     const MsgTask* mMsgTask;
+#ifdef USE_GLIB
+    // XtraHalListenerSocket class
+    // TBD - this will be removed once bidirectional socket changes in
+    // xtra-daemon will be implemented
+    XtraHalListenerSocket mHalListenerSocket;
+#endif
 
 };