From 8ba846f7fab5c56c1a9380cf700ba3682c1041b0 Mon Sep 17 00:00:00 2001 From: Ziyan Date: Thu, 31 Dec 2015 18:41:54 +0100 Subject: espresso-common: Add libgpsd-compat Credits to: Dmitry Grinberg . I just renamed it to libgpsd-compat because libdmitry doesn't make sense, and cleaned it up a little. Change-Id: Ib01e7aa0ecbe1b50a7810e613009e8424bce4c56 --- espresso-common.mk | 3 + libgpsd-compat/Android.mk | 25 ++++++ libgpsd-compat/libgpsd-compat.c | 164 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 libgpsd-compat/Android.mk create mode 100644 libgpsd-compat/libgpsd-compat.c diff --git a/espresso-common.mk b/espresso-common.mk index edbf19d..2c83234 100644 --- a/espresso-common.mk +++ b/espresso-common.mk @@ -47,6 +47,9 @@ PRODUCT_PACKAGES += \ init.recovery.espresso.rc # GPS +PRODUCT_PACKAGES += \ + libgpsd-compat + PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/configs/gps.xml:system/etc/gps.xml diff --git a/libgpsd-compat/Android.mk b/libgpsd-compat/Android.mk new file mode 100644 index 0000000..f1ce946 --- /dev/null +++ b/libgpsd-compat/Android.mk @@ -0,0 +1,25 @@ +# Copyright (C) 2015 The Android Open Source Project +# Written by Dmitry Grinberg +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SHARED_LIBRARIES := liblog libhardware_legacy libgui libbinder libutils +LOCAL_SRC_FILES := libgpsd-compat.c +LOCAL_MODULE := libgpsd-compat +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/libgpsd-compat/libgpsd-compat.c b/libgpsd-compat/libgpsd-compat.c new file mode 100644 index 0000000..6bd1a49 --- /dev/null +++ b/libgpsd-compat/libgpsd-compat.c @@ -0,0 +1,164 @@ +#define LOG_TAG "libgpsd-compat" +#include +#include +#include +#include +#include +#include +#include + +/* + * Problems: + * 1. Nexus 10's GPS library was made to work with android L + * 2. Android M changed a few things around that make it not work + * a. Sensor manager API changed in a few places + * b. BoringSSL replaced OpenSSL + * 3. Due to these now-missing unresolved symbols GPS library will not load or run + * + * A tricky but clever solution: INTERPOSITION library + * 1. We'll edit the GPS library and replace one of its "NEED" record with one referencing a new library + * which we'll create. + * 2. Make sure that libgpsd-compat's NEED records include the library whose record we replaced in the GPS + * library, to make sure that the linker brings it in afterall and all symbols in it are found + * 3. Implement libgpsd-compat such that it provides the missing things and does them in such a way that the + * GPS library is happy. + * + * Result: GPS library works on M, with the help of libgpsd-compat and a small binary patch to the GPS + * library itself (replacing one of the "NEED" records with a NEED record for "libgpsd-compat") + */ + + +//various funcs we'll need to call, in their mangled form + + //android::String8::String8(char const*) + extern void _ZN7android7String8C1EPKc(void **str8P, const char *str); + + //android::String8::~String8() + extern void _ZN7android7String8D1Ev(void **str8P); + + //android::String16::String16(char const*) + extern void _ZN7android8String16C1EPKc(void **str16P, const char *str); + + //android::String16::~String16() + extern void _ZN7android8String16D1Ev(void **str16P); + + //android::SensorManager::~SensorManager() + extern void _ZN7android13SensorManagerD1Ev(void *sensorMgr); + + //android::SensorManager::SensorManager(android::String16 const&) + extern void _ZN7android13SensorManagerC1ERKNS_8String16E(void *sensorMgr, void **str16P); + + //android::SensorManager::createEventQueue(android::String8, int) + extern void _ZN7android13SensorManager16createEventQueueENS_7String8Ei(void **retVal, void *sensorMgr, void **str8P, int mode); + + +//data exports we must provide for gps library to be happy + + /* + * DATA: android::Singleton::sLock + * USE: INTERPOSE: a mutes that GPS lib will insist on accessing + * NOTES: In L, the sensor manager exposed this lock that callers + * actually locked & unlocked when accessing it. In M this + * is no longer the case, but we still must provide it for + * the GPS library to be happy. It will lock nothnhing, but + * as long as it is a real lock and pthread_mutex_* funcs + * work on it, the GPS library will be happy. + */ + pthread_mutex_t _ZN7android9SingletonINS_13SensorManagerEE5sLockE = PTHREAD_MUTEX_INITIALIZER; + + /* + * DATA: android::Singleton::sInstance + * USE: INTERPOSE: a singleton instance of SensorManager + * NOTES: In L, the sensor manager exposed this variable, as it was + * a singleton and one could just access this directly to get + * the current already-existing instance if it happened to + * already exist. If not one would create one and store it + * there. In M this is entirely different, but the GPS library + * does not know that. So we'll init it to NULL to signify that + * no current instance exists, let it create one, and store it + * here, and upon unloading we'll clean it up, if it is not + * NULL (which is what it would be if the GPS library itself + * did the cleanup). + */ + void* _ZN7android9SingletonINS_13SensorManagerEE9sInstanceE = NULL; + + +//code exports we provide + + //android::SensorManager::SensorManager(void) + void _ZN7android13SensorManagerC1Ev(void *sensorMgr); + + //android::SensorManager::createEventQueue(void) + void _ZN7android13SensorManager16createEventQueueEv(void **retVal, void *sensorMgr); + + //this used to exist in OpenSLL, but does not in BoringSSL - for some reason GPS library uses it anyways + void *CRYPTO_malloc(uint32_t sz, const char *file, uint32_t line); + + +//library on-load and on-unload handlers (to help us set things up and tear them down) + void libEvtUnloading(void) __attribute__((destructor)); + + +/* + * FUNCTION: android::SensorManager::SensorManager(void) + * USE: INTERPOSE: construct a sensor manager object + * NOTES: This constructor no longer exists in M, instead now one must pass + * in a package name as a "string16" to the consrtuctor. Since this + * lib only services GPS library, it is easy for us to just do that + * and this provide the constructor that the GPS library wants. + * The package name we use if "gps.manta". Why not? + */ +void _ZN7android13SensorManagerC1Ev(void *sensorMgr) +{ + void *string; + + _ZN7android8String16C1EPKc(&string, "gps.manta"); + _ZN7android13SensorManagerC1ERKNS_8String16E(sensorMgr, &string); + _ZN7android8String16D1Ev(&string); +} + +/* + * FUNCTION: android::SensorManager::createEventQueue(void) + * USE: INTERPOSE: create an event queue to receive events + * NOTES: This function no longer exists in M, instead now one must pass + * in a client name as a "string8" and an integer "mode"to it. M + * sources list default values for these params as an empty string + * and 0. So we'll craft the same call here. + */ +void _ZN7android13SensorManager16createEventQueueEv(void **retVal, void *sensorMgr) +{ + void *string; + + _ZN7android7String8C1EPKc(&string, ""); + _ZN7android13SensorManager16createEventQueueENS_7String8Ei(retVal, sensorMgr, &string, 0); + _ZN7android7String8D1Ev(&string); +} + +/* + * FUNCTION: CRYPTO_malloc(uint32_t sz, const char *file, uint32_t line) + * USE: INTERPOSE: Allocate memory + * NOTES: In OpenSSL, this just allocates memory and optionally tracks it. + * Why manta's GPS library chose to use it is a mystery, but to make + * it happy we must provide it, so we do, backing the allocation with + * a calloc()-ed memory chunk. + */ +void *CRYPTO_malloc(uint32_t sz, const char *file, uint32_t line) +{ + (void)file; + (void)line; + return calloc(sz, 1); +} + +/* + * FUNCTION: libEvtUnloading() + * USE: Handle library unloading + * NOTES: This is a good time to free whatever is unfreed and say goodbye + */ +void libEvtUnloading(void) +{ + if (_ZN7android9SingletonINS_13SensorManagerEE9sInstanceE) { + //if an instance stil exists, free it by calling the destructor, just to be throrough + _ZN7android13SensorManagerD1Ev(_ZN7android9SingletonINS_13SensorManagerEE9sInstanceE); + _ZN7android9SingletonINS_13SensorManagerEE9sInstanceE = NULL; + } +} -- cgit v1.1