xref: /aosp_15_r20/hardware/interfaces/gnss/1.0/default/GnssBatching.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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