// Copyright (C) 2021 The Qt Company Ltd. // Copyright (C) 2019 BogDan Vatra // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "sensormanager.h" #include #include Q_DECLARE_JNI_CLASS(AndroidContext, "android/content/Context") Q_DECLARE_JNI_TYPE(Sensor, "Landroid/hardware/Sensor;") SensorManager::SensorManager() { auto sensorService = QJniObject::getStaticField("SENSOR_SERVICE"); QJniObject context = QNativeInterface::QAndroidApplication::context(); m_sensorManager = context.callMethod("getSystemService", sensorService.object()); setObjectName("QtSensorsLooperThread"); start(); m_waitForStart.acquire(); } SensorManager::~SensorManager() { m_quit.storeRelaxed(1); wait(); } QJniObject SensorManager::javaSensor(const ASensor *sensor) const { return m_sensorManager.callMethod("getDefaultSensor", ASensor_getType(sensor)); } QSharedPointer &SensorManager::instance() { static QSharedPointer looper{new SensorManager}; return looper; } ALooper *SensorManager::looper() const { return m_looper; } static inline ASensorManager* androidManager() { QJniObject context = QNativeInterface::QAndroidApplication::context(); auto packageName = context.callMethod("getPackageName").toString().toUtf8(); #if __ANDROID_API__ >= 26 return ASensorManager_getInstanceForPackage(packageName.constData()); #else if (QNativeInterface::QAndroidApplication::sdkVersion() >= 26) { using GetInstanceForPackage = ASensorManager *(*)(const char *); auto handler = dlopen("libandroid.so", RTLD_NOW); auto function = GetInstanceForPackage(dlsym(handler, "ASensorManager_getInstanceForPackage")); if (function) { auto res = function(packageName.constData()); dlclose(handler); return res; } dlclose(handler); } return ASensorManager_getInstance(); #endif } ASensorManager *SensorManager::manager() const { static auto sensorManger = androidManager(); return sensorManger; } QString SensorManager::description(const ASensor *sensor) const { return QString::fromUtf8(ASensor_getName(sensor)) + " " + ASensor_getVendor(sensor) + " v" + QString::number(javaSensor(sensor).callMethod("getVersion")); } double SensorManager::getMaximumRange(const ASensor *sensor) const { return qreal(javaSensor(sensor).callMethod("getMaximumRange")); } void SensorManager::run() { m_looper = ALooper_prepare(0); m_waitForStart.release(); do { if (ALooper_pollAll(5 /*ms*/, nullptr, nullptr, nullptr) == ALOOPER_POLL_TIMEOUT) QThread::yieldCurrentThread(); } while (!m_quit.loadRelaxed()); }