blob: 51cba033b887ded4df5fff071b7758886d23c93a [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.
*/
#include "chre/platform/shared/nanoapp_support_lib_dso.h"
#include <chre.h>
#include "chre/platform/shared/debug_dump.h"
#include "chre/util/macros.h"
/**
* @file
* The Nanoapp Support Library (NSL) that gets built with nanoapps to act as an
* intermediary to the reference CHRE implementation. It provides hooks so the
* app can be registered with the system, and also provides a layer where we can
* implement cross-version compatibility features as needed.
*/
namespace {
#ifdef CHRE_SLPI_UIMG_ENABLED
constexpr int kIsTcmNanoapp = 1;
#else
constexpr int kIsTcmNanoapp = 0;
#endif // CHRE_SLPI_UIMG_ENABLED
#ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
// Return a v1.3+ GnssLocationEvent for the nanoapp when running on a v1.2-
// platform.
chreGnssLocationEvent translateLegacyGnssLocation(
const chreGnssLocationEvent &legacyEvent) {
// Copy v1.2- fields over to a v1.3+ event.
chreGnssLocationEvent newEvent = {};
newEvent.timestamp = legacyEvent.timestamp;
newEvent.latitude_deg_e7 = legacyEvent.latitude_deg_e7;
newEvent.longitude_deg_e7 = legacyEvent.longitude_deg_e7;
newEvent.altitude = legacyEvent.altitude;
newEvent.speed = legacyEvent.speed;
newEvent.bearing = legacyEvent.bearing;
newEvent.accuracy = legacyEvent.accuracy;
newEvent.flags = legacyEvent.flags;
// Unset flags that are defined in v1.3+ but not in v1.2-.
newEvent.flags &= ~(CHRE_GPS_LOCATION_HAS_ALTITUDE_ACCURACY |
CHRE_GPS_LOCATION_HAS_SPEED_ACCURACY |
CHRE_GPS_LOCATION_HAS_BEARING_ACCURACY);
return newEvent;
}
void nanoappHandleEventCompat(uint32_t senderInstanceId, uint16_t eventType,
const void *eventData) {
if (eventType == CHRE_EVENT_GNSS_LOCATION &&
chreGetApiVersion() < CHRE_API_VERSION_1_3) {
chreGnssLocationEvent event = translateLegacyGnssLocation(
*static_cast<const chreGnssLocationEvent *>(eventData));
nanoappHandleEvent(senderInstanceId, eventType, &event);
} else {
nanoappHandleEvent(senderInstanceId, eventType, eventData);
}
}
#endif
} // anonymous namespace
DLL_EXPORT extern "C" const struct chreNslNanoappInfo _chreNslDsoNanoappInfo = {
/* magic */ CHRE_NSL_NANOAPP_INFO_MAGIC,
/* structMinorVersion */ CHRE_NSL_NANOAPP_INFO_STRUCT_MINOR_VERSION,
/* isSystemNanoapp */ NANOAPP_IS_SYSTEM_NANOAPP,
/* isTcmNanoapp */ kIsTcmNanoapp,
/* reservedFlags */ 0,
/* reserved */ 0,
/* targetApiVersion */ CHRE_API_VERSION,
// These values are supplied by the build environment.
/* vendor */ NANOAPP_VENDOR_STRING,
/* name */ NANOAPP_NAME_STRING,
/* appId */ NANOAPP_ID,
/* appVersion */ NANOAPP_VERSION,
/* entryPoints */
{
/* start */ nanoappStart,
#ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
/* handleEvent */ nanoappHandleEventCompat,
#else
/* handleEvent */ nanoappHandleEvent,
#endif
/* end */ nanoappEnd,
},
/* appVersionString */ NANOAPP_VERSION_STRING,
};
// The code section below provides default implementations for new symbols
// introduced in CHRE API v1.2+ to provide binary compatibility with previous
// CHRE implementations. Note that we don't presently include symbols for v1.1,
// as the current known set of CHRE platforms that use this NSL implementation
// are all v1.1+.
// If a nanoapp knows that it is only targeting the latest platform version, it
// can define the CHRE_NANOAPP_DISABLE_BACKCOMPAT flag, so this indirection will
// be avoided at the expense of a nanoapp not being able to load at all on prior
// implementations.
#ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
#include <dlfcn.h>
/**
* Lazily calls dlsym to find the function pointer for a given function
* (provided without quotes) in another library (i.e. the CHRE platform DSO),
* caching and returning the result.
*/
#define CHRE_NSL_LAZY_LOOKUP(functionName) \
({ \
static bool lookupPerformed = false; \
static decltype(functionName) *fptr = nullptr; \
if (!lookupPerformed) { \
fptr = reinterpret_cast<decltype(fptr)>( \
dlsym(RTLD_NEXT, STRINGIFY(functionName))); \
lookupPerformed = true; \
} \
fptr; \
})
WEAK_SYMBOL
bool chreAudioGetSource(uint32_t handle, struct chreAudioSource *audioSource) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetSource);
return (fptr != nullptr) ? fptr(handle, audioSource) : false;
}
WEAK_SYMBOL
bool chreAudioConfigureSource(uint32_t handle, bool enable,
uint64_t bufferDuration,
uint64_t deliveryInterval) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioConfigureSource);
return (fptr != nullptr)
? fptr(handle, enable, bufferDuration, deliveryInterval)
: false;
}
WEAK_SYMBOL
bool chreAudioGetStatus(uint32_t handle, struct chreAudioSourceStatus *status) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetStatus);
return (fptr != nullptr) ? fptr(handle, status) : false;
}
WEAK_SYMBOL
void chreConfigureHostSleepStateEvents(bool enable) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureHostSleepStateEvents);
if (fptr != nullptr) {
fptr(enable);
}
}
WEAK_SYMBOL
bool chreIsHostAwake(void) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreIsHostAwake);
return (fptr != nullptr) ? fptr() : false;
}
WEAK_SYMBOL
bool chreGnssConfigureLocationMonitor(bool enable) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGnssConfigureLocationMonitor);
return (fptr != nullptr) ? fptr(enable) : false;
}
WEAK_SYMBOL
bool chreWifiRequestRangingAsync(const struct chreWifiRangingParams *params,
const void *cookie) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiRequestRangingAsync);
return (fptr != nullptr) ? fptr(params, cookie) : false;
}
WEAK_SYMBOL
bool chreSensorConfigureBiasEvents(uint32_t sensorHandle, bool enable) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorConfigureBiasEvents);
return (fptr != nullptr) ? fptr(sensorHandle, enable) : false;
}
WEAK_SYMBOL
bool chreSensorGetThreeAxisBias(uint32_t sensorHandle,
struct chreSensorThreeAxisData *bias) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorGetThreeAxisBias);
return (fptr != nullptr) ? fptr(sensorHandle, bias) : false;
}
WEAK_SYMBOL
bool chreSensorFlushAsync(uint32_t sensorHandle, const void *cookie) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorFlushAsync);
return (fptr != nullptr) ? fptr(sensorHandle, cookie) : false;
}
WEAK_SYMBOL
void chreConfigureDebugDumpEvent(bool enable) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureDebugDumpEvent);
if (fptr != nullptr) {
fptr(enable);
}
}
WEAK_SYMBOL
void chreDebugDumpLog(const char *formatStr, ...) {
auto *fptr = CHRE_NSL_LAZY_LOOKUP(platform_chreDebugDumpVaLog);
if (fptr != nullptr) {
va_list args;
va_start(args, formatStr);
fptr(formatStr, args);
va_end(args);
}
}
#endif // CHRE_NANOAPP_DISABLE_BACKCOMPAT