File indexing completed on 2024-12-01 07:25:49

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "wifimonitor_p.h"
0007 #include "logging.h"
0008 
0009 #include <QSharedData>
0010 
0011 #include <private/qandroidextras_p.h>
0012 #include <QCoreApplication>
0013 #include <QJniEnvironment>
0014 #include <QJniObject>
0015 
0016 using namespace KPublicTransport;
0017 
0018 namespace KPublicTransport {
0019 class WifiMonitorBackend : public QSharedData
0020 {
0021 public:
0022     void setSsid(const QString &ssid);
0023     void setStatus(int statusCode);
0024 
0025     std::vector<WifiMonitor*> frontends;
0026     WifiMonitor::Status status = WifiMonitor::NotAvailable;
0027     QJniObject wifiMonitor;
0028 };
0029 }
0030 
0031 void WifiMonitorBackend::setSsid(const QString &ssid)
0032 {
0033     for (auto m : frontends) {
0034         m->setSsid(ssid);
0035     }
0036 }
0037 
0038 void WifiMonitorBackend::setStatus(int statusCode)
0039 {
0040     if (status == statusCode) {
0041         return;
0042     }
0043     status = static_cast<WifiMonitor::Status>(statusCode);
0044     for (auto m : frontends) {
0045         Q_EMIT m->statusChanged();
0046     }
0047 }
0048 
0049 static WifiMonitorBackend *s_backend = nullptr;
0050 
0051 static void setSsid(JNIEnv *env, [[maybe_unused]] jobject that, jstring ssid)
0052 {
0053     if (s_backend) {
0054         const char *str = env->GetStringUTFChars(ssid, nullptr);
0055         s_backend->setSsid(QString::fromUtf8(str));
0056         env->ReleaseStringUTFChars(ssid, str);
0057     }
0058 }
0059 
0060 static void setStatus([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jobject that, jint statusCode)
0061 {
0062     if (s_backend) {
0063         s_backend->setStatus(statusCode);
0064     }
0065 }
0066 
0067 static const JNINativeMethod methods[] = {
0068     {"setSsid", "(Ljava/lang/String;)V", (void *)setSsid},
0069     {"setStatus", "(I)V", (void *)setStatus},
0070 };
0071 
0072 WifiMonitor::WifiMonitor(QObject *parent)
0073     : QObject(parent)
0074 {
0075     static bool nativesRegistered = false;
0076     if (!nativesRegistered) {
0077         QJniEnvironment env;
0078         jclass cls = env->FindClass("org/kde/publictransport/onboard/WifiMonitor");
0079         if (env->RegisterNatives(cls, methods, sizeof(methods) / sizeof(JNINativeMethod)) < 0) {
0080             qCWarning(Log) << "Failed to register native functions!";
0081         }
0082         nativesRegistered = true;
0083     }
0084 
0085     if (!s_backend) {
0086         s_backend = new WifiMonitorBackend;
0087         s_backend->wifiMonitor = QJniObject("org/kde/publictransport/onboard/WifiMonitor", "(Landroid/content/Context;)V", QNativeInterface::QAndroidApplication::context());
0088     }
0089 
0090     s_backend->ref.ref();
0091     s_backend->frontends.push_back(this);
0092 }
0093 
0094 WifiMonitor::~WifiMonitor()
0095 {
0096     s_backend->ref.deref();
0097     if (!s_backend->ref) {
0098         delete s_backend;
0099         s_backend = nullptr;
0100     } else {
0101         auto it = std::find(s_backend->frontends.begin(), s_backend->frontends.end(), this);
0102         if (it != s_backend->frontends.end()) {
0103             s_backend->frontends.erase(it);
0104         }
0105     }
0106 }
0107 
0108 WifiMonitor::Status WifiMonitor::status() const
0109 {
0110     return s_backend->status;
0111 }
0112 
0113 void WifiMonitor::requestPermissions()
0114 {
0115     // TODO make this properly async
0116     QtAndroidPrivate::requestPermission(QStringLiteral("android.permission.ACCESS_FINE_LOCATION"));
0117     s_backend->wifiMonitor.callMethod<void>("checkStatus", "()V");
0118 }