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