1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2016 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 "GnssHAL_GnssBatchingInterface"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include "GnssBatching.h"
20*4d7e907cSAndroid Build Coastguard Worker #include <Gnss.h> // for wakelock consolidation
21*4d7e907cSAndroid Build Coastguard Worker #include <GnssUtils.h>
22*4d7e907cSAndroid Build Coastguard Worker
23*4d7e907cSAndroid Build Coastguard Worker #include <android/log.h> // for ALOGE
24*4d7e907cSAndroid Build Coastguard Worker #include <vector>
25*4d7e907cSAndroid Build Coastguard Worker
26*4d7e907cSAndroid Build Coastguard Worker namespace android {
27*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
28*4d7e907cSAndroid Build Coastguard Worker namespace gnss {
29*4d7e907cSAndroid Build Coastguard Worker namespace V1_0 {
30*4d7e907cSAndroid Build Coastguard Worker namespace implementation {
31*4d7e907cSAndroid Build Coastguard Worker
32*4d7e907cSAndroid Build Coastguard Worker sp<IGnssBatchingCallback> GnssBatching::sGnssBatchingCbIface = nullptr;
33*4d7e907cSAndroid Build Coastguard Worker bool GnssBatching::sFlpSupportsBatching = false;
34*4d7e907cSAndroid Build Coastguard Worker
35*4d7e907cSAndroid Build Coastguard Worker FlpCallbacks GnssBatching::sFlpCb = {
36*4d7e907cSAndroid Build Coastguard Worker .size = sizeof(FlpCallbacks),
37*4d7e907cSAndroid Build Coastguard Worker .location_cb = locationCb,
38*4d7e907cSAndroid Build Coastguard Worker .acquire_wakelock_cb = acquireWakelockCb,
39*4d7e907cSAndroid Build Coastguard Worker .release_wakelock_cb = releaseWakelockCb,
40*4d7e907cSAndroid Build Coastguard Worker .set_thread_event_cb = setThreadEventCb,
41*4d7e907cSAndroid Build Coastguard Worker .flp_capabilities_cb = flpCapabilitiesCb,
42*4d7e907cSAndroid Build Coastguard Worker .flp_status_cb = flpStatusCb,
43*4d7e907cSAndroid Build Coastguard Worker };
44*4d7e907cSAndroid Build Coastguard Worker
GnssBatching(const FlpLocationInterface * flpLocationIface)45*4d7e907cSAndroid Build Coastguard Worker GnssBatching::GnssBatching(const FlpLocationInterface* flpLocationIface) :
46*4d7e907cSAndroid Build Coastguard Worker mFlpLocationIface(flpLocationIface) {
47*4d7e907cSAndroid Build Coastguard Worker }
48*4d7e907cSAndroid Build Coastguard Worker
49*4d7e907cSAndroid Build Coastguard Worker /*
50*4d7e907cSAndroid Build Coastguard Worker * This enum is used locally by various methods below. It is only used by the default
51*4d7e907cSAndroid Build Coastguard Worker * implementation and is not part of the GNSS interface.
52*4d7e907cSAndroid Build Coastguard Worker */
53*4d7e907cSAndroid Build Coastguard Worker enum BatchingValues : uint16_t {
54*4d7e907cSAndroid Build Coastguard Worker // Numbers 0-3 were used in earlier implementations - using 4 to be distinct to the HAL
55*4d7e907cSAndroid Build Coastguard Worker FLP_GNSS_BATCHING_CLIENT_ID = 4,
56*4d7e907cSAndroid Build Coastguard Worker // Tech. mask of GNSS, and sensor aiding, for legacy HAL to fit with GnssBatching API
57*4d7e907cSAndroid Build Coastguard Worker FLP_TECH_MASK_GNSS_AND_SENSORS = FLP_TECH_MASK_GNSS | FLP_TECH_MASK_SENSORS,
58*4d7e907cSAndroid Build Coastguard Worker // Putting a cap to avoid possible memory issues. Unlikely values this high are supported.
59*4d7e907cSAndroid Build Coastguard Worker MAX_LOCATIONS_PER_BATCH = 1000
60*4d7e907cSAndroid Build Coastguard Worker };
61*4d7e907cSAndroid Build Coastguard Worker
locationCb(int32_t locationsCount,FlpLocation ** locations)62*4d7e907cSAndroid Build Coastguard Worker void GnssBatching::locationCb(int32_t locationsCount, FlpLocation** locations) {
63*4d7e907cSAndroid Build Coastguard Worker if (sGnssBatchingCbIface == nullptr) {
64*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: GNSS Batching Callback Interface configured incorrectly", __func__);
65*4d7e907cSAndroid Build Coastguard Worker return;
66*4d7e907cSAndroid Build Coastguard Worker }
67*4d7e907cSAndroid Build Coastguard Worker
68*4d7e907cSAndroid Build Coastguard Worker if (locations == nullptr) {
69*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Invalid locations from GNSS HAL", __func__);
70*4d7e907cSAndroid Build Coastguard Worker return;
71*4d7e907cSAndroid Build Coastguard Worker }
72*4d7e907cSAndroid Build Coastguard Worker
73*4d7e907cSAndroid Build Coastguard Worker if (locationsCount < 0) {
74*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Negative location count: %d set to 0", __func__, locationsCount);
75*4d7e907cSAndroid Build Coastguard Worker locationsCount = 0;
76*4d7e907cSAndroid Build Coastguard Worker } else if (locationsCount > MAX_LOCATIONS_PER_BATCH) {
77*4d7e907cSAndroid Build Coastguard Worker ALOGW("%s: Unexpected high location count: %d set to %d", __func__, locationsCount,
78*4d7e907cSAndroid Build Coastguard Worker MAX_LOCATIONS_PER_BATCH);
79*4d7e907cSAndroid Build Coastguard Worker locationsCount = MAX_LOCATIONS_PER_BATCH;
80*4d7e907cSAndroid Build Coastguard Worker }
81*4d7e907cSAndroid Build Coastguard Worker
82*4d7e907cSAndroid Build Coastguard Worker /**
83*4d7e907cSAndroid Build Coastguard Worker * Note:
84*4d7e907cSAndroid Build Coastguard Worker * Some existing implementations may drop duplicate locations. These could be expanded here
85*4d7e907cSAndroid Build Coastguard Worker * but as there's ambiguity between no-GPS-fix vs. dropped duplicates in that implementation,
86*4d7e907cSAndroid Build Coastguard Worker * and that's not specified by the fused_location.h, that isn't safe to do here.
87*4d7e907cSAndroid Build Coastguard Worker * Fortunately, this shouldn't be a major issue in cases where GNSS batching is typically
88*4d7e907cSAndroid Build Coastguard Worker * used (e.g. when user is likely in vehicle/bicycle.)
89*4d7e907cSAndroid Build Coastguard Worker */
90*4d7e907cSAndroid Build Coastguard Worker std::vector<android::hardware::gnss::V1_0::GnssLocation> gnssLocations;
91*4d7e907cSAndroid Build Coastguard Worker for (int iLocation = 0; iLocation < locationsCount; iLocation++) {
92*4d7e907cSAndroid Build Coastguard Worker if (locations[iLocation] == nullptr) {
93*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Null location at slot: %d of %d, skipping", __func__, iLocation,
94*4d7e907cSAndroid Build Coastguard Worker locationsCount);
95*4d7e907cSAndroid Build Coastguard Worker continue;
96*4d7e907cSAndroid Build Coastguard Worker }
97*4d7e907cSAndroid Build Coastguard Worker if ((locations[iLocation]->sources_used & ~FLP_TECH_MASK_GNSS_AND_SENSORS) != 0)
98*4d7e907cSAndroid Build Coastguard Worker {
99*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Unrequested location type %d at slot: %d of %d, skipping", __func__,
100*4d7e907cSAndroid Build Coastguard Worker locations[iLocation]->sources_used, iLocation, locationsCount);
101*4d7e907cSAndroid Build Coastguard Worker continue;
102*4d7e907cSAndroid Build Coastguard Worker }
103*4d7e907cSAndroid Build Coastguard Worker gnssLocations.push_back(convertToGnssLocation(locations[iLocation]));
104*4d7e907cSAndroid Build Coastguard Worker }
105*4d7e907cSAndroid Build Coastguard Worker
106*4d7e907cSAndroid Build Coastguard Worker auto ret = sGnssBatchingCbIface->gnssLocationBatchCb(gnssLocations);
107*4d7e907cSAndroid Build Coastguard Worker if (!ret.isOk()) {
108*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Unable to invoke callback", __func__);
109*4d7e907cSAndroid Build Coastguard Worker }
110*4d7e907cSAndroid Build Coastguard Worker }
111*4d7e907cSAndroid Build Coastguard Worker
acquireWakelockCb()112*4d7e907cSAndroid Build Coastguard Worker void GnssBatching::acquireWakelockCb() {
113*4d7e907cSAndroid Build Coastguard Worker Gnss::acquireWakelockFused();
114*4d7e907cSAndroid Build Coastguard Worker }
115*4d7e907cSAndroid Build Coastguard Worker
releaseWakelockCb()116*4d7e907cSAndroid Build Coastguard Worker void GnssBatching::releaseWakelockCb() {
117*4d7e907cSAndroid Build Coastguard Worker Gnss::releaseWakelockFused();
118*4d7e907cSAndroid Build Coastguard Worker }
119*4d7e907cSAndroid Build Coastguard Worker
120*4d7e907cSAndroid Build Coastguard Worker // this can just return success, because threads are now set up on demand in the jni layer
setThreadEventCb(ThreadEvent)121*4d7e907cSAndroid Build Coastguard Worker int32_t GnssBatching::setThreadEventCb(ThreadEvent /*event*/) {
122*4d7e907cSAndroid Build Coastguard Worker return FLP_RESULT_SUCCESS;
123*4d7e907cSAndroid Build Coastguard Worker }
124*4d7e907cSAndroid Build Coastguard Worker
flpCapabilitiesCb(int32_t capabilities)125*4d7e907cSAndroid Build Coastguard Worker void GnssBatching::flpCapabilitiesCb(int32_t capabilities) {
126*4d7e907cSAndroid Build Coastguard Worker ALOGD("%s capabilities %d", __func__, capabilities);
127*4d7e907cSAndroid Build Coastguard Worker
128*4d7e907cSAndroid Build Coastguard Worker if (capabilities & CAPABILITY_GNSS) {
129*4d7e907cSAndroid Build Coastguard Worker // once callback is received and capabilities high enough, we know version is
130*4d7e907cSAndroid Build Coastguard Worker // high enough for flush()
131*4d7e907cSAndroid Build Coastguard Worker sFlpSupportsBatching = true;
132*4d7e907cSAndroid Build Coastguard Worker }
133*4d7e907cSAndroid Build Coastguard Worker }
134*4d7e907cSAndroid Build Coastguard Worker
flpStatusCb(int32_t status)135*4d7e907cSAndroid Build Coastguard Worker void GnssBatching::flpStatusCb(int32_t status) {
136*4d7e907cSAndroid Build Coastguard Worker ALOGD("%s (default implementation) not forwarding status: %d", __func__, status);
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker
139*4d7e907cSAndroid Build Coastguard Worker // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
init(const sp<IGnssBatchingCallback> & callback)140*4d7e907cSAndroid Build Coastguard Worker Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
141*4d7e907cSAndroid Build Coastguard Worker if (mFlpLocationIface == nullptr) {
142*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching is unavailable", __func__);
143*4d7e907cSAndroid Build Coastguard Worker return false;
144*4d7e907cSAndroid Build Coastguard Worker }
145*4d7e907cSAndroid Build Coastguard Worker
146*4d7e907cSAndroid Build Coastguard Worker sGnssBatchingCbIface = callback;
147*4d7e907cSAndroid Build Coastguard Worker
148*4d7e907cSAndroid Build Coastguard Worker return (mFlpLocationIface->init(&sFlpCb) == 0);
149*4d7e907cSAndroid Build Coastguard Worker }
150*4d7e907cSAndroid Build Coastguard Worker
getBatchSize()151*4d7e907cSAndroid Build Coastguard Worker Return<uint16_t> GnssBatching::getBatchSize() {
152*4d7e907cSAndroid Build Coastguard Worker if (mFlpLocationIface == nullptr) {
153*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching interface is unavailable", __func__);
154*4d7e907cSAndroid Build Coastguard Worker return 0;
155*4d7e907cSAndroid Build Coastguard Worker }
156*4d7e907cSAndroid Build Coastguard Worker
157*4d7e907cSAndroid Build Coastguard Worker return mFlpLocationIface->get_batch_size();
158*4d7e907cSAndroid Build Coastguard Worker }
159*4d7e907cSAndroid Build Coastguard Worker
start(const IGnssBatching::Options & options)160*4d7e907cSAndroid Build Coastguard Worker Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
161*4d7e907cSAndroid Build Coastguard Worker if (mFlpLocationIface == nullptr) {
162*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching interface is unavailable", __func__);
163*4d7e907cSAndroid Build Coastguard Worker return false;
164*4d7e907cSAndroid Build Coastguard Worker }
165*4d7e907cSAndroid Build Coastguard Worker
166*4d7e907cSAndroid Build Coastguard Worker if (!sFlpSupportsBatching) {
167*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching interface not supported, no capabilities callback received",
168*4d7e907cSAndroid Build Coastguard Worker __func__);
169*4d7e907cSAndroid Build Coastguard Worker return false;
170*4d7e907cSAndroid Build Coastguard Worker }
171*4d7e907cSAndroid Build Coastguard Worker
172*4d7e907cSAndroid Build Coastguard Worker FlpBatchOptions optionsHw;
173*4d7e907cSAndroid Build Coastguard Worker // Legacy code used 9999 mW for High accuracy, and 21 mW for balanced.
174*4d7e907cSAndroid Build Coastguard Worker // New GNSS API just expects reasonable GNSS chipset behavior - do something efficient
175*4d7e907cSAndroid Build Coastguard Worker // given the interval. This 100 mW limit should be quite sufficient (esp. given legacy code
176*4d7e907cSAndroid Build Coastguard Worker // implementations may not even use this value.)
177*4d7e907cSAndroid Build Coastguard Worker optionsHw.max_power_allocation_mW = 100;
178*4d7e907cSAndroid Build Coastguard Worker optionsHw.sources_to_use = FLP_TECH_MASK_GNSS_AND_SENSORS;
179*4d7e907cSAndroid Build Coastguard Worker optionsHw.flags = 0;
180*4d7e907cSAndroid Build Coastguard Worker if (options.flags & Flag::WAKEUP_ON_FIFO_FULL) {
181*4d7e907cSAndroid Build Coastguard Worker optionsHw.flags |= FLP_BATCH_WAKEUP_ON_FIFO_FULL;
182*4d7e907cSAndroid Build Coastguard Worker }
183*4d7e907cSAndroid Build Coastguard Worker optionsHw.period_ns = options.periodNanos;
184*4d7e907cSAndroid Build Coastguard Worker optionsHw.smallest_displacement_meters = 0; // Zero offset - just use time interval
185*4d7e907cSAndroid Build Coastguard Worker
186*4d7e907cSAndroid Build Coastguard Worker return (mFlpLocationIface->start_batching(FLP_GNSS_BATCHING_CLIENT_ID, &optionsHw)
187*4d7e907cSAndroid Build Coastguard Worker == FLP_RESULT_SUCCESS);
188*4d7e907cSAndroid Build Coastguard Worker }
189*4d7e907cSAndroid Build Coastguard Worker
flush()190*4d7e907cSAndroid Build Coastguard Worker Return<void> GnssBatching::flush() {
191*4d7e907cSAndroid Build Coastguard Worker if (mFlpLocationIface == nullptr) {
192*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching interface is unavailable", __func__);
193*4d7e907cSAndroid Build Coastguard Worker return Void();
194*4d7e907cSAndroid Build Coastguard Worker }
195*4d7e907cSAndroid Build Coastguard Worker
196*4d7e907cSAndroid Build Coastguard Worker mFlpLocationIface->flush_batched_locations();
197*4d7e907cSAndroid Build Coastguard Worker
198*4d7e907cSAndroid Build Coastguard Worker return Void();
199*4d7e907cSAndroid Build Coastguard Worker }
200*4d7e907cSAndroid Build Coastguard Worker
stop()201*4d7e907cSAndroid Build Coastguard Worker Return<bool> GnssBatching::stop() {
202*4d7e907cSAndroid Build Coastguard Worker if (mFlpLocationIface == nullptr) {
203*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching interface is unavailable", __func__);
204*4d7e907cSAndroid Build Coastguard Worker return false;
205*4d7e907cSAndroid Build Coastguard Worker }
206*4d7e907cSAndroid Build Coastguard Worker
207*4d7e907cSAndroid Build Coastguard Worker return (mFlpLocationIface->stop_batching(FLP_GNSS_BATCHING_CLIENT_ID) == FLP_RESULT_SUCCESS);
208*4d7e907cSAndroid Build Coastguard Worker }
209*4d7e907cSAndroid Build Coastguard Worker
cleanup()210*4d7e907cSAndroid Build Coastguard Worker Return<void> GnssBatching::cleanup() {
211*4d7e907cSAndroid Build Coastguard Worker if (mFlpLocationIface == nullptr) {
212*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Flp batching interface is unavailable", __func__);
213*4d7e907cSAndroid Build Coastguard Worker return Void();
214*4d7e907cSAndroid Build Coastguard Worker }
215*4d7e907cSAndroid Build Coastguard Worker
216*4d7e907cSAndroid Build Coastguard Worker mFlpLocationIface->cleanup();
217*4d7e907cSAndroid Build Coastguard Worker
218*4d7e907cSAndroid Build Coastguard Worker return Void();
219*4d7e907cSAndroid Build Coastguard Worker }
220*4d7e907cSAndroid Build Coastguard Worker
221*4d7e907cSAndroid Build Coastguard Worker } // namespace implementation
222*4d7e907cSAndroid Build Coastguard Worker } // namespace V1_0
223*4d7e907cSAndroid Build Coastguard Worker } // namespace gnss
224*4d7e907cSAndroid Build Coastguard Worker } // namespace hardware
225*4d7e907cSAndroid Build Coastguard Worker } // namespace android
226