/* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation, nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define LOG_TAG "LocSvc_XtraSystemStatusObs" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace loc_util; using namespace loc_core; #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "LocSvc_XSSO" class XtraIpcListener : public ILocIpcListener { IOsObserver* mSystemStatusObsrvr; const MsgTask* mMsgTask; XtraSystemStatusObserver& mXSSO; public: inline XtraIpcListener(IOsObserver* observer, const MsgTask* msgTask, XtraSystemStatusObserver& xsso) : mSystemStatusObsrvr(observer), mMsgTask(msgTask), mXSSO(xsso) {} virtual void onReceive(const char* data, uint32_t length __unused, const LocIpcRecver* recver __unused) override { #define STRNCMP(str, constStr) strncmp(str, constStr, sizeof(constStr)-1) if (!STRNCMP(data, "ping")) { LOC_LOGd("ping received"); #ifdef USE_GLIB } else if ((!STRNCMP(data, "connectBackhaul")) || (!STRNCMP(data, "disconnectBackhaul"))) { char clientName[30] = {0}; uint16_t prefSub; char prefApnName[30] = {0}; uint16_t prefIpType; int ret = sscanf(data, "%*s %29s %u %29s %u", clientName, &prefSub, prefApnName, &prefIpType); BackhaulContext ctx = { clientName, prefSub, (0 == STRNCMP(prefApnName, "EMPTY")) ? "" : prefApnName, prefIpType }; if (!STRNCMP(data, "connectBackhaul")) { mSystemStatusObsrvr->connectBackhaul(ctx); } else { mSystemStatusObsrvr->disconnectBackhaul(ctx); } #endif } else if (!STRNCMP(data, "requestStatus")) { int32_t xtraStatusUpdated = 0; char socketName[40] = {0}; sscanf(data, "%*s %d %39s", &xtraStatusUpdated, socketName); struct HandleStatusRequestMsg : public LocMsg { XtraSystemStatusObserver& mXSSO; int32_t mStatusUpdated; string mSocketName; inline HandleStatusRequestMsg(XtraSystemStatusObserver& xsso, int32_t statusUpdated, string socketName) : mXSSO(xsso), mStatusUpdated(statusUpdated), mSocketName(socketName) {} inline void proc() const override { mXSSO.onStatusRequested(mStatusUpdated); /* SSR for DGnss Ntrip Source*/ if (0 == mSocketName.compare(LOC_IPC_DGNSS)) { mXSSO.restartDgnssSource(); } } }; mMsgTask->sendMsg(new HandleStatusRequestMsg(mXSSO, xtraStatusUpdated, socketName)); } else { LOC_LOGw("unknown event: %s", data); } } }; XtraSystemStatusObserver::XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask) : mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask), mGpsLock(-1), mConnections(~0), mRoaming(false), mXtraThrottle(true), mReqStatusReceived(false), mIsConnectivityStatusKnown(false), mXtraSender(LocIpc::getLocIpcLocalSender(LOC_IPC_XTRA)), mDgnssSender(LocIpc::getLocIpcLocalSender(LOC_IPC_DGNSS)), mDelayLocTimer(*mXtraSender, *mDgnssSender) { subscribe(true); auto recver = LocIpc::getLocIpcLocalRecver( make_shared(sysStatObs, msgTask, *this), LOC_IPC_HAL); mIpc.startNonBlockingListening(recver); mDelayLocTimer.start(100 /*.1 sec*/, false); } bool XtraSystemStatusObserver::updateLockStatus(GnssConfigGpsLock lock) { // mask NI(NFW bit) since from XTRA's standpoint GPS is enabled if // MO(AFW bit) is enabled and disabled when MO is disabled mGpsLock = lock & ~GNSS_CONFIG_GPS_LOCK_NFW_ALL; if (!mReqStatusReceived) { return true; } stringstream ss; ss << "gpslock"; ss << " " << mGpsLock; string s = ss.str(); return ( LocIpc::send(*mXtraSender, (const uint8_t*)s.data(), s.size()) ); } bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections, NetworkInfoType* networkHandleInfo, bool roaming) { mIsConnectivityStatusKnown = true; mConnections = allConnections; mRoaming = roaming; LOC_LOGd("updateConnections mConnections:%" PRIx64 " mRoaming:%u", mConnections, mRoaming); for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) { mNetworkHandle[i] = networkHandleInfo[i]; LOC_LOGd("updateConnections [%d] networkHandle:%" PRIx64 " networkType:%u", i, mNetworkHandle[i].networkHandle, mNetworkHandle[i].networkType); } if (!mReqStatusReceived) { return true; } stringstream ss; ss << "connection" << endl << mConnections << endl << mNetworkHandle[0].toString() << endl << mNetworkHandle[1].toString() << endl << mNetworkHandle[2].toString() << endl << mNetworkHandle[3].toString() << endl << mNetworkHandle[4].toString() << endl << mNetworkHandle[5].toString() << endl << mNetworkHandle[6].toString() << endl << mNetworkHandle[7].toString() << endl << mNetworkHandle[8].toString() << endl << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString() << endl << (mRoaming ? 1 : 0); string s = ss.str(); LocIpc::send(*mDgnssSender, (const uint8_t*)s.data(), s.size()); return ( LocIpc::send(*mXtraSender, (const uint8_t*)s.data(), s.size())); } bool XtraSystemStatusObserver::updateTac(const string& tac) { mTac = tac; if (!mReqStatusReceived) { return true; } stringstream ss; ss << "tac"; ss << " " << tac.c_str(); string s = ss.str(); return ( LocIpc::send(*mXtraSender, (const uint8_t*)s.data(), s.size()) ); } bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) { mMccmnc = mccmnc; if (!mReqStatusReceived) { return true; } stringstream ss; ss << "mncmcc"; ss << " " << mccmnc.c_str(); string s = ss.str(); return ( LocIpc::send(*mXtraSender, (const uint8_t*)s.data(), s.size()) ); } bool XtraSystemStatusObserver::updateXtraThrottle(const bool enabled) { mXtraThrottle = enabled; if (!mReqStatusReceived) { return true; } stringstream ss; ss << "xtrathrottle"; ss << " " << (enabled ? 1 : 0); string s = ss.str(); return ( LocIpc::send(*mXtraSender, (const uint8_t*)s.data(), s.size()) ); } inline bool XtraSystemStatusObserver::onStatusRequested(int32_t statusUpdated) { mReqStatusReceived = true; if (statusUpdated) { return true; } stringstream ss; ss << "respondStatus" << endl; (mGpsLock == -1 ? ss : ss << mGpsLock) << endl; (mConnections == (uint64_t)~0 ? ss : ss << mConnections) << endl << mNetworkHandle[0].toString() << endl << mNetworkHandle[1].toString() << endl << mNetworkHandle[2].toString() << endl << mNetworkHandle[3].toString() << endl << mNetworkHandle[4].toString() << endl << mNetworkHandle[5].toString() << endl << mNetworkHandle[6].toString() << endl << mNetworkHandle[7].toString() << endl << mNetworkHandle[8].toString() << endl << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString() << endl << mTac << endl << mMccmnc << endl << mIsConnectivityStatusKnown; string s = ss.str(); LocIpc::send(*mDgnssSender, (const uint8_t*)s.data(), s.size()); return ( LocIpc::send(*mXtraSender, (const uint8_t*)s.data(), s.size()) ); } void XtraSystemStatusObserver::startDgnssSource(const StartDgnssNtripParams& params) { stringstream ss; const GnssNtripConnectionParams* ntripParams = &(params.ntripParams); ss << "startDgnssSource" << endl; ss << ntripParams->useSSL << endl; ss << ntripParams->hostNameOrIp.data() << endl; ss << ntripParams->port << endl; ss << ntripParams->mountPoint.data() << endl; ss << ntripParams->username.data() << endl; ss << ntripParams->password.data() << endl; if (ntripParams->requiresNmeaLocation && !params.nmea.empty()) { ss << params.nmea.data() << endl; } string s = ss.str(); LOC_LOGd("%s", s.data()); LocIpc::send(*mDgnssSender, (const uint8_t*)s.data(), s.size()); // make a local copy of the string for SSR mNtripParamsString.assign(std::move(s)); } void XtraSystemStatusObserver::restartDgnssSource() { if (!mNtripParamsString.empty()) { LocIpc::send(*mDgnssSender, (const uint8_t*)mNtripParamsString.data(), mNtripParamsString.size()); LOC_LOGv("Xtra SSR %s", mNtripParamsString.data()); } } void XtraSystemStatusObserver::stopDgnssSource() { LOC_LOGv(); mNtripParamsString.clear(); const char s[] = "stopDgnssSource"; LocIpc::send(*mDgnssSender, (const uint8_t*)s, strlen(s)); } void XtraSystemStatusObserver::updateNmeaToDgnssServer(const string& nmea) { stringstream ss; ss << "updateDgnssServerNmea" << endl; ss << nmea.data() << endl; string s = ss.str(); LOC_LOGd("%s", s.data()); LocIpc::send(*mDgnssSender, (const uint8_t*)s.data(), s.size()); } void XtraSystemStatusObserver::subscribe(bool yes) { // Subscription data unordered_set unordered_set subItemIdSet; subItemIdSet.insert(NETWORKINFO_DATA_ITEM_ID); subItemIdSet.insert(MCCMNC_DATA_ITEM_ID); if (yes) { mSystemStatusObsrvr->subscribe(subItemIdSet, this); unordered_set reqItemIdSet; reqItemIdSet.insert(TAC_DATA_ITEM_ID); mSystemStatusObsrvr->requestData(reqItemIdSet, this); } else { mSystemStatusObsrvr->unsubscribe(subItemIdSet, this); } } // IDataItemObserver overrides void XtraSystemStatusObserver::getName(string& name) { name = "XtraSystemStatusObserver"; } void XtraSystemStatusObserver::notify(const unordered_set& dlist) { struct HandleOsObserverUpdateMsg : public LocMsg { XtraSystemStatusObserver* mXtraSysStatObj; list mDataItemList; inline HandleOsObserverUpdateMsg(XtraSystemStatusObserver* xtraSysStatObs, const unordered_set& dataItemList) : mXtraSysStatObj(xtraSysStatObs) { for (auto eachItem : dataItemList) { IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(eachItem); if (NULL == dataitem) { break; } mDataItemList.push_back(dataitem); } } inline ~HandleOsObserverUpdateMsg() { for (auto itor = mDataItemList.begin(); itor != mDataItemList.end(); ++itor) { if (*itor != nullptr) { delete *itor; *itor = nullptr; } } } inline void proc() const { for (auto each : mDataItemList) { switch (each->getId()) { case NETWORKINFO_DATA_ITEM_ID: { NetworkInfoDataItem* networkInfo = static_cast(each); NetworkInfoType* networkHandleInfo = static_cast(networkInfo->getNetworkHandle()); mXtraSysStatObj->updateConnections(networkInfo->getAllTypes(), networkHandleInfo, (*networkInfo).mRoaming); } break; case TAC_DATA_ITEM_ID: { TacDataItem* tac = static_cast(each); mXtraSysStatObj->updateTac(tac->mValue); } break; case MCCMNC_DATA_ITEM_ID: { MccmncDataItem* mccmnc = static_cast(each); mXtraSysStatObj->updateMccMnc(mccmnc->mValue); } break; default: break; } } } }; mMsgTask->sendMsg(new (nothrow) HandleOsObserverUpdateMsg(this, dlist)); }