File indexing completed on 2024-11-17 04:18:46

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "connector_p.h"
0007 #include "logging.h"
0008 
0009 #include <QCoreApplication>
0010 using QAndroidJniObject = QJniObject;
0011 
0012 using namespace KUnifiedPush;
0013 
0014 static QString fromJniString(JNIEnv *env, jstring s)
0015 {
0016     if (!s) {
0017         return {};
0018     }
0019 
0020     const char *str = env->GetStringUTFChars(s, nullptr);
0021     const auto qs = QString::fromUtf8(str);
0022     env->ReleaseStringUTFChars(s, str);
0023     return qs;
0024 }
0025 
0026 static void newEndpoint(JNIEnv *env, jobject that, jstring token, jstring endpoint)
0027 {
0028     Q_UNUSED(that);
0029     for (auto c : ConnectorPrivate::s_instances) {
0030         c->NewEndpoint(fromJniString(env, token), fromJniString(env, endpoint));
0031     }
0032 }
0033 
0034 static void registrationFailed(JNIEnv *env, jobject that, jstring token, jstring reason)
0035 {
0036     Q_UNUSED(that);
0037     // TODO
0038     qDebug() << "TODO" << fromJniString(env, token) << fromJniString(env, reason);
0039 }
0040 
0041 static void unregistered(JNIEnv *env, jobject that, jstring token)
0042 {
0043     Q_UNUSED(that);
0044     for (auto c : ConnectorPrivate::s_instances) {
0045         c->Unregistered(fromJniString(env, token));
0046     }
0047 }
0048 
0049 static void message(JNIEnv *env, jobject that, jstring token, jbyteArray message, jstring messageId)
0050 {
0051     Q_UNUSED(that);
0052     const auto messageSize = env->GetArrayLength(message);
0053     const auto messageData = env->GetByteArrayElements(message, nullptr);
0054     const auto messageQBA = QByteArray::fromRawData(reinterpret_cast<const char*>(messageData), messageSize);
0055     for (auto c : ConnectorPrivate::s_instances) {
0056         c->Message(fromJniString(env, token), messageQBA, fromJniString(env, messageId));
0057     }
0058     env->ReleaseByteArrayElements(message, messageData, JNI_ABORT);
0059 }
0060 
0061 static const JNINativeMethod methods[] = {
0062     {"newEndpoint", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)newEndpoint},
0063     {"registrationFailed", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)registrationFailed},
0064     {"unregistered", "(Ljava/lang/String;)V", (void*)unregistered},
0065     {"message", "(Ljava/lang/String;[BLjava/lang/String;)V", (void*)message},
0066 };
0067 
0068 Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void*)
0069 {
0070     static bool initialized = false;
0071     if (initialized) {
0072         return JNI_VERSION_1_4;
0073     }
0074     initialized = true;
0075 
0076     JNIEnv *env = nullptr;
0077     if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
0078         qCWarning(Log) << "Failed to get JNI environment.";
0079         return -1;
0080     }
0081     jclass cls = env->FindClass("org/kde/kunifiedpush/MessageReceiver");
0082     if (env->RegisterNatives(cls, methods, sizeof(methods) / sizeof(JNINativeMethod)) < 0) {
0083         qCWarning(Log) << "Failed to register native functions.";
0084         return -1;
0085     }
0086 
0087     return JNI_VERSION_1_4;
0088 }
0089 
0090 std::vector<ConnectorPrivate*> ConnectorPrivate::s_instances;
0091 
0092 void ConnectorPrivate::init()
0093 {
0094     s_instances.push_back(this);
0095 }
0096 
0097 void ConnectorPrivate::deinit()
0098 {
0099     s_instances.erase(std::remove(s_instances.begin(), s_instances.end(), this), s_instances.end());
0100 }
0101 
0102 void ConnectorPrivate::doSetDistributor(const QString &distServiceName)
0103 {
0104     QJniObject context = QNativeInterface::QAndroidApplication::context();
0105     m_distributor = QAndroidJniObject("org.kde.kunifiedpush.Distributor", "(Ljava/lang/String;Landroid/content/Context;)V", QAndroidJniObject::fromString(distServiceName).object(), context.object());
0106 }
0107 
0108 bool ConnectorPrivate::hasDistributor() const
0109 {
0110     return m_distributor.isValid();
0111 }
0112 
0113 void ConnectorPrivate::doRegister()
0114 {
0115     m_distributor.callMethod<void>("register", "(Ljava/lang/String;Ljava/lang/String;)V", QAndroidJniObject::fromString(m_token).object(), QAndroidJniObject::fromString(m_description).object());
0116 }
0117 
0118 void ConnectorPrivate::doUnregister()
0119 {
0120     m_distributor.callMethod<void>("unregister", "(Ljava/lang/String;)V", QAndroidJniObject::fromString(m_token).object());
0121 }