1/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 * Not a Contribution
4 */
5/*
6 * Copyright (C) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#define LOG_TAG "LocSvc_GnssInterface"
22
23#include <log_util.h>
24#include <dlfcn.h>
25#include "Gnss.h"
26typedef void* (getLocationInterface)();
27
28namespace android {
29namespace hardware {
30namespace gnss {
31namespace V1_0 {
32namespace implementation {
33
34void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
35    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
36            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
37    if (mGnss != nullptr) {
38        mGnss->stop();
39        mGnss->cleanup();
40    }
41}
42
43Gnss::Gnss() {
44    ENTRY_LOG_CALLFLOW();
45    // clear pending GnssConfig
46    memset(&mPendingConfig, 0, sizeof(GnssConfig));
47
48    mGnssDeathRecipient = new GnssDeathRecipient(this);
49}
50
51Gnss::~Gnss() {
52    ENTRY_LOG_CALLFLOW();
53    if (mApi != nullptr) {
54        delete mApi;
55        mApi = nullptr;
56    }
57}
58
59GnssAPIClient* Gnss::getApi() {
60    if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) {
61        mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
62        if (mApi == nullptr) {
63            LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__);
64            return mApi;
65        }
66
67        if (mPendingConfig.size == sizeof(GnssConfig)) {
68            // we have pending GnssConfig
69            mApi->gnssConfigurationUpdate(mPendingConfig);
70            // clear size to invalid mPendingConfig
71            mPendingConfig.size = 0;
72            if (mPendingConfig.assistanceServer.hostName != nullptr) {
73                free((void*)mPendingConfig.assistanceServer.hostName);
74            }
75        }
76    }
77    if (mApi == nullptr) {
78        LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
79    }
80    return mApi;
81}
82
83GnssInterface* Gnss::getGnssInterface() {
84    static bool getGnssInterfaceFailed = false;
85    if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
86        LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__);
87        getLocationInterface* getter = NULL;
88        const char *error;
89        dlerror();
90        void *handle = dlopen("libgnss.so", RTLD_NOW);
91        if (NULL == handle || (error = dlerror()) != NULL)  {
92            LOC_LOGW("dlopen for libgnss.so failed, error = %s", error);
93        } else {
94            getter = (getLocationInterface*)dlsym(handle, "getGnssInterface");
95            if ((error = dlerror()) != NULL)  {
96                LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error);
97                getter = NULL;
98            }
99        }
100
101        if (NULL == getter) {
102            getGnssInterfaceFailed = true;
103        } else {
104            mGnssInterface = (GnssInterface*)(*getter)();
105        }
106    }
107    return mGnssInterface;
108}
109
110Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback)  {
111    ENTRY_LOG_CALLFLOW();
112    if (mGnssCbIface != nullptr) {
113        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
114    }
115    mGnssCbIface = callback;
116    if (mGnssCbIface != nullptr) {
117        mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
118    }
119
120    GnssAPIClient* api = getApi();
121    if (api != nullptr) {
122        api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
123        api->locAPIEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
124    }
125    return true;
126}
127
128Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
129    ENTRY_LOG_CALLFLOW();
130    mGnssNiCbIface = callback;
131    GnssAPIClient* api = getApi();
132    if (api != nullptr) {
133        api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
134    }
135    return true;
136}
137
138Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
139    ENTRY_LOG_CALLFLOW();
140    GnssAPIClient* api = getApi();
141    if (api) {
142        api->locAPIGnssUpdateConfig(gnssConfig);
143    } else if (gnssConfig.flags != 0) {
144        // api is not ready yet, update mPendingConfig with gnssConfig
145        mPendingConfig.size = sizeof(GnssConfig);
146
147        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
148            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
149            mPendingConfig.gpsLock = gnssConfig.gpsLock;
150        }
151        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
152            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
153            mPendingConfig.suplVersion = gnssConfig.suplVersion;
154        }
155        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
156            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
157            mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
158            mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
159            if (mPendingConfig.assistanceServer.hostName != nullptr) {
160                free((void*)mPendingConfig.assistanceServer.hostName);
161                mPendingConfig.assistanceServer.hostName =
162                    strdup(gnssConfig.assistanceServer.hostName);
163            }
164            mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
165        }
166        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
167            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
168            mPendingConfig.lppProfile = gnssConfig.lppProfile;
169        }
170        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
171            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
172            mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
173        }
174        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
175            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
176            mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
177        }
178        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
179            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
180            mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
181        }
182        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
183            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
184            mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
185        }
186        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
187            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
188            mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
189        }
190        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
191            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
192            mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
193        }
194    }
195    return true;
196}
197
198Return<bool> Gnss::start()  {
199    ENTRY_LOG_CALLFLOW();
200    bool retVal = false;
201    GnssAPIClient* api = getApi();
202    if (api) {
203        retVal = api->gnssStart();
204    }
205    return retVal;
206}
207
208Return<bool> Gnss::stop()  {
209    ENTRY_LOG_CALLFLOW();
210    bool retVal = false;
211    GnssAPIClient* api = getApi();
212    if (api) {
213        retVal = api->gnssStop();
214    }
215    return retVal;
216}
217
218Return<void> Gnss::cleanup()  {
219    ENTRY_LOG_CALLFLOW();
220
221    if (mApi != nullptr) {
222        mApi->locAPIDisable();
223    }
224
225    return Void();
226}
227
228Return<bool> Gnss::injectLocation(double latitudeDegrees,
229                                  double longitudeDegrees,
230                                  float accuracyMeters)  {
231    ENTRY_LOG_CALLFLOW();
232    GnssInterface* gnssInterface = getGnssInterface();
233    if (nullptr != gnssInterface) {
234        gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
235        return true;
236    } else {
237        return false;
238    }
239}
240
241Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
242                              int32_t uncertaintyMs) {
243    ENTRY_LOG_CALLFLOW();
244    GnssInterface* gnssInterface = getGnssInterface();
245    if (nullptr != gnssInterface) {
246        gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs);
247        return true;
248    } else {
249        return false;
250    }
251}
252
253Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags)  {
254    ENTRY_LOG_CALLFLOW();
255    GnssAPIClient* api = getApi();
256    if (api) {
257        api->gnssDeleteAidingData(aidingDataFlags);
258    }
259    return Void();
260}
261
262Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
263                                   IGnss::GnssPositionRecurrence recurrence,
264                                   uint32_t minIntervalMs,
265                                   uint32_t preferredAccuracyMeters,
266                                   uint32_t preferredTimeMs)  {
267    ENTRY_LOG_CALLFLOW();
268    bool retVal = false;
269    GnssAPIClient* api = getApi();
270    if (api) {
271        retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
272                preferredAccuracyMeters, preferredTimeMs);
273    }
274    return retVal;
275}
276
277Return<sp<IAGnss>> Gnss::getExtensionAGnss()  {
278    ENTRY_LOG_CALLFLOW();
279    mAGnssIface = new AGnss(this);
280    return mAGnssIface;
281}
282
283Return<sp<IGnssNi>> Gnss::getExtensionGnssNi()  {
284    ENTRY_LOG_CALLFLOW();
285    mGnssNi = new GnssNi(this);
286    return mGnssNi;
287}
288
289Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
290    ENTRY_LOG_CALLFLOW();
291    mGnssMeasurement = new GnssMeasurement();
292    return mGnssMeasurement;
293}
294
295Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration()  {
296    ENTRY_LOG_CALLFLOW();
297    mGnssConfig = new GnssConfiguration(this);
298    return mGnssConfig;
299}
300
301Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing()  {
302    ENTRY_LOG_CALLFLOW();
303    mGnssGeofencingIface = new GnssGeofencing();
304    return mGnssGeofencingIface;
305}
306
307Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching()  {
308    mGnssBatching = new GnssBatching();
309    return mGnssBatching;
310}
311
312IGnss* HIDL_FETCH_IGnss(const char* hal) {
313    ENTRY_LOG_CALLFLOW();
314    IGnss* iface = nullptr;
315    iface = new Gnss();
316    if (iface == nullptr) {
317        LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
318    }
319    return iface;
320}
321
322}  // namespace implementation
323}  // namespace V1_0
324}  // namespace gnss
325}  // namespace hardware
326}  // namespace android
327