Home | History | Annotate | Download | only in default
      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 <cutils/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 
     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 
     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 
    112 void GnssBatching::acquireWakelockCb() {
    113     Gnss::acquireWakelockFused();
    114 }
    115 
    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
    121 int32_t GnssBatching::setThreadEventCb(ThreadEvent /*event*/) {
    122     return FLP_RESULT_SUCCESS;
    123 }
    124 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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