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_AGnssInterface"
     18 
     19 #include "AGnss.h"
     20 
     21 namespace android {
     22 namespace hardware {
     23 namespace gnss {
     24 namespace V1_0 {
     25 namespace implementation {
     26 
     27 std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
     28 sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
     29 bool AGnss::sInterfaceExists = false;
     30 
     31 AGpsCallbacks AGnss::sAGnssCb = {
     32     .status_cb = statusCb,
     33     .create_thread_cb = createThreadCb
     34 };
     35 
     36 AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
     37     /* Error out if an instance of the interface already exists. */
     38     LOG_ALWAYS_FATAL_IF(sInterfaceExists);
     39     sInterfaceExists = true;
     40 }
     41 
     42 AGnss::~AGnss() {
     43     sThreadFuncArgsList.clear();
     44     sInterfaceExists = false;
     45 }
     46 
     47 void AGnss::statusCb(AGpsStatus* status) {
     48     if (sAGnssCbIface == nullptr) {
     49         ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
     50         return;
     51     }
     52 
     53     if (status == nullptr) {
     54         ALOGE("AGNSS status is invalid");
     55         return;
     56     }
     57 
     58     /*
     59      * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
     60      * AGpsStatus is checked for backward compatibility since some devices may
     61      * be sending out an older version of AGpsStatus that only supports IPv4.
     62      */
     63     size_t statusSize = status->size;
     64     if (status->size == sizeof(AGpsStatus)) {
     65         switch (status->addr.ss_family)
     66         {
     67             case AF_INET:
     68                 {
     69                     /*
     70                      * ss_family indicates IPv4.
     71                      */
     72                     struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
     73                     IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
     74                         .type = static_cast<IAGnssCallback::AGnssType>(status->type),
     75                         .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
     76                         .ipV4Addr = in->sin_addr.s_addr,
     77                     };
     78 
     79                     /*
     80                      * Callback to client with agnssStatusIpV4Cb.
     81                      */
     82                     auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
     83                     if (!ret.isOk()) {
     84                         ALOGE("%s: Unable to invoke callback", __func__);
     85                     }
     86                     break;
     87                 }
     88             case AF_INET6:
     89                 {
     90                     /*
     91                      * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
     92                      */
     93                     IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
     94 
     95                     aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
     96                     aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
     97                             status->status);
     98 
     99                     struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
    100                             &(status->addr));
    101                     memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
    102                            aGnssStatusIpV6.ipV6Addr.size());
    103                     auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
    104                     if (!ret.isOk()) {
    105                         ALOGE("%s: Unable to invoke callback", __func__);
    106                     }
    107                     break;
    108                 }
    109              default:
    110                     ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
    111         }
    112     } else if (statusSize >= sizeof(AGpsStatus_v2)) {
    113         AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
    114         uint32_t ipV4Addr = statusV2->ipaddr;
    115         IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
    116             .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
    117             .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
    118             /*
    119              * For older versions of AGpsStatus, change IP addr to net order. This
    120              * was earlier being done in GnssLocationProvider.
    121              */
    122             .ipV4Addr = htonl(ipV4Addr)
    123         };
    124         /*
    125          * Callback to client with agnssStatusIpV4Cb.
    126          */
    127         auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
    128         if (!ret.isOk()) {
    129             ALOGE("%s: Unable to invoke callback", __func__);
    130         }
    131     } else {
    132         ALOGE("%s: Invalid size for AGPS Status", __func__);
    133     }
    134 }
    135 
    136 pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
    137     return createPthread(name, start, arg, &sThreadFuncArgsList);
    138 }
    139 
    140 /*
    141  * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
    142  */
    143 Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
    144     if (mAGnssIface == nullptr) {
    145         ALOGE("%s: AGnss interface is unavailable", __func__);
    146         return Void();
    147     }
    148 
    149     sAGnssCbIface = callback;
    150 
    151     mAGnssIface->init(&sAGnssCb);
    152     return Void();
    153 }
    154 
    155 Return<bool> AGnss::dataConnClosed()  {
    156     if (mAGnssIface == nullptr) {
    157         ALOGE("%s: AGnss interface is unavailable", __func__);
    158         return false;
    159     }
    160 
    161     return (mAGnssIface->data_conn_closed() == 0);
    162 }
    163 
    164 Return<bool> AGnss::dataConnFailed()  {
    165     if (mAGnssIface == nullptr) {
    166         ALOGE("%s: AGnss interface is unavailable", __func__);
    167         return false;
    168     }
    169 
    170     return (mAGnssIface->data_conn_failed() == 0);
    171 }
    172 
    173 Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
    174                               const hidl_string& hostname,
    175                               int32_t port) {
    176     if (mAGnssIface == nullptr) {
    177         ALOGE("%s: AGnss interface is unavailable", __func__);
    178         return false;
    179     }
    180 
    181     return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
    182 }
    183 
    184 Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
    185     if (mAGnssIface == nullptr) {
    186         ALOGE("%s: AGnss interface is unavailable", __func__);
    187         return false;
    188     }
    189 
    190     return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
    191                                                      static_cast<uint16_t>(apnIpType)) == 0);
    192 }
    193 
    194 }  // namespace implementation
    195 }  // namespace V1_0
    196 }  // namespace gnss
    197 }  // namespace hardware
    198 }  // namespace android
    199