summaryrefslogtreecommitdiff
path: root/gnss/aidl/default/GnssBatching.cpp
blob: b8be5e5baf5d67da33fc154404aadb84f1bc71d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "GnssBatchingAidl"

#include "GnssBatching.h"
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <inttypes.h>
#include <log/log.h>
#include <utils/SystemClock.h>
#include "Utils.h"

namespace aidl::android::hardware::gnss {

using namespace ::android::hardware::gnss;

constexpr int BATCH_SIZE = 10;

std::shared_ptr<IGnssBatchingCallback> GnssBatching::sCallback = nullptr;

GnssBatching::GnssBatching()
    : mMinIntervalMs(1000),
      mWakeUpOnFifoFull(false),
      mBatchedLocations(std::vector<GnssLocation>()) {}
GnssBatching::~GnssBatching() {
    cleanup();
}

ndk::ScopedAStatus GnssBatching::init(const std::shared_ptr<IGnssBatchingCallback>& callback) {
    ALOGD("init");
    std::unique_lock<std::mutex> lock(mMutex);
    sCallback = callback;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus GnssBatching::getBatchSize(int* size) {
    ALOGD("getBatchingSize");
    *size = BATCH_SIZE;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus GnssBatching::start(int64_t periodNanos, int flags) {
    ALOGD("start: periodNanos=%" PRId64 ", flags=%d", periodNanos, flags);
    if (mIsActive) {
        ALOGW("Gnss has started. Restarting...");
        stop();
    }

    mWakeUpOnFifoFull = (flags & IGnssBatching::WAKEUP_ON_FIFO_FULL) ? true : false;
    // mMinIntervalMs is not smaller than 1 sec
    periodNanos = (periodNanos < 1e9) ? 1e9 : periodNanos;
    mMinIntervalMs = periodNanos / 1e6;

    mIsActive = true;
    mThread = std::thread([this]() {
        while (mIsActive == true) {
            const auto location = common::Utils::getMockLocation();
            this->batchLocation(location);
            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
        }
    });

    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus GnssBatching::flush() {
    ALOGD("flush");
    std::vector<GnssLocation> copy = std::vector<GnssLocation>(mBatchedLocations);
    ndk::ScopedAStatus status;
    if (sCallback != nullptr) {
        sCallback->gnssLocationBatchCb(copy);
        status = ndk::ScopedAStatus::ok();
    } else {
        ALOGE("GnssBatchingCallback is null. flush() failed.");
        status = ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_GENERIC);
    }
    mBatchedLocations.clear();
    return status;
}

ndk::ScopedAStatus GnssBatching::stop() {
    ALOGD("stop");
    // Do not call flush() at stop()
    mIsActive = false;
    if (mThread.joinable()) {
        mThread.join();
    }
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus GnssBatching::cleanup() {
    ALOGD("cleanup");
    std::unique_lock<std::mutex> lock(mMutex);
    if (mIsActive) {
        stop();
    }
    flush();

    sCallback = nullptr;
    return ndk::ScopedAStatus::ok();
}

void GnssBatching::batchLocation(const GnssLocation& location) {
    if (mBatchedLocations.size() > BATCH_SIZE) {
        mBatchedLocations.erase(mBatchedLocations.begin());
    }
    mBatchedLocations.push_back(location);
    if (mWakeUpOnFifoFull && mBatchedLocations.size() == BATCH_SIZE) {
        flush();
    }
}

}  // namespace aidl::android::hardware::gnss