1 /*
2  * Copyright (C) 2020 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 #define LOG_TAG "GnssMeasIfaceAidl"
18 
19 #include "GnssMeasurementInterface.h"
20 #include <aidl/android/hardware/gnss/BnGnss.h>
21 #include <log/log.h>
22 #include "DeviceFileReader.h"
23 #include "Gnss.h"
24 #include "GnssRawMeasurementParser.h"
25 #include "GnssReplayUtils.h"
26 #include "Utils.h"
27 
28 namespace aidl::android::hardware::gnss {
29 
30 using Utils = ::android::hardware::gnss::common::Utils;
31 using ReplayUtils = ::android::hardware::gnss::common::ReplayUtils;
32 using GnssRawMeasurementParser = ::android::hardware::gnss::common::GnssRawMeasurementParser;
33 using DeviceFileReader = ::android::hardware::gnss::common::DeviceFileReader;
34 
35 std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
36 
GnssMeasurementInterface()37 GnssMeasurementInterface::GnssMeasurementInterface()
38     : mIntervalMs(1000), mLocationIntervalMs(1000) {
39     mThreads.reserve(2);
40 }
41 
~GnssMeasurementInterface()42 GnssMeasurementInterface::~GnssMeasurementInterface() {
43     waitForStoppingThreads();
44 }
45 
setCallback(const std::shared_ptr<IGnssMeasurementCallback> & callback,const bool enableFullTracking,const bool enableCorrVecOutputs)46 ndk::ScopedAStatus GnssMeasurementInterface::setCallback(
47         const std::shared_ptr<IGnssMeasurementCallback>& callback, const bool enableFullTracking,
48         const bool enableCorrVecOutputs) {
49     ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking,
50           (int)enableCorrVecOutputs);
51     {
52         std::unique_lock<std::mutex> lock(mMutex);
53         sCallback = callback;
54     }
55 
56     if (mIsActive) {
57         ALOGW("GnssMeasurement callback already set. Resetting the callback...");
58         stop();
59     }
60     start(enableCorrVecOutputs, enableFullTracking);
61 
62     return ndk::ScopedAStatus::ok();
63 }
64 
setCallbackWithOptions(const std::shared_ptr<IGnssMeasurementCallback> & callback,const Options & options)65 ndk::ScopedAStatus GnssMeasurementInterface::setCallbackWithOptions(
66         const std::shared_ptr<IGnssMeasurementCallback>& callback, const Options& options) {
67     ALOGD("setCallbackWithOptions: fullTracking:%d, corrVec:%d, intervalMs:%d",
68           (int)options.enableFullTracking, (int)options.enableCorrVecOutputs, options.intervalMs);
69     {
70         std::unique_lock<std::mutex> lock(mMutex);
71         sCallback = callback;
72     }
73 
74     if (mIsActive) {
75         ALOGW("GnssMeasurement callback already set. Resetting the callback...");
76         stop();
77     }
78     mIntervalMs = std::max(options.intervalMs, 1000);
79     mGnss->setGnssMeasurementInterval(mIntervalMs);
80     start(options.enableCorrVecOutputs, options.enableFullTracking);
81 
82     return ndk::ScopedAStatus::ok();
83 }
84 
close()85 ndk::ScopedAStatus GnssMeasurementInterface::close() {
86     ALOGD("close");
87     if (mIsActive) {
88         stop();
89     }
90     {
91         std::unique_lock<std::mutex> lock(mMutex);
92         sCallback = nullptr;
93     }
94     mIntervalMs = 1000;
95     return ndk::ScopedAStatus::ok();
96 }
97 
start(const bool enableCorrVecOutputs,const bool enableFullTracking)98 void GnssMeasurementInterface::start(const bool enableCorrVecOutputs,
99                                      const bool enableFullTracking) {
100     ALOGD("start");
101 
102     if (mIsActive) {
103         ALOGD("restarting since measurement has started");
104         stop();
105     }
106 
107     mIsActive = true;
108     mGnss->setGnssMeasurementEnabled(true);
109     mThreads.emplace_back(std::thread([this, enableCorrVecOutputs, enableFullTracking]() {
110         waitForStoppingThreads();
111         mThreadBlocker.reset();
112 
113         int intervalMs;
114         do {
115             if (!mIsActive) {
116                 break;
117             }
118             std::string rawMeasurementStr = "";
119             if (ReplayUtils::hasGnssDeviceFile() &&
120                 ReplayUtils::isGnssRawMeasurement(
121                         rawMeasurementStr =
122                                 DeviceFileReader::Instance().getGnssRawMeasurementData())) {
123                 ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
124                       rawMeasurementStr.c_str());
125                 auto measurement =
126                         GnssRawMeasurementParser::getMeasurementFromStrs(rawMeasurementStr);
127                 if (measurement != nullptr) {
128                     this->reportMeasurement(*measurement);
129                 }
130             } else {
131                 auto measurement =
132                         Utils::getMockMeasurement(enableCorrVecOutputs, enableFullTracking);
133                 this->reportMeasurement(measurement);
134                 if (!mLocationEnabled || mLocationIntervalMs > mIntervalMs) {
135                     mGnss->reportSvStatus();
136                 }
137             }
138             intervalMs =
139                     (mLocationEnabled) ? std::min(mLocationIntervalMs, mIntervalMs) : mIntervalMs;
140         } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(intervalMs)));
141     }));
142 }
143 
stop()144 void GnssMeasurementInterface::stop() {
145     ALOGD("stop");
146     mIsActive = false;
147     mGnss->setGnssMeasurementEnabled(false);
148     mThreadBlocker.notify();
149     for (auto iter = mThreads.begin(); iter != mThreads.end();) {
150         if (iter->joinable()) {
151             // Store the thread object by value
152             std::thread threadToMove = std::move(*iter);
153 
154             mFutures.push_back(std::async(std::launch::async,
155                                           [threadToMove = std::move(threadToMove)]() mutable {
156                                               ALOGD("joining thread");
157                                               threadToMove.join();
158                                           }));
159         }
160         iter = mThreads.erase(iter);
161     }
162 }
163 
reportMeasurement(const GnssData & data)164 void GnssMeasurementInterface::reportMeasurement(const GnssData& data) {
165     ALOGD("reportMeasurement()");
166     std::shared_ptr<IGnssMeasurementCallback> callbackCopy;
167     {
168         std::unique_lock<std::mutex> lock(mMutex);
169         if (sCallback == nullptr) {
170             ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
171             return;
172         }
173         callbackCopy = sCallback;
174     }
175     callbackCopy->gnssMeasurementCb(data);
176 }
177 
setLocationInterval(const int intervalMs)178 void GnssMeasurementInterface::setLocationInterval(const int intervalMs) {
179     mLocationIntervalMs = intervalMs;
180 }
181 
setLocationEnabled(const bool enabled)182 void GnssMeasurementInterface::setLocationEnabled(const bool enabled) {
183     mLocationEnabled = enabled;
184 }
185 
setGnssInterface(const std::shared_ptr<Gnss> & gnss)186 void GnssMeasurementInterface::setGnssInterface(const std::shared_ptr<Gnss>& gnss) {
187     mGnss = gnss;
188 }
189 
waitForStoppingThreads()190 void GnssMeasurementInterface::waitForStoppingThreads() {
191     for (auto& future : mFutures) {
192         ALOGD("Stopping previous thread.");
193         future.wait();
194         ALOGD("Done stopping thread.");
195     }
196     mFutures.clear();
197 }
198 
199 }  // namespace aidl::android::hardware::gnss
200