blob: 42f14730acc78892d216b472c808b9a0adce5879 [file] [log] [blame]
Wyatt Riley8791e7b2017-01-17 12:12:25 -08001/*
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
Wyatt Rileyad03ab22016-12-14 14:54:29 -080019#include "GnssBatching.h"
Wyatt Riley8791e7b2017-01-17 12:12:25 -080020#include <Gnss.h> // for wakelock consolidation
21#include <GnssUtils.h>
22
23#include <cutils/log.h> // for ALOGE
24#include <vector>
Wyatt Rileyad03ab22016-12-14 14:54:29 -080025
26namespace android {
27namespace hardware {
28namespace gnss {
29namespace V1_0 {
30namespace implementation {
31
Wyatt Riley8791e7b2017-01-17 12:12:25 -080032sp<IGnssBatchingCallback> GnssBatching::sGnssBatchingCbIface = nullptr;
33bool GnssBatching::sFlpSupportsBatching = false;
Wyatt Rileyad03ab22016-12-14 14:54:29 -080034
Wyatt Riley8791e7b2017-01-17 12:12:25 -080035FlpCallbacks 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
45GnssBatching::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 */
53enum 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
62void 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
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800106 auto ret = sGnssBatchingCbIface->gnssLocationBatchCb(gnssLocations);
107 if (!ret.isOk()) {
108 ALOGE("%s: Unable to invoke callback", __func__);
109 }
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800110}
111
112void GnssBatching::acquireWakelockCb() {
113 Gnss::acquireWakelockFused();
114}
115
116void 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
121int32_t GnssBatching::setThreadEventCb(ThreadEvent event) {
122 return FLP_RESULT_SUCCESS;
123}
124
125void 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
135void GnssBatching::flpStatusCb(int32_t status) {
136 ALOGD("%s (default implementation) not forwarding status: %d", __func__, status);
137}
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800138
139// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
140Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800141 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);
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800149}
150
151Return<uint16_t> GnssBatching::getBatchSize() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800152 if (mFlpLocationIface == nullptr) {
153 ALOGE("%s: Flp batching interface is unavailable", __func__);
154 return 0;
155 }
156
157 return mFlpLocationIface->get_batch_size();
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800158}
159
160Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800161 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);
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800188}
189
190Return<void> GnssBatching::flush() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800191 if (mFlpLocationIface == nullptr) {
192 ALOGE("%s: Flp batching interface is unavailable", __func__);
193 return Void();
194 }
195
196 mFlpLocationIface->flush_batched_locations();
197
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800198 return Void();
199}
200
201Return<bool> GnssBatching::stop() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800202 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);
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800208}
209
210Return<void> GnssBatching::cleanup() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800211 if (mFlpLocationIface == nullptr) {
212 ALOGE("%s: Flp batching interface is unavailable", __func__);
213 return Void();
214 }
215
216 mFlpLocationIface->cleanup();
217
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800218 return Void();
219}
220
221} // namespace implementation
222} // namespace V1_0
223} // namespace gnss
224} // namespace hardware
225} // namespace android