Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provider mode #740

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ android {
}

defaultConfig {
applicationId "network.mysterium.vpn"
applicationId "network.mysterium.provider"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode getVersionCode()
Expand Down
4 changes: 4 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
android:name="updated.mysterium.vpn.ui.settings.SettingsActivity"
android:screenOrientation="portrait" />

<activity
android:name="updated.mysterium.vpn.ui.provider.ProviderActivity"
android:screenOrientation="portrait" />

<activity
android:name="updated.mysterium.vpn.ui.create.account.CreateAccountActivity"
android:screenOrientation="portrait" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import mysterium.MobileNode
// DeferredNode is a wrapper class which holds MobileNode instance promise.
// This allows to load UI without waiting for node to start.
class DeferredNode {

private companion object {
const val TAG = "DeferredNode"
}
Expand All @@ -26,6 +25,7 @@ class DeferredNode {
) {
if (!lock.tryAcquire()) {
Log.i(TAG, "Node is already started or starting, skipping")

} else {
val handler = CoroutineExceptionHandler { _, exception ->
Log.e(TAG, exception.localizedMessage ?: exception.toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ import android.os.Binder
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import mysterium.MobileNode
import mysterium.Mysterium
import network.mysterium.vpn.BuildConfig
import network.mysterium.vpn.R
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
Expand Down Expand Up @@ -75,6 +73,7 @@ class MysteriumAndroidCoreService : VpnService(), KoinComponent {
private var currentState = ConnectionState.NOTCONNECTED
private var vpnTimeSpent: Float? = null // time spent for last session in minutes
private var secondsBetweenAnalyticEvent = 0
private var isProviderActive = false

override fun onDestroy() {
stopMobileNode()
Expand All @@ -89,11 +88,50 @@ class MysteriumAndroidCoreService : VpnService(), KoinComponent {
return MysteriumCoreServiceBridge()
}

private fun startMobileProviderService(active: Boolean) {
mobileNode?.let {
isProviderActive = active
try {
if (active) {
it.startProvider()
} else {
it.stopProvider()
}

} catch (e: Exception) {
isProviderActive = !active
println(e)
}
}
}

private fun innerStopConsumer() {
var c = currentState == ConnectionState.CONNECTED ||
currentState == ConnectionState.CONNECTING ||
currentState == ConnectionState.ON_HOLD ||
currentState == ConnectionState.IP_NOT_CHANGED


GlobalScope.launch(Dispatchers.IO) {
if (c) {
connectionUseCase.disconnect()

activeProposal = null
deferredNode = null
stopForeground(true)
}
}
}

private fun startMobileNode(filesPath: String): MobileNode {
mobileNode?.let {
return it
}
mobileNode = Mysterium.newNode(filesPath, Mysterium.defaultNodeOptions())
mobileNode = Mysterium.newNode(filesPath, Mysterium.defaultProviderNodeOptions())

val launcherVersion = String.format("%s/android", BuildConfig.VERSION_NAME)
Mysterium.setFlagLauncherVersion(launcherVersion)

mobileNode?.overrideWireguardConnection(WireguardAndroidTunnelSetup(this@MysteriumAndroidCoreService))
return mobileNode ?: MobileNode()
}
Expand Down Expand Up @@ -272,6 +310,16 @@ class MysteriumAndroidCoreService : VpnService(), KoinComponent {

inner class MysteriumCoreServiceBridge : Binder(), MysteriumCoreService {

override fun stopConsumer() {
innerStopConsumer()
}
override fun startProvider(active: Boolean) {
startMobileProviderService(active)
}
override fun isProviderActive(): Boolean {
return isProviderActive
}

override fun getDeferredNode() = deferredNode

override fun setDeferredNode(node: DeferredNode?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import updated.mysterium.vpn.notification.NotificationFactory
interface MysteriumCoreService : IBinder {

suspend fun startNode(): MobileNode
fun isProviderActive(): Boolean
fun startProvider(provider: Boolean)
fun stopConsumer()

fun stopNode()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import updated.mysterium.vpn.model.identity.MigrateHermesStatus
import updated.mysterium.vpn.model.identity.MigrateHermesStatusResponse
import updated.mysterium.vpn.model.manual.connect.ConnectionState
import updated.mysterium.vpn.model.manual.connect.CountryInfo
import updated.mysterium.vpn.model.manual.connect.ServiceStatus
import updated.mysterium.vpn.model.nodes.ProposalItem
import updated.mysterium.vpn.model.nodes.ProposalsResponse
import updated.mysterium.vpn.model.payment.Order
Expand Down Expand Up @@ -71,6 +72,16 @@ class NodeRepository(var deferredNode: DeferredNode) {
}
}

// Register service status callback.
suspend fun registerServiceStatusChangeCallback(cb: (stats: ServiceStatus) -> Unit) {
withContext(Dispatchers.IO) {
deferredNode.await()
.registerServiceStatusChangeCallback { service, status ->
cb(ServiceStatus(service, status))
}
}
}

// Register statistics callback.
suspend fun registerStatisticsChangeCallback(cb: (stats: Statistics) -> Unit) {
withContext(Dispatchers.IO) {
Expand Down
4 changes: 4 additions & 0 deletions android/app/src/main/java/updated/mysterium/vpn/di/Modules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import updated.mysterium.vpn.ui.onboarding.OnboardingViewModel
import updated.mysterium.vpn.ui.prepare.top.up.PrepareTopUpViewModel
import updated.mysterium.vpn.ui.private.key.PrivateKeyViewModel
import updated.mysterium.vpn.ui.profile.ProfileViewModel
import updated.mysterium.vpn.ui.provider.ProviderViewModel
import updated.mysterium.vpn.ui.report.issue.ReportIssueViewModel
import updated.mysterium.vpn.ui.search.SearchViewModel
import updated.mysterium.vpn.ui.settings.SettingsViewModel
Expand Down Expand Up @@ -158,6 +159,9 @@ object Modules {
viewModel {
SelectCountryViewModel(get())
}
single {
ProviderViewModel(get())
}
}

fun provideDatabase(context: Context) = Room.databaseBuilder(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package updated.mysterium.vpn.model.manual.connect

data class ProviderState(
val active: Boolean,
)

class ServiceStatus(
val service: String,
val status: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ object NotificationChannels {
const val BALANCE_NOTIFICATION_ID = 4
const val PRIVATE_KEY_NOTIFICATION_ID = 5
const val PAYMENT_STATUS_ID = 6
const val PROVIDER_NOTIFICATION = 7
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package updated.mysterium.vpn.network.usecase
import mysterium.ConnectRequest
import mysterium.GetIdentityRequest
import mysterium.RegisterIdentityRequest
import okhttp3.internal.format
import updated.mysterium.vpn.core.DeferredNode
import updated.mysterium.vpn.core.NodeRepository
import updated.mysterium.vpn.database.preferences.SharedPreferencesList
import updated.mysterium.vpn.database.preferences.SharedPreferencesManager
import updated.mysterium.vpn.model.manual.connect.ConnectionState
import updated.mysterium.vpn.model.manual.connect.ServiceStatus
import updated.mysterium.vpn.model.statistics.Statistics
import updated.mysterium.vpn.model.wallet.Identity

Expand Down Expand Up @@ -77,6 +80,10 @@ class ConnectionUseCase(
callback: (Statistics) -> Unit
) = nodeRepository.registerStatisticsChangeCallback(callback)

suspend fun serviceStatusChangeCallback(
callback: (ServiceStatus) -> Unit
) = nodeRepository.registerServiceStatusChangeCallback(callback)

suspend fun connectionStatusCallback(
callback: (String) -> Unit
) = nodeRepository.registerConnectionStatusChangeCallback(callback)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.core.app.NotificationCompat
import network.mysterium.vpn.R
import updated.mysterium.vpn.model.notification.NotificationChannels
import updated.mysterium.vpn.ui.connection.ConnectionActivity
import updated.mysterium.vpn.ui.provider.ProviderActivity
import updated.mysterium.vpn.ui.splash.SplashActivity
import updated.mysterium.vpn.ui.splash.SplashActivity.Companion.REDIRECTED_FROM_PUSH_KEY

Expand All @@ -19,6 +20,7 @@ class AppNotificationManager(private val notificationManager: NotificationManage
const val ACTION_DISCONNECT = "DISCONNECT"
}

private val providerChannel = "provider"
private val statisticsChannel = "statistics"
private val connLostChannel = "connectionlost"
private val paymentStatusChannel = "paymentstatus"
Expand All @@ -28,6 +30,7 @@ class AppNotificationManager(private val notificationManager: NotificationManage
// pendingAppIntent is used to navigate back to MainActivity
// when user taps on notification.
private lateinit var pendingAppIntent: PendingIntent
private lateinit var pendingProviderIntent: PendingIntent

fun init(ctx: Context) {
context = ctx
Expand All @@ -36,11 +39,17 @@ class AppNotificationManager(private val notificationManager: NotificationManage
}
pendingAppIntent = PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_IMMUTABLE)

val intentProvider = Intent(ctx, ProviderActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
}
pendingProviderIntent = PendingIntent.getActivity(ctx, 0, intentProvider, PendingIntent.FLAG_IMMUTABLE)

registerAllNotificationChannels(context)
}

private fun registerAllNotificationChannels(context: Context) {
with(context) {
createChannel(providerChannel, getString(R.string.provider_notification_chanel))
createChannel(statisticsChannel, getString(R.string.statisctics_notification_chanel))
createChannel(connLostChannel, getString(R.string.connection_lost_notification_chanel))
createChannel(paymentStatusChannel, getString(R.string.payment_notification_chanel))
Expand Down Expand Up @@ -72,6 +81,19 @@ class AppNotificationManager(private val notificationManager: NotificationManage
}
}

fun createProviderNotification(): NotificationFactory {
return {
NotificationCompat.Builder(it, providerChannel)
.setSmallIcon(R.drawable.notification_logo)
.setContentTitle("Provider is active")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVibrate(LongArray(0))
.setContentIntent(pendingProviderIntent)
.setOnlyAlertOnce(true)
.build()
}
}

fun showStatisticsNotification(title: String, content: String) {
val disconnectIntent = Intent(context, AppBroadcastReceiver::class.java).apply {
action = ACTION_DISCONNECT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import updated.mysterium.vpn.ui.connection.ConnectionActivity
import updated.mysterium.vpn.ui.custom.view.ConnectionToolbar
import updated.mysterium.vpn.ui.home.selection.HomeSelectionActivity
import updated.mysterium.vpn.ui.home.selection.HomeSelectionViewModel
import updated.mysterium.vpn.ui.menu.MenuActivity
import updated.mysterium.vpn.ui.provider.ProviderActivity

import java.util.*

abstract class BaseActivity : AppCompatActivity() {
Expand Down Expand Up @@ -266,7 +269,7 @@ abstract class BaseActivity : AppCompatActivity() {
) {
Intent(this, ConnectionActivity::class.java)
} else {
Intent(this, HomeSelectionActivity::class.java)
Intent(this, MenuActivity::class.java)
}
intent.apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import updated.mysterium.vpn.ui.monitoring.MonitoringActivity
import updated.mysterium.vpn.ui.profile.ProfileActivity
import updated.mysterium.vpn.ui.report.issue.ReportIssueActivity
import updated.mysterium.vpn.ui.settings.SettingsActivity
import updated.mysterium.vpn.ui.provider.ProviderActivity
import updated.mysterium.vpn.ui.terms.TermsOfUseActivity
import updated.mysterium.vpn.ui.wallet.WalletActivity

Expand Down Expand Up @@ -50,6 +51,10 @@ class MenuActivity : BaseActivity() {
iconResId = R.drawable.menu_icon_settings,
titleResId = R.string.menu_list_item_settings,
),
MenuItem(
iconResId = R.drawable.menu_icon_settings,
titleResId = R.string.menu_list_item_provider,
),
MenuItem(
iconResId = R.drawable.menu_icon_referral_deactivated,
titleResId = R.string.menu_item_referral_title,
Expand Down Expand Up @@ -185,6 +190,9 @@ class MenuActivity : BaseActivity() {
startActivity(Intent(this, SettingsActivity::class.java))
}
5 -> menuItem.onItemClickListener = {
startActivity(Intent(this, ProviderActivity::class.java))
}
6 -> menuItem.onItemClickListener = {
// TODO("Implement navigation to Referral")
}
}
Expand Down
Loading