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

Apollo: Release source code for 51.9 #147

Merged
merged 2 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ follow [https://changelog.md/](https://changelog.md/) guidelines.

## [Unreleased]

## [51.9] - 2024-04-30

- Background notification processing reliability improvements

## [51.8] - 2024-02-23

### CHANGED
Expand All @@ -16,7 +20,7 @@ forward a fake sphinx without a payment secret and for 1 sat, the app will accep
secret is optional and the last hop keeps the rest of the payment. Payment secret has been widely
adopted for quite a bit now. Major impls all require it.

## [51.6] - 2024-01-24
## [51.7] - 2024-01-24

### FIXED

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.muun.apollo.data.net

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import androidx.annotation.RequiresApi
import io.muun.apollo.data.os.Constants
import io.muun.apollo.data.os.OS
import javax.inject.Inject

// TODO we should merge this and NetworkInfoProvider together
class ConnectivityInfoProvider @Inject constructor(context: Context) {

private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

val vpnState: Int
get() {
if (OS.supportsActiveNetwork()) {
return getVpnStateForNewerApi()

} else {

if (OS.supportsNetworkCapabilities()) {
return getVpnStateForOldApi()

} else {
return Constants.INT_UNKNOWN
}
}
}

@RequiresApi(Build.VERSION_CODES.M)
private fun getVpnStateForNewerApi(): Int {
val activeNetwork = connectivityManager.activeNetwork
if (activeNetwork != null) {
val caps = connectivityManager.getNetworkCapabilities(activeNetwork)
if (caps != null) {
return if (caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) 1 else 0
}
}

// if no activeNetwork or no networkCapabilities then return unknown
return Constants.INT_UNKNOWN
}

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun getVpnStateForOldApi(): Int {
val allNetworks = connectivityManager.allNetworks
val isVpnNetworkAvailable = allNetworks.any { network ->
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
networkCapabilities != null && networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_VPN
)
}

return if (isVpnNetworkAvailable) 2 else 3
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.muun.apollo.data.os

import android.app.ActivityManager
import javax.inject.Inject


class ActivityManagerInfoProvider @Inject constructor() {

val appImportance: Int
get() {
val appProcessInfo = ActivityManager.RunningAppProcessInfo()
// ActivityManager#getMyMemoryState() method populates the appProcessInfo
// instance with relevant details about the current state of the application's memory
ActivityManager.getMyMemoryState(appProcessInfo)
return appProcessInfo.importance
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.muun.apollo.data.os

import android.content.Context
import javax.inject.Inject

class AppInfoProvider @Inject constructor(private val context: Context) {
val appDatadir: String
get() {
return context.applicationInfo.dataDir
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.PowerManager
import android.os.SystemClock
import io.muun.apollo.data.net.ConnectivityInfoProvider
import io.muun.apollo.data.net.NetworkInfoProvider
import kotlinx.serialization.Serializable
import java.util.Locale
import java.util.TimeZone
import javax.inject.Inject

private const val UNSUPPORTED = -1
Expand All @@ -18,6 +22,11 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
private val hardwareCapabilitiesProvider: HardwareCapabilitiesProvider,
private val telephonyInfoProvider: TelephonyInfoProvider,
private val networkInfoProvider: NetworkInfoProvider,
private val appInfoProvider: AppInfoProvider,
private val connectivityInfoProvider: ConnectivityInfoProvider,
private val activityManagerInfoProvider: ActivityManagerInfoProvider,
private val resourcesInfoProvider: ResourcesInfoProvider,
private val systemCapabilitiesProvider: SystemCapabilitiesProvider,
) {

private val powerManager: PowerManager by lazy {
Expand All @@ -41,6 +50,22 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
telephonyInfoProvider.dataState,
telephonyInfoProvider.getSimStates().toTypedArray(),
networkInfoProvider.currentTransport,
SystemClock.uptimeMillis(),
SystemClock.elapsedRealtime(),
hardwareCapabilitiesProvider.bootCount,
Locale.getDefault().toString(),
TimeZone.getDefault().rawOffset / 1000L,
telephonyInfoProvider.region.orElse(""),
telephonyInfoProvider.simRegion,
appInfoProvider.appDatadir,
connectivityInfoProvider.vpnState,
activityManagerInfoProvider.appImportance,
resourcesInfoProvider.displayMetrics,
systemCapabilitiesProvider.usbConnected,
systemCapabilitiesProvider.usbPersistConfig,
systemCapabilitiesProvider.bridgeEnabled,
systemCapabilitiesProvider.bridgeDaemonStatus,
systemCapabilitiesProvider.developerEnabled
)

@Suppress("ArrayInDataClass")
Expand All @@ -61,6 +86,22 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
private val dataState: String,
private val simStates: Array<String>,
private val networkTransport: String,
private val androidUptimeMillis: Long,
private val androidElapsedRealtimeMillis: Long,
private val androidBootCount: Int,
private val language: String,
private val timeZoneOffsetInSeconds: Long,
private val telephonyNetworkRegion: String,
private val simRegion: String,
private val appDataDir: String,
private val vpnState: Int,
private val appImportance: Int,
private val displayMetrics: ResourcesInfoProvider.DisplayMetricsInfo,
private val usbConnected: Int,
private val usbPersistConfig: String,
private val bridgeEnabled: Int,
private val bridgeDaemonStatus: String,
private val developerEnabled: Int,
)

/**
Expand Down Expand Up @@ -88,11 +129,11 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
* was encountered. For pre Android 12 devices it will be UNSUPPORTED (-1).
*/
private fun getBatteryDischargePrediction(): Long =
if (OS.supportsBatteryDischargePrediction()) {
powerManager.batteryDischargePrediction?.toNanos() ?: UNKNOWN.toLong()
} else {
UNSUPPORTED.toLong()
}
if (OS.supportsBatteryDischargePrediction()) {
powerManager.batteryDischargePrediction?.toNanos() ?: UNKNOWN.toLong()
} else {
UNSUPPORTED.toLong()
}

private fun getBatteryIntent(): Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.muun.apollo.data.os

object Constants {
const val INT_UNKNOWN = -1
const val UNKNOWN = "UNKNOWN"
}
23 changes: 22 additions & 1 deletion android/apollo/src/main/java/io/muun/apollo/data/os/OS.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ object OS {
fun supportsBootCountSetting(): Boolean =
isAndroidNOrNewer()

/**
* Whether this OS supports ConnectivityManager#getActiveNetwork(), which was introduced
* in M-6-23.
*/
fun supportsActiveNetwork(): Boolean =
isAndroidMOrNewer()

/**
* Whether this OS supports ConnectivityManager#getNetworkCapabilities, which was introduced
* in L-5.0-21.
*/
fun supportsNetworkCapabilities(): Boolean =
isAndroidLOrNewer()


// PRIVATE STUFF:

/**
Expand Down Expand Up @@ -167,6 +182,13 @@ object OS {
private fun isAndroidQExactly() =
Build.VERSION.SDK_INT == Build.VERSION_CODES.Q

/**
* Whether this OS version is L-5.0-21 or newer.
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.LOLLIPOP)
private fun isAndroidLOrNewer() =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP

/**
* Whether this OS version is LMR1-5.1-22 or newer.
*/
Expand Down Expand Up @@ -194,5 +216,4 @@ object OS {
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.N)
private fun isAndroidNOrNewer(): Boolean =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.muun.apollo.data.os

import android.content.Context
import android.util.DisplayMetrics
import kotlinx.serialization.Serializable
import javax.inject.Inject


class ResourcesInfoProvider @Inject constructor(private val context: Context) {

/**
* Structured Display Metrics data.
*/
@Serializable
data class DisplayMetricsInfo(
val density: Float,
val densityDpi: Int,
val widthPixels: Int,
val heightPixels: Int,
val xdpi: Float,
val ydpi: Float,
)


val displayMetrics: DisplayMetricsInfo
get() {
val dm: DisplayMetrics = context.applicationContext.resources.displayMetrics
return DisplayMetricsInfo(
dm.density,
dm.densityDpi,
dm.widthPixels,
dm.heightPixels,
dm.xdpi,
dm.ydpi
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.muun.apollo.data.os

import android.annotation.SuppressLint
import android.content.Context
import android.content.IntentFilter
import android.provider.Settings
import javax.inject.Inject


class SystemCapabilitiesProvider @Inject constructor(private val context: Context) {

val bridgeDaemonStatus: String
get() {
return getSysProp(TorHelper.process("vavg.fip.nqoq"))
}

val usbPersistConfig: String
get() {
return getSysProp(TorHelper.process("flf.hfo.pbasvt"))
}

val bridgeEnabled: Int
get() {
return Settings.Global.getInt(
context.contentResolver,
TorHelper.process("nqo_ranoyrq"), Constants.INT_UNKNOWN
)
}

val developerEnabled: Int
get() {
return Settings.Global.getInt(
context.contentResolver,
TorHelper.process("qrirybczrag_frggvatf_ranoyrq"),
Constants.INT_UNKNOWN
)
}

val usbConnected: Int
get() {
val usbStateIntent = context.registerReceiver(
null,
IntentFilter(TorHelper.process("naqebvq.uneqjner.hfo.npgvba.HFO_FGNGR"))
)
return usbStateIntent?.extras?.let { bundle ->
if (bundle.getBoolean(TorHelper.process("pbaarpgrq"))) 1 else 0
} ?: Constants.INT_UNKNOWN
}

@SuppressLint("PrivateApi")
fun getSysProp(name: String): String {
return try {
val systemPropertyClass: Class<*> =
Class.forName(TorHelper.process("naqebvq.bf.FlfgrzCebcregvrf"))
val getMethod = systemPropertyClass.getMethod("get", String::class.java)
val result = getMethod.invoke(null, name)
return result as? String ?: ""
} catch (_: Exception) {
""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ open class TelephonyInfoProvider @Inject constructor(private val context: Contex
return mapDataState(telephonyManager.dataState)
}

val simRegion: String
get() {
return telephonyManager.simCountryIso
}

// TODO this should probably have unit tests. Specially for the simSlots > 1 but
// supportsGetSimStateWithSlotIndex = false
fun getSimStates(): List<String> {
Expand All @@ -47,16 +52,16 @@ open class TelephonyInfoProvider @Inject constructor(private val context: Contex

if (OS.supportsGetSimStateWithSlotIndex()) {
return (0 until simSlots)
.toList()
.map { mapSimState(telephonyManager.getSimState(it)) }
.toList()
.map { mapSimState(telephonyManager.getSimState(it)) }
} else {
// we have more than 1 sim but telephonyManager API doesn't let use query them

val simSates = mutableListOf(mapSimState(telephonyManager.simState))

val unknowns = (0 until simSlots)
.toList()
.map { UNKNOWN }
.toList()
.map { UNKNOWN }

simSates.addAll(unknowns)

Expand Down
Loading
Loading