1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "GnssNavigationMessageAidl"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include "GnssNavigationMessageInterface.h"
20*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/gnss/BnGnss.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <log/log.h>
22*4d7e907cSAndroid Build Coastguard Worker #include "Utils.h"
23*4d7e907cSAndroid Build Coastguard Worker
24*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::gnss {
25*4d7e907cSAndroid Build Coastguard Worker
26*4d7e907cSAndroid Build Coastguard Worker using namespace ::android::hardware::gnss;
27*4d7e907cSAndroid Build Coastguard Worker using GnssNavigationMessage = IGnssNavigationMessageCallback::GnssNavigationMessage;
28*4d7e907cSAndroid Build Coastguard Worker using GnssNavigationMessageType = GnssNavigationMessage::GnssNavigationMessageType;
29*4d7e907cSAndroid Build Coastguard Worker
30*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IGnssNavigationMessageCallback> GnssNavigationMessageInterface::sCallback = nullptr;
31*4d7e907cSAndroid Build Coastguard Worker
GnssNavigationMessageInterface()32*4d7e907cSAndroid Build Coastguard Worker GnssNavigationMessageInterface::GnssNavigationMessageInterface() : mMinIntervalMillis(1000) {
33*4d7e907cSAndroid Build Coastguard Worker mThreads.reserve(2);
34*4d7e907cSAndroid Build Coastguard Worker }
35*4d7e907cSAndroid Build Coastguard Worker
~GnssNavigationMessageInterface()36*4d7e907cSAndroid Build Coastguard Worker GnssNavigationMessageInterface::~GnssNavigationMessageInterface() {
37*4d7e907cSAndroid Build Coastguard Worker waitForStoppingThreads();
38*4d7e907cSAndroid Build Coastguard Worker }
39*4d7e907cSAndroid Build Coastguard Worker
setCallback(const std::shared_ptr<IGnssNavigationMessageCallback> & callback)40*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus GnssNavigationMessageInterface::setCallback(
41*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<IGnssNavigationMessageCallback>& callback) {
42*4d7e907cSAndroid Build Coastguard Worker ALOGD("setCallback");
43*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
44*4d7e907cSAndroid Build Coastguard Worker sCallback = callback;
45*4d7e907cSAndroid Build Coastguard Worker start();
46*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
47*4d7e907cSAndroid Build Coastguard Worker }
48*4d7e907cSAndroid Build Coastguard Worker
close()49*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus GnssNavigationMessageInterface::close() {
50*4d7e907cSAndroid Build Coastguard Worker ALOGD("close");
51*4d7e907cSAndroid Build Coastguard Worker if (mIsActive) {
52*4d7e907cSAndroid Build Coastguard Worker stop();
53*4d7e907cSAndroid Build Coastguard Worker }
54*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
55*4d7e907cSAndroid Build Coastguard Worker sCallback = nullptr;
56*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
57*4d7e907cSAndroid Build Coastguard Worker }
58*4d7e907cSAndroid Build Coastguard Worker
start()59*4d7e907cSAndroid Build Coastguard Worker void GnssNavigationMessageInterface::start() {
60*4d7e907cSAndroid Build Coastguard Worker ALOGD("start");
61*4d7e907cSAndroid Build Coastguard Worker
62*4d7e907cSAndroid Build Coastguard Worker if (mIsActive) {
63*4d7e907cSAndroid Build Coastguard Worker ALOGD("restarting since nav msg has started");
64*4d7e907cSAndroid Build Coastguard Worker stop();
65*4d7e907cSAndroid Build Coastguard Worker }
66*4d7e907cSAndroid Build Coastguard Worker
67*4d7e907cSAndroid Build Coastguard Worker mIsActive = true;
68*4d7e907cSAndroid Build Coastguard Worker mThreads.emplace_back(std::thread([this]() {
69*4d7e907cSAndroid Build Coastguard Worker waitForStoppingThreads();
70*4d7e907cSAndroid Build Coastguard Worker mThreadBlocker.reset();
71*4d7e907cSAndroid Build Coastguard Worker do {
72*4d7e907cSAndroid Build Coastguard Worker if (!mIsActive) {
73*4d7e907cSAndroid Build Coastguard Worker break;
74*4d7e907cSAndroid Build Coastguard Worker }
75*4d7e907cSAndroid Build Coastguard Worker GnssNavigationMessage message = {
76*4d7e907cSAndroid Build Coastguard Worker .svid = 19,
77*4d7e907cSAndroid Build Coastguard Worker .type = GnssNavigationMessageType::GPS_L1CA,
78*4d7e907cSAndroid Build Coastguard Worker .status = GnssNavigationMessage::STATUS_PARITY_PASSED,
79*4d7e907cSAndroid Build Coastguard Worker .messageId = 2,
80*4d7e907cSAndroid Build Coastguard Worker .submessageId = 3,
81*4d7e907cSAndroid Build Coastguard Worker .data = std::vector<uint8_t>(40, 0xF9),
82*4d7e907cSAndroid Build Coastguard Worker };
83*4d7e907cSAndroid Build Coastguard Worker this->reportMessage(message);
84*4d7e907cSAndroid Build Coastguard Worker } while (mIsActive &&
85*4d7e907cSAndroid Build Coastguard Worker mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMillis)));
86*4d7e907cSAndroid Build Coastguard Worker }));
87*4d7e907cSAndroid Build Coastguard Worker }
88*4d7e907cSAndroid Build Coastguard Worker
stop()89*4d7e907cSAndroid Build Coastguard Worker void GnssNavigationMessageInterface::stop() {
90*4d7e907cSAndroid Build Coastguard Worker ALOGD("stop");
91*4d7e907cSAndroid Build Coastguard Worker mIsActive = false;
92*4d7e907cSAndroid Build Coastguard Worker mThreadBlocker.notify();
93*4d7e907cSAndroid Build Coastguard Worker for (auto iter = mThreads.begin(); iter != mThreads.end();) {
94*4d7e907cSAndroid Build Coastguard Worker if (iter->joinable()) {
95*4d7e907cSAndroid Build Coastguard Worker // Store the thread object by value
96*4d7e907cSAndroid Build Coastguard Worker std::thread threadToMove = std::move(*iter);
97*4d7e907cSAndroid Build Coastguard Worker
98*4d7e907cSAndroid Build Coastguard Worker mFutures.push_back(std::async(std::launch::async,
99*4d7e907cSAndroid Build Coastguard Worker [threadToMove = std::move(threadToMove)]() mutable {
100*4d7e907cSAndroid Build Coastguard Worker ALOGD("joining thread");
101*4d7e907cSAndroid Build Coastguard Worker threadToMove.join();
102*4d7e907cSAndroid Build Coastguard Worker }));
103*4d7e907cSAndroid Build Coastguard Worker }
104*4d7e907cSAndroid Build Coastguard Worker iter = mThreads.erase(iter);
105*4d7e907cSAndroid Build Coastguard Worker }
106*4d7e907cSAndroid Build Coastguard Worker }
107*4d7e907cSAndroid Build Coastguard Worker
reportMessage(const GnssNavigationMessage & message)108*4d7e907cSAndroid Build Coastguard Worker void GnssNavigationMessageInterface::reportMessage(const GnssNavigationMessage& message) {
109*4d7e907cSAndroid Build Coastguard Worker ALOGD("reportMessage()");
110*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IGnssNavigationMessageCallback> callbackCopy;
111*4d7e907cSAndroid Build Coastguard Worker {
112*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
113*4d7e907cSAndroid Build Coastguard Worker if (sCallback == nullptr) {
114*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: GnssNavigationMessageInterface::sCallback is null.", __func__);
115*4d7e907cSAndroid Build Coastguard Worker return;
116*4d7e907cSAndroid Build Coastguard Worker }
117*4d7e907cSAndroid Build Coastguard Worker callbackCopy = sCallback;
118*4d7e907cSAndroid Build Coastguard Worker }
119*4d7e907cSAndroid Build Coastguard Worker callbackCopy->gnssNavigationMessageCb(message);
120*4d7e907cSAndroid Build Coastguard Worker }
121*4d7e907cSAndroid Build Coastguard Worker
waitForStoppingThreads()122*4d7e907cSAndroid Build Coastguard Worker void GnssNavigationMessageInterface::waitForStoppingThreads() {
123*4d7e907cSAndroid Build Coastguard Worker for (auto& future : mFutures) {
124*4d7e907cSAndroid Build Coastguard Worker ALOGD("Stopping previous thread.");
125*4d7e907cSAndroid Build Coastguard Worker future.wait();
126*4d7e907cSAndroid Build Coastguard Worker ALOGD("Done stopping thread.");
127*4d7e907cSAndroid Build Coastguard Worker }
128*4d7e907cSAndroid Build Coastguard Worker mFutures.clear();
129*4d7e907cSAndroid Build Coastguard Worker }
130*4d7e907cSAndroid Build Coastguard Worker
131*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl::android::hardware::gnss
132