Add passing the VPN connection status when rebinding to the service
This commit is contained in:
parent
5835a756ce
commit
dc6e3ec53b
8 changed files with 65 additions and 28 deletions
|
@ -92,12 +92,10 @@ void AmneziaApplication::init()
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
connect(AndroidController::instance(), &AndroidController::serviceIsAlive, this,
|
connect(AndroidController::instance(), &AndroidController::serviceIsAlive, this,
|
||||||
[this](bool connected) {
|
[this](Vpn::ConnectionState state) {
|
||||||
if (connected) {
|
m_connectionController->onConnectionStateChanged(state);
|
||||||
m_connectionController->onConnectionStateChanged(Vpn::ConnectionState::Connected);
|
if (m_vpnConnection)
|
||||||
if (m_vpnConnection)
|
m_vpnConnection->restoreConnection();
|
||||||
m_vpnConnection->restoreConnection();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (!AndroidController::instance()->initialize()) {
|
if (!AndroidController::instance()->initialize()) {
|
||||||
qCritical() << QString("Init failed");
|
qCritical() << QString("Init failed");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.amnezia.vpn.protocol
|
package org.amnezia.vpn.protocol
|
||||||
|
|
||||||
|
// keep synchronized with client/platforms/android/android_controller.h ConnectionState
|
||||||
enum class ProtocolState {
|
enum class ProtocolState {
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
CONNECTING,
|
CONNECTING,
|
||||||
|
|
|
@ -2,19 +2,19 @@ package org.amnezia.vpn.protocol
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
|
||||||
private const val IS_CONNECTED_KEY = "isConnected"
|
private const val STATE_KEY = "state"
|
||||||
|
|
||||||
@Suppress("DataClassPrivateConstructor")
|
@Suppress("DataClassPrivateConstructor")
|
||||||
data class Status private constructor(
|
data class Status private constructor(
|
||||||
val isConnected: Boolean = false
|
val state: ProtocolState
|
||||||
) {
|
) {
|
||||||
private constructor(builder: Builder) : this(builder.isConnected)
|
private constructor(builder: Builder) : this(builder.state)
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
var isConnected: Boolean = false
|
lateinit var state: ProtocolState
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun setConnected(isConnected: Boolean) = apply { this.isConnected = isConnected }
|
fun setState(state: ProtocolState) = apply { this.state = state }
|
||||||
|
|
||||||
fun build(): Status = Status(this)
|
fun build(): Status = Status(this)
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,11 @@ data class Status private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Bundle.putStatus(statistics: Status) {
|
fun Bundle.putStatus(status: Status) {
|
||||||
putBoolean(IS_CONNECTED_KEY, statistics.isConnected)
|
putInt(STATE_KEY, status.state.ordinal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Bundle.getStatus(): Status =
|
fun Bundle.getStatus(): Status =
|
||||||
Status.build {
|
Status.build {
|
||||||
setConnected(getBoolean(IS_CONNECTED_KEY))
|
setState(ProtocolState.entries[getInt(STATE_KEY)])
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,8 +62,8 @@ class AmneziaActivity : QtActivity() {
|
||||||
ServiceEvent.STATUS -> {
|
ServiceEvent.STATUS -> {
|
||||||
if (isWaitingStatus) {
|
if (isWaitingStatus) {
|
||||||
isWaitingStatus = false
|
isWaitingStatus = false
|
||||||
msg.data?.getStatus()?.let { (isConnected) ->
|
msg.data?.getStatus()?.let { (state) ->
|
||||||
QtAndroidController.onStatus(isConnected)
|
QtAndroidController.onStatus(state.ordinal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ class AmneziaVpnService : VpnService() {
|
||||||
clientMessenger.send {
|
clientMessenger.send {
|
||||||
ServiceEvent.STATUS.packToMessage {
|
ServiceEvent.STATUS.packToMessage {
|
||||||
putStatus(Status.build {
|
putStatus(Status.build {
|
||||||
setConnected(this@AmneziaVpnService.isConnected)
|
setState(this@AmneziaVpnService.protocolState.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ package org.amnezia.vpn.qt
|
||||||
* called by events in the Android part of the client
|
* called by events in the Android part of the client
|
||||||
*/
|
*/
|
||||||
object QtAndroidController {
|
object QtAndroidController {
|
||||||
external fun onStatus(isVpnConnected: Boolean)
|
external fun onStatus(stateCode: Int)
|
||||||
external fun onServiceDisconnected()
|
external fun onServiceDisconnected()
|
||||||
external fun onServiceError()
|
external fun onServiceError()
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ namespace
|
||||||
AndroidController::AndroidController() : QObject()
|
AndroidController::AndroidController() : QObject()
|
||||||
{
|
{
|
||||||
connect(this, &AndroidController::status, this,
|
connect(this, &AndroidController::status, this,
|
||||||
[this](bool isVpnConnected) {
|
[this](AndroidController::ConnectionState state) {
|
||||||
qDebug() << "Android event: status; connected:" << isVpnConnected;
|
qDebug() << "Android event: status; state:" << textConnectionState(state);
|
||||||
if (isWaitingStatus) {
|
if (isWaitingStatus) {
|
||||||
qDebug() << "Android VPN service is alive, initialization by service status";
|
qDebug() << "Android VPN service is alive, initialization by service status";
|
||||||
isWaitingStatus = false;
|
isWaitingStatus = false;
|
||||||
emit serviceIsAlive(isVpnConnected);
|
emit serviceIsAlive(convertState(state));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
@ -30,7 +30,7 @@ AndroidController::AndroidController() : QObject()
|
||||||
[this]() {
|
[this]() {
|
||||||
qDebug() << "Android event: service disconnected";
|
qDebug() << "Android event: service disconnected";
|
||||||
isWaitingStatus = true;
|
isWaitingStatus = true;
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Unknown);
|
emit connectionStateChanged(Vpn::ConnectionState::Disconnected);
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ bool AndroidController::initialize()
|
||||||
qDebug() << "Initialize AndroidController";
|
qDebug() << "Initialize AndroidController";
|
||||||
|
|
||||||
const JNINativeMethod methods[] = {
|
const JNINativeMethod methods[] = {
|
||||||
{"onStatus", "(Z)V", reinterpret_cast<void *>(onStatus)},
|
{"onStatus", "(I)V", reinterpret_cast<void *>(onStatus)},
|
||||||
{"onServiceDisconnected", "()V", reinterpret_cast<void *>(onServiceDisconnected)},
|
{"onServiceDisconnected", "()V", reinterpret_cast<void *>(onServiceDisconnected)},
|
||||||
{"onServiceError", "()V", reinterpret_cast<void *>(onServiceError)},
|
{"onServiceError", "()V", reinterpret_cast<void *>(onServiceError)},
|
||||||
{"onVpnPermissionRejected", "()V", reinterpret_cast<void *>(onVpnPermissionRejected)},
|
{"onVpnPermissionRejected", "()V", reinterpret_cast<void *>(onVpnPermissionRejected)},
|
||||||
|
@ -179,14 +179,40 @@ void AndroidController::qtAndroidControllerInitialized()
|
||||||
callActivityMethod("qtAndroidControllerInitialized", "()V");
|
callActivityMethod("qtAndroidControllerInitialized", "()V");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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::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::UNKNOWN: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// JNI functions called by Android
|
// JNI functions called by Android
|
||||||
// static
|
// static
|
||||||
void AndroidController::onStatus(JNIEnv *env, jobject thiz, jboolean isVpnConnected)
|
void AndroidController::onStatus(JNIEnv *env, jobject thiz, jint stateCode)
|
||||||
{
|
{
|
||||||
Q_UNUSED(env);
|
Q_UNUSED(env);
|
||||||
Q_UNUSED(thiz);
|
Q_UNUSED(thiz);
|
||||||
|
|
||||||
emit AndroidController::instance()->status(isVpnConnected);
|
auto state = ConnectionState(stateCode);
|
||||||
|
|
||||||
|
emit AndroidController::instance()->status(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -17,6 +17,15 @@ public:
|
||||||
|
|
||||||
bool initialize();
|
bool initialize();
|
||||||
|
|
||||||
|
// keep synchronized with org.amnezia.vpn.protocol.ProtocolState
|
||||||
|
enum class ConnectionState {
|
||||||
|
CONNECTED,
|
||||||
|
CONNECTING,
|
||||||
|
DISCONNECTED,
|
||||||
|
DISCONNECTING,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
ErrorCode start(const QJsonObject &vpnConfig);
|
ErrorCode start(const QJsonObject &vpnConfig);
|
||||||
void stop();
|
void stop();
|
||||||
void setNotificationText(const QString &title, const QString &message, int timerSec);
|
void setNotificationText(const QString &title, const QString &message, int timerSec);
|
||||||
|
@ -25,7 +34,7 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionStateChanged(Vpn::ConnectionState state);
|
void connectionStateChanged(Vpn::ConnectionState state);
|
||||||
void status(bool isVpnConnected);
|
void status(ConnectionState state);
|
||||||
void serviceDisconnected();
|
void serviceDisconnected();
|
||||||
void serviceError();
|
void serviceError();
|
||||||
void vpnPermissionRejected();
|
void vpnPermissionRejected();
|
||||||
|
@ -34,15 +43,18 @@ signals:
|
||||||
void statisticsUpdated(quint64 rxBytes, quint64 txBytes);
|
void statisticsUpdated(quint64 rxBytes, quint64 txBytes);
|
||||||
void configImported();
|
void configImported();
|
||||||
void importConfigFromOutside(QString &data);
|
void importConfigFromOutside(QString &data);
|
||||||
void serviceIsAlive(bool connected);
|
void serviceIsAlive(Vpn::ConnectionState state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isWaitingStatus = true;
|
bool isWaitingStatus = true;
|
||||||
|
|
||||||
void qtAndroidControllerInitialized();
|
void qtAndroidControllerInitialized();
|
||||||
|
|
||||||
|
static Vpn::ConnectionState convertState(ConnectionState state);
|
||||||
|
static QString textConnectionState(ConnectionState state);
|
||||||
|
|
||||||
// JNI functions called by Android
|
// JNI functions called by Android
|
||||||
static void onStatus(JNIEnv *env, jobject thiz, jboolean isVpnConnected);
|
static void onStatus(JNIEnv *env, jobject thiz, jint stateCode);
|
||||||
static void onServiceDisconnected(JNIEnv *env, jobject thiz);
|
static void onServiceDisconnected(JNIEnv *env, jobject thiz);
|
||||||
static void onServiceError(JNIEnv *env, jobject thiz);
|
static void onServiceError(JNIEnv *env, jobject thiz);
|
||||||
static void onVpnPermissionRejected(JNIEnv *env, jobject thiz);
|
static void onVpnPermissionRejected(JNIEnv *env, jobject thiz);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue