Files
DefaultVPN/client/platforms/android/android_controller.cpp

561 lines
18 KiB
C++
Raw Normal View History

#include <QJniEnvironment>
2021-11-26 17:43:02 +03:00
#include <QJsonDocument>
#include <QQmlFile>
2023-12-26 17:00:06 +03:00
#include <QEventLoop>
#include <QImage>
#include <android/bitmap.h>
2021-11-26 17:43:02 +03:00
#include "android_controller.h"
2023-12-26 17:00:06 +03:00
#include "android_utils.h"
2023-11-21 22:48:52 +03:00
#include "ui/controllers/importController.h"
2021-11-26 17:43:02 +03:00
namespace
{
AndroidController *s_instance = nullptr;
2021-11-26 17:43:02 +03:00
constexpr auto QT_ANDROID_CONTROLLER_CLASS = "org/amnezia/vpn/qt/QtAndroidController";
constexpr auto ANDROID_LOG_CLASS = "org/amnezia/vpn/util/Log";
constexpr auto TAG = "AmneziaQt";
} // namespace
2021-11-26 17:43:02 +03:00
AndroidController::AndroidController() : QObject()
2021-11-26 17:43:02 +03:00
{
connect(this, &AndroidController::status, this,
[this](AndroidController::ConnectionState state) {
qDebug() << "Android event: status =" << textConnectionState(state);
2023-11-23 20:30:03 +03:00
if (isWaitingStatus) {
2023-12-06 15:36:26 +03:00
qDebug() << "Initialization by service status";
2023-11-23 20:30:03 +03:00
isWaitingStatus = false;
2023-12-06 15:36:26 +03:00
emit initConnectionState(convertState(state));
}
},
Qt::QueuedConnection);
connect(
this, &AndroidController::serviceDisconnected, this,
[this]() {
qDebug() << "Android event: service disconnected";
2023-11-23 20:30:03 +03:00
isWaitingStatus = true;
emit connectionStateChanged(Vpn::ConnectionState::Disconnected);
},
Qt::QueuedConnection);
connect(
this, &AndroidController::serviceError, this,
[this]() {
qDebug() << "Android event: service error";
// todo: add error message
emit connectionStateChanged(Vpn::ConnectionState::Error);
},
Qt::QueuedConnection);
connect(
this, &AndroidController::vpnPermissionRejected, this,
[this]() {
qWarning() << "Android event: VPN permission rejected";
emit connectionStateChanged(Vpn::ConnectionState::Disconnected);
},
Qt::QueuedConnection);
connect(
this, &AndroidController::vpnStateChanged, this,
[this](AndroidController::ConnectionState state) {
qDebug() << "Android event: VPN state changed:" << textConnectionState(state);
emit connectionStateChanged(convertState(state));
},
Qt::QueuedConnection);
connect(
this, &AndroidController::configImported, this,
[this](const QString& config) {
qDebug() << "Android event: config import";
emit importConfigFromOutside(config);
},
Qt::QueuedConnection);
2021-11-26 17:43:02 +03:00
}
AndroidController *AndroidController::instance()
{
if (!s_instance) {
s_instance = new AndroidController();
}
2021-11-26 17:43:02 +03:00
return s_instance;
}
bool AndroidController::initialize()
2021-11-26 17:43:02 +03:00
{
qDebug() << "Initialize AndroidController";
2021-11-26 17:43:02 +03:00
const JNINativeMethod methods[] = {
{"onStatus", "(I)V", reinterpret_cast<void *>(onStatus)},
{"onServiceDisconnected", "()V", reinterpret_cast<void *>(onServiceDisconnected)},
{"onServiceError", "()V", reinterpret_cast<void *>(onServiceError)},
{"onVpnPermissionRejected", "()V", reinterpret_cast<void *>(onVpnPermissionRejected)},
{"onNotificationStateChanged", "()V", reinterpret_cast<void *>(onNotificationStateChanged)},
{"onVpnStateChanged", "(I)V", reinterpret_cast<void *>(onVpnStateChanged)},
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
{"onFileOpened", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onFileOpened)},
{"onConfigImported", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onConfigImported)},
{"onAuthResult", "(Z)V", reinterpret_cast<void *>(onAuthResult)},
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)},
{"onImeInsetsChanged", "(I)V", reinterpret_cast<void *>(onImeInsetsChanged)},
{"onSystemBarsInsetsChanged", "(II)V", reinterpret_cast<void *>(onSystemBarsInsetsChanged)}
};
2021-11-26 17:43:02 +03:00
QJniEnvironment env;
bool registered = env.registerNativeMethods(QT_ANDROID_CONTROLLER_CLASS, methods,
sizeof(methods) / sizeof(JNINativeMethod));
if (!registered) {
qCritical() << "Failed native method registration";
return false;
}
qtAndroidControllerInitialized();
return true;
2021-11-26 17:43:02 +03:00
}
// static
template <typename Ret, typename ...Args>
auto AndroidController::callActivityMethod(const char *methodName, const char *signature, Args &&...args)
2021-11-26 17:43:02 +03:00
{
qDebug() << "Call activity method:" << methodName;
2023-12-26 17:00:06 +03:00
QJniObject activity = AndroidUtils::getActivity();
Q_ASSERT(activity.isValid());
return activity.callMethod<Ret>(methodName, signature, std::forward<Args>(args)...);
}
2021-11-26 17:43:02 +03:00
// static
template <typename ...Args>
void AndroidController::callActivityMethod(const char *methodName, const char *signature, Args &&...args)
{
callActivityMethod<void>(methodName, signature, std::forward<Args>(args)...);
}
ErrorCode AndroidController::start(const QJsonObject &vpnConfig)
{
2023-11-23 20:30:03 +03:00
isWaitingStatus = false;
auto config = QJsonDocument(vpnConfig).toJson();
callActivityMethod("start", "(Ljava/lang/String;)V",
QJniObject::fromString(config).object<jstring>());
2021-11-26 17:43:02 +03:00
2024-05-25 13:00:51 +03:00
return ErrorCode::NoError;
2021-11-26 17:43:02 +03:00
}
void AndroidController::stop()
{
callActivityMethod("stop", "()V");
2021-11-26 17:43:02 +03:00
}
void AndroidController::resetLastServer(int serverIndex)
{
callActivityMethod("resetLastServer", "(I)V", serverIndex);
}
void AndroidController::saveFile(const QString &fileName, const QString &data)
{
callActivityMethod("saveFile", "(Ljava/lang/String;Ljava/lang/String;)V",
QJniObject::fromString(fileName).object<jstring>(),
QJniObject::fromString(data).object<jstring>());
2021-11-26 17:43:02 +03:00
}
QString AndroidController::openFile(const QString &filter)
{
QEventLoop wait;
QString fileName;
connect(this, &AndroidController::fileOpened, this,
[&fileName, &wait](const QString &uri) {
Improve navigation cpp (#1061) * add focusController class * add more key handlers * add focus navigation to qml * fixed language selector * add reverse focus change to FocusController * add default focus item * update transitions * update pages * add ListViewFocusController * fix ListView navigation * update CardType for using with focus navigation * remove useless key navigation * remove useless slots, logs, Drawer open and close * fix reverse focus move on listView * fix drawer radio buttons selection * fix drawer layout and focus move * fix PageSetupWizardProtocolSettings focus move * fix back navigation on default focus item * fix crashes after ListView navigation * fix protocol settings focus move * fix focus on users on page share * clean up page share * fix server rename * fix page share default server selection * refactor about page for correct focus move * fix focus move on list views with header and-or footer * minor fixes * fix server list back button handler * fix spawn signals on switch * fix share details drawer * fix drawer open close usage * refactor listViewFocusController * refactor focusController to make the logic more straightforward * fix focus on notification * update config page for scrolling with tab * fix crash on return with esc key * fix focus navigation in dynamic delegate of list view * fix focus move on qr code on share page * refactor page logging settings for focus navigation * update popup * Bump version * Add mandatory requirement for android.software.leanback. * Fix importing files on TVs * fix: add separate method for reading files to fix file reading on Android TV * fix(android): add CHANGE_NETWORK_STATE permission for all Android versions * Fix connection check for AWG/WG * chore: minor fixes (#1235) * fix: add a workaround to open files on Android TV due to lack of SAF * fix: change the banner format for TV * refactor: make TvFilePicker activity more sustainable * fix: add the touch emulation method for Android TV * fix: null uri processing * fix: add the touch emulation method for Android TV * fix: hide UI elements that use file saving * chore: bump version code * add `ScrollBarType` * update initial config page * refactor credentials setup page to handle the focus navigation * add `setDelegateIndex` method to `listViewFocusController` * fix focus behavior on new page/popup * make minor fixes and clean up * fix: get rid of the assign function call * Scrollbar is on if the content is larger than a screen * Fix selection in language change list * Update select language list * update logging settings page * fix checked item in lists * fix split tunneling settings * make unchangable properties readonly * refactor SwitcherType * fix hide/unhide password * `PageShare` readonly properties * Fix list view focus moving on `PageShare` * remove manual focus control on `PageShare` * format `ListViewFocusController` * format `FocusController` * add `focusControl` with utility functions for focus control * refactor `listViewFocusController` acoording to `focusControl` * refactor `focusConroller` according to `focusControl` * add `printSectionName` method to `listViewController` * remove arrow from `Close application` item * fix focus movement in `ServersListView` * `Restore from backup` is visible only on start screen * `I have nothing` is visible only on start screen * fix back button on `SelectLanguageDrawer` * rename `focusControl` to `qmlUtils` * fix `CMakeLists.txt` * fix `ScrollBarType` * fix `PageSetupWizardApiServicesList` * fix focus movement on dynamic delegates in listView * refactor `PageSetupWizardProtocols` * remove comments and clean up * fix `ListViewWithLabelsType` * fix `PageProtocolCloakSettings` * fix `PageSettingsAppSplitTunneling` * fix `PageDevMenu` * remove debug output from `FocusController` * remove debug output from `ListViewFocusController` * remove debug output from `focusControl` * `focusControl` => `FocusControl` --------- Co-authored-by: albexk <albexk@proton.me> Co-authored-by: Nethius <nethiuswork@gmail.com>
2024-12-31 04:16:52 +01:00
fileName = uri;
wait.quit();
},
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::SingleShotConnection));
callActivityMethod("openFile", "(Ljava/lang/String;)V",
QJniObject::fromString(filter).object<jstring>());
wait.exec();
return fileName;
}
Improve navigation cpp (#1061) * add focusController class * add more key handlers * add focus navigation to qml * fixed language selector * add reverse focus change to FocusController * add default focus item * update transitions * update pages * add ListViewFocusController * fix ListView navigation * update CardType for using with focus navigation * remove useless key navigation * remove useless slots, logs, Drawer open and close * fix reverse focus move on listView * fix drawer radio buttons selection * fix drawer layout and focus move * fix PageSetupWizardProtocolSettings focus move * fix back navigation on default focus item * fix crashes after ListView navigation * fix protocol settings focus move * fix focus on users on page share * clean up page share * fix server rename * fix page share default server selection * refactor about page for correct focus move * fix focus move on list views with header and-or footer * minor fixes * fix server list back button handler * fix spawn signals on switch * fix share details drawer * fix drawer open close usage * refactor listViewFocusController * refactor focusController to make the logic more straightforward * fix focus on notification * update config page for scrolling with tab * fix crash on return with esc key * fix focus navigation in dynamic delegate of list view * fix focus move on qr code on share page * refactor page logging settings for focus navigation * update popup * Bump version * Add mandatory requirement for android.software.leanback. * Fix importing files on TVs * fix: add separate method for reading files to fix file reading on Android TV * fix(android): add CHANGE_NETWORK_STATE permission for all Android versions * Fix connection check for AWG/WG * chore: minor fixes (#1235) * fix: add a workaround to open files on Android TV due to lack of SAF * fix: change the banner format for TV * refactor: make TvFilePicker activity more sustainable * fix: add the touch emulation method for Android TV * fix: null uri processing * fix: add the touch emulation method for Android TV * fix: hide UI elements that use file saving * chore: bump version code * add `ScrollBarType` * update initial config page * refactor credentials setup page to handle the focus navigation * add `setDelegateIndex` method to `listViewFocusController` * fix focus behavior on new page/popup * make minor fixes and clean up * fix: get rid of the assign function call * Scrollbar is on if the content is larger than a screen * Fix selection in language change list * Update select language list * update logging settings page * fix checked item in lists * fix split tunneling settings * make unchangable properties readonly * refactor SwitcherType * fix hide/unhide password * `PageShare` readonly properties * Fix list view focus moving on `PageShare` * remove manual focus control on `PageShare` * format `ListViewFocusController` * format `FocusController` * add `focusControl` with utility functions for focus control * refactor `listViewFocusController` acoording to `focusControl` * refactor `focusConroller` according to `focusControl` * add `printSectionName` method to `listViewController` * remove arrow from `Close application` item * fix focus movement in `ServersListView` * `Restore from backup` is visible only on start screen * `I have nothing` is visible only on start screen * fix back button on `SelectLanguageDrawer` * rename `focusControl` to `qmlUtils` * fix `CMakeLists.txt` * fix `ScrollBarType` * fix `PageSetupWizardApiServicesList` * fix focus movement on dynamic delegates in listView * refactor `PageSetupWizardProtocols` * remove comments and clean up * fix `ListViewWithLabelsType` * fix `PageProtocolCloakSettings` * fix `PageSettingsAppSplitTunneling` * fix `PageDevMenu` * remove debug output from `FocusController` * remove debug output from `ListViewFocusController` * remove debug output from `focusControl` * `focusControl` => `FocusControl` --------- Co-authored-by: albexk <albexk@proton.me> Co-authored-by: Nethius <nethiuswork@gmail.com>
2024-12-31 04:16:52 +01:00
int AndroidController::getFd(const QString &fileName)
{
return callActivityMethod<jint>("getFd", "(Ljava/lang/String;)I",
QJniObject::fromString(fileName).object<jstring>());
}
void AndroidController::closeFd()
{
callActivityMethod("closeFd", "()V");
}
QString AndroidController::getFileName(const QString &uri)
{
auto fileName = callActivityMethod<jstring, jstring>("getFileName", "(Ljava/lang/String;)Ljava/lang/String;",
QJniObject::fromString(uri).object<jstring>());
QJniEnvironment env;
return AndroidUtils::convertJString(env.jniEnv(), fileName.object<jstring>());
}
bool AndroidController::isCameraPresent()
{
return callActivityMethod<jboolean>("isCameraPresent", "()Z");
}
bool AndroidController::isOnTv()
{
return callActivityMethod<jboolean>("isOnTv", "()Z");
}
bool AndroidController::isEdgeToEdgeEnabled()
{
return callActivityMethod<jboolean>("isEdgeToEdgeEnabled", "()Z");
}
int AndroidController::getStatusBarHeight()
{
return callActivityMethod<jint>("getStatusBarHeight", "()I");
}
int AndroidController::getNavigationBarHeight()
{
return callActivityMethod<jint>("getNavigationBarHeight", "()I");
}
void AndroidController::startQrReaderActivity()
{
callActivityMethod("startQrCodeReader", "()V");
}
void AndroidController::setSaveLogs(bool enabled)
{
callActivityMethod("setSaveLogs", "(Z)V", enabled);
}
void AndroidController::exportLogsFile(const QString &fileName)
{
callActivityMethod("exportLogsFile", "(Ljava/lang/String;)V",
QJniObject::fromString(fileName).object<jstring>());
}
void AndroidController::clearLogs()
{
callActivityMethod("clearLogs", "()V");
}
void AndroidController::setScreenshotsEnabled(bool enabled)
{
callActivityMethod("setScreenshotsEnabled", "(Z)V", enabled);
}
void AndroidController::setNavigationBarColor(unsigned int color)
{
callActivityMethod("setNavigationBarColor", "(I)V", color);
}
void AndroidController::minimizeApp()
{
callActivityMethod("minimizeApp", "()V");
}
QJsonArray AndroidController::getAppList()
{
QJniObject appList = callActivityMethod<jstring>("getAppList", "()Ljava/lang/String;");
QJsonArray jsonAppList = QJsonDocument::fromJson(appList.toString().toUtf8()).array();
return jsonAppList;
}
QPixmap AndroidController::getAppIcon(const QString &package, QSize *size, const QSize &requestedSize)
{
QJniObject bitmap = callActivityMethod<jobject>("getAppIcon", "(Ljava/lang/String;II)Landroid/graphics/Bitmap;",
QJniObject::fromString(package).object<jstring>(),
requestedSize.width(), requestedSize.height());
QJniEnvironment env;
AndroidBitmapInfo info;
if (AndroidBitmap_getInfo(env.jniEnv(), bitmap.object(), &info) != ANDROID_BITMAP_RESULT_SUCCESS) return {};
void *pixels;
if (AndroidBitmap_lockPixels(env.jniEnv(), bitmap.object(), &pixels) != ANDROID_BITMAP_RESULT_SUCCESS) return {};
int width = info.width;
int height = info.height;
size->setWidth(width);
size->setHeight(height);
QImage image(width, height, QImage::Format_RGBA8888);
if (info.stride == uint32_t(image.bytesPerLine())) {
memcpy((void *) image.constBits(), pixels, info.stride * height);
} else {
auto *bmpPtr = static_cast<uchar *>(pixels);
for (int i = 0; i < height; i++, bmpPtr += info.stride)
memcpy((void *) image.constScanLine(i), bmpPtr, width);
}
if (AndroidBitmap_unlockPixels(env.jniEnv(), bitmap.object()) != ANDROID_BITMAP_RESULT_SUCCESS) return {};
return QPixmap::fromImage(image);
}
bool AndroidController::isNotificationPermissionGranted()
{
return callActivityMethod<jboolean>("isNotificationPermissionGranted", "()Z");
}
void AndroidController::requestNotificationPermission()
{
callActivityMethod("requestNotificationPermission", "()V");
}
bool AndroidController::requestAuthentication()
{
QEventLoop wait;
bool result;
connect(this, &AndroidController::authenticationResult, this,
[&result, &wait](const bool &authResult){
qDebug() << "Android authentication result:" << authResult;
result = authResult;
wait.quit();
},
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::SingleShotConnection));
callActivityMethod("requestAuthentication", "()V");
wait.exec();
return result;
}
Improve navigation cpp (#1061) * add focusController class * add more key handlers * add focus navigation to qml * fixed language selector * add reverse focus change to FocusController * add default focus item * update transitions * update pages * add ListViewFocusController * fix ListView navigation * update CardType for using with focus navigation * remove useless key navigation * remove useless slots, logs, Drawer open and close * fix reverse focus move on listView * fix drawer radio buttons selection * fix drawer layout and focus move * fix PageSetupWizardProtocolSettings focus move * fix back navigation on default focus item * fix crashes after ListView navigation * fix protocol settings focus move * fix focus on users on page share * clean up page share * fix server rename * fix page share default server selection * refactor about page for correct focus move * fix focus move on list views with header and-or footer * minor fixes * fix server list back button handler * fix spawn signals on switch * fix share details drawer * fix drawer open close usage * refactor listViewFocusController * refactor focusController to make the logic more straightforward * fix focus on notification * update config page for scrolling with tab * fix crash on return with esc key * fix focus navigation in dynamic delegate of list view * fix focus move on qr code on share page * refactor page logging settings for focus navigation * update popup * Bump version * Add mandatory requirement for android.software.leanback. * Fix importing files on TVs * fix: add separate method for reading files to fix file reading on Android TV * fix(android): add CHANGE_NETWORK_STATE permission for all Android versions * Fix connection check for AWG/WG * chore: minor fixes (#1235) * fix: add a workaround to open files on Android TV due to lack of SAF * fix: change the banner format for TV * refactor: make TvFilePicker activity more sustainable * fix: add the touch emulation method for Android TV * fix: null uri processing * fix: add the touch emulation method for Android TV * fix: hide UI elements that use file saving * chore: bump version code * add `ScrollBarType` * update initial config page * refactor credentials setup page to handle the focus navigation * add `setDelegateIndex` method to `listViewFocusController` * fix focus behavior on new page/popup * make minor fixes and clean up * fix: get rid of the assign function call * Scrollbar is on if the content is larger than a screen * Fix selection in language change list * Update select language list * update logging settings page * fix checked item in lists * fix split tunneling settings * make unchangable properties readonly * refactor SwitcherType * fix hide/unhide password * `PageShare` readonly properties * Fix list view focus moving on `PageShare` * remove manual focus control on `PageShare` * format `ListViewFocusController` * format `FocusController` * add `focusControl` with utility functions for focus control * refactor `listViewFocusController` acoording to `focusControl` * refactor `focusConroller` according to `focusControl` * add `printSectionName` method to `listViewController` * remove arrow from `Close application` item * fix focus movement in `ServersListView` * `Restore from backup` is visible only on start screen * `I have nothing` is visible only on start screen * fix back button on `SelectLanguageDrawer` * rename `focusControl` to `qmlUtils` * fix `CMakeLists.txt` * fix `ScrollBarType` * fix `PageSetupWizardApiServicesList` * fix focus movement on dynamic delegates in listView * refactor `PageSetupWizardProtocols` * remove comments and clean up * fix `ListViewWithLabelsType` * fix `PageProtocolCloakSettings` * fix `PageSettingsAppSplitTunneling` * fix `PageDevMenu` * remove debug output from `FocusController` * remove debug output from `ListViewFocusController` * remove debug output from `focusControl` * `focusControl` => `FocusControl` --------- Co-authored-by: albexk <albexk@proton.me> Co-authored-by: Nethius <nethiuswork@gmail.com>
2024-12-31 04:16:52 +01:00
void AndroidController::sendTouch(float x, float y)
{
callActivityMethod("sendTouch", "(FF)V", x, y);
}
// Moving log processing to the Android side
jclass AndroidController::log;
jmethodID AndroidController::logDebug;
jmethodID AndroidController::logInfo;
jmethodID AndroidController::logWarning;
jmethodID AndroidController::logError;
jmethodID AndroidController::logFatal;
// static
bool AndroidController::initLogging()
{
QJniEnvironment env;
log = env.findClass(ANDROID_LOG_CLASS);
if (log == nullptr) {
qCritical() << "Android log class" << ANDROID_LOG_CLASS << "not found";
return false;
}
auto logMethodSignature = "(Ljava/lang/String;Ljava/lang/String;)V";
logDebug = env.findStaticMethod(log, "d", logMethodSignature);
if (logDebug == nullptr) {
qCritical() << "Android debug log method not found";
return false;
}
logInfo = env.findStaticMethod(log, "i", logMethodSignature);
if (logInfo == nullptr) {
qCritical() << "Android info log method not found";
return false;
}
logWarning = env.findStaticMethod(log, "w", logMethodSignature);
if (logWarning == nullptr) {
qCritical() << "Android warning log method not found";
return false;
}
logError = env.findStaticMethod(log, "e", logMethodSignature);
if (logError == nullptr) {
qCritical() << "Android error log method not found";
return false;
}
logFatal = env.findStaticMethod(log, "f", logMethodSignature);
if (logFatal == nullptr) {
qCritical() << "Android fatal log method not found";
return false;
}
qInstallMessageHandler(messageHandler);
return true;
}
// static
void AndroidController::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
{
jmethodID logMethod = logDebug;
switch (type) {
case QtDebugMsg:
logMethod = logDebug;
break;
case QtInfoMsg:
logMethod = logInfo;
break;
case QtWarningMsg:
logMethod = logWarning;
break;
case QtCriticalMsg:
logMethod = logError;
break;
case QtFatalMsg:
logMethod = logFatal;
break;
}
QString formattedMessage = qFormatLogMessage(type, context, message);
QJniObject::callStaticMethod<void>(log, logMethod,
QJniObject::fromString(TAG).object<jstring>(),
QJniObject::fromString(formattedMessage).object<jstring>());
}
void AndroidController::qtAndroidControllerInitialized()
{
callActivityMethod("qtAndroidControllerInitialized", "()V");
2021-11-26 17:43:02 +03:00
}
// static
Vpn::ConnectionState AndroidController::convertState(AndroidController::ConnectionState state)
{
switch (state) {
case AndroidController::ConnectionState::CONNECTED: return Vpn::ConnectionState::Connected;
case AndroidController::ConnectionState::CONNECTING: return Vpn::ConnectionState::Connecting;
case AndroidController::ConnectionState::DISCONNECTED: return Vpn::ConnectionState::Disconnected;
case AndroidController::ConnectionState::DISCONNECTING: return Vpn::ConnectionState::Disconnecting;
case AndroidController::ConnectionState::RECONNECTING: return Vpn::ConnectionState::Reconnecting;
case AndroidController::ConnectionState::UNKNOWN: return Vpn::ConnectionState::Unknown;
}
}
// static
QString AndroidController::textConnectionState(AndroidController::ConnectionState state)
{
switch (state) {
case AndroidController::ConnectionState::CONNECTED: return "CONNECTED";
case AndroidController::ConnectionState::CONNECTING: return "CONNECTING";
case AndroidController::ConnectionState::DISCONNECTED: return "DISCONNECTED";
case AndroidController::ConnectionState::DISCONNECTING: return "DISCONNECTING";
case AndroidController::ConnectionState::RECONNECTING: return "RECONNECTING";
case AndroidController::ConnectionState::UNKNOWN: return "UNKNOWN";
}
}
// JNI functions called by Android
// static
void AndroidController::onStatus(JNIEnv *env, jobject thiz, jint stateCode)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
auto state = ConnectionState(stateCode);
emit AndroidController::instance()->status(state);
2021-11-26 17:43:02 +03:00
}
// static
void AndroidController::onServiceDisconnected(JNIEnv *env, jobject thiz)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
2021-11-26 17:43:02 +03:00
emit AndroidController::instance()->serviceDisconnected();
2021-11-26 17:43:02 +03:00
}
// static
void AndroidController::onServiceError(JNIEnv *env, jobject thiz)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
2021-11-26 17:43:02 +03:00
emit AndroidController::instance()->serviceError();
2021-11-26 17:43:02 +03:00
}
// static
void AndroidController::onVpnPermissionRejected(JNIEnv *env, jobject thiz)
2021-11-26 17:43:02 +03:00
{
Q_UNUSED(env);
Q_UNUSED(thiz);
emit AndroidController::instance()->vpnPermissionRejected();
2021-11-26 17:43:02 +03:00
}
// static
void AndroidController::onNotificationStateChanged(JNIEnv *env, jobject thiz)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
emit AndroidController::instance()->notificationStateChanged();
}
// static
void AndroidController::onVpnStateChanged(JNIEnv *env, jobject thiz, jint stateCode)
2021-11-26 17:43:02 +03:00
{
Q_UNUSED(env);
Q_UNUSED(thiz);
auto state = ConnectionState(stateCode);
emit AndroidController::instance()->vpnStateChanged(state);
}
// static
void AndroidController::onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBytes, jlong txBytes)
2022-12-14 18:52:19 +03:00
{
Q_UNUSED(env);
Q_UNUSED(thiz);
emit AndroidController::instance()->statisticsUpdated((quint64) rxBytes, (quint64) txBytes);
2022-12-14 18:52:19 +03:00
}
2021-11-26 17:43:02 +03:00
// static
void AndroidController::onFileOpened(JNIEnv *env, jobject thiz, jstring uri)
{
Q_UNUSED(thiz);
2023-12-26 17:00:06 +03:00
emit AndroidController::instance()->fileOpened(AndroidUtils::convertJString(env, uri));
}
2023-11-21 22:48:52 +03:00
// static
void AndroidController::onConfigImported(JNIEnv *env, jobject thiz, jstring data)
2021-11-26 17:43:02 +03:00
{
Q_UNUSED(thiz);
2023-12-26 17:00:06 +03:00
emit AndroidController::instance()->configImported(AndroidUtils::convertJString(env, data));
2021-11-26 17:43:02 +03:00
}
2023-11-21 22:48:52 +03:00
// static
void AndroidController::onAuthResult(JNIEnv *env, jobject thiz, jboolean result)
{
Q_UNUSED(thiz);
emit AndroidController::instance()->authenticationResult(result);
}
2023-11-21 22:48:52 +03:00
// static
bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
{
Q_UNUSED(thiz);
2023-12-26 17:00:06 +03:00
return ImportController::decodeQrCode(AndroidUtils::convertJString(env, data));
2023-11-21 22:48:52 +03:00
}
// static
void AndroidController::onImeInsetsChanged(JNIEnv *env, jobject thiz, jint heightDp)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
qDebug() << "Android IME insets changed: height =" << heightDp << "dp";
emit AndroidController::instance()->imeInsetsChanged(heightDp);
}
// static
void AndroidController::onSystemBarsInsetsChanged(JNIEnv *env, jobject thiz, jint navBarHeightDp, jint statusBarHeightDp)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
qDebug() << "Android system bars insets changed: nav bar =" << navBarHeightDp << "dp, status bar =" << statusBarHeightDp << "dp";
emit AndroidController::instance()->systemBarsInsetsChanged(navBarHeightDp, statusBarHeightDp);
}