summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2024-10-08 16:09:13 +0200
committerDavid Göransson <david.goransson@mullvad.net>2024-10-08 16:09:13 +0200
commit65bdbb5158242d80617dd9b40a9be33333831ce9 (patch)
treeebf0bd03ecff93868b877657c0cad1b097b77e8e
parenta0086e992faf269a6819e1c593962d360ee052aa (diff)
parent24df46bece887df0bd17af55399d69e8021e7d4e (diff)
downloadmullvadvpn-65bdbb5158242d80617dd9b40a9be33333831ce9.tar.xz
mullvadvpn-65bdbb5158242d80617dd9b40a9be33333831ce9.zip
Merge branch 'fix-all-baselined-lint-issues-droid-218'
-rw-r--r--android/app/build.gradle.kts2
-rw-r--r--android/app/lint-baseline.xml37
-rw-r--r--android/app/src/debug/AndroidManifest.xml2
-rw-r--r--android/app/src/main/AndroidManifest.xml10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt91
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/ResourcesExtensions.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt7
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/CustomTextField.kt17
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/EditApiAccessMethodViewModel.kt1
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt1
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt1
-rw-r--r--android/app/src/main/res/xml/data_extraction_rules.xml21
-rw-r--r--android/app/src/main/res/xml/full_backup_content.xml16
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt3
-rw-r--r--android/build.gradle.kts2
-rw-r--r--android/config/baseline.xml23
-rw-r--r--android/lib/build.gradle.kts1
-rw-r--r--android/lib/common/src/main/AndroidManifest.xml5
-rw-r--r--android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparator.kt36
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherConstant.kt3
-rw-r--r--android/lib/resource/build.gradle.kts1
-rw-r--r--android/lib/resource/lint-baseline.xml76
-rw-r--r--android/lib/resource/src/main/res/drawable-xhdpi/banner.pngbin10264 -> 0 bytes
-rw-r--r--android/lib/resource/src/main/res/drawable/ic_banner_foreground.xml62
-rw-r--r--android/lib/resource/src/main/res/drawable/icon_android_mono.xml6
-rw-r--r--android/lib/resource/src/main/res/mipmap-hdpi/ic_launcher.pngbin3844 -> 0 bytes
-rw-r--r--android/lib/resource/src/main/res/mipmap-mdpi/ic_launcher.pngbin2381 -> 0 bytes
-rw-r--r--android/lib/resource/src/main/res/mipmap-xhdpi/ic_launcher.pngbin5345 -> 0 bytes
-rw-r--r--android/lib/resource/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin8115 -> 0 bytes
-rw-r--r--android/lib/resource/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin11152 -> 0 bytes
-rw-r--r--android/lib/resource/src/main/res/mipmap/ic_banner.xml5
-rw-r--r--android/lib/resource/src/main/res/mipmap/ic_launcher.xml (renamed from android/lib/resource/src/main/res/mipmap-anydpi-v26/ic_launcher.xml)0
-rw-r--r--android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt4
-rw-r--r--android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt3
-rw-r--r--android/test/build.gradle.kts1
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt2
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt3
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt1
39 files changed, 237 insertions, 235 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 979eb466e2..4d5ab430ca 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -47,9 +47,9 @@ android {
lint {
lintConfig = file("${rootProject.projectDir}/config/lint.xml")
- baseline = file("lint-baseline.xml")
abortOnError = true
warningsAsErrors = true
+ checkDependencies = true
}
}
diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml
deleted file mode 100644
index 9f67e68efa..0000000000
--- a/android/app/lint-baseline.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.4.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0)" variant="all" version="8.4.0">
-
- <issue
- id="UseCheckPermission"
- message="The result of `checkPermission` is not used"
- errorLine1=" mockedPackageManager.checkPermission(internet, packageName)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt"
- line="88"
- column="21"/>
- </issue>
-
- <issue
- id="DataExtractionRules"
- message="The attribute `android:allowBackup` is deprecated from Android 12 and higher and may be removed in future versions. Consider adding the attribute `android:dataExtractionRules` specifying an `@xml` resource which configures cloud backups and device transfers on Android 12 and higher."
- errorLine1=" android:allowBackup=&quot;false&quot;"
- errorLine2=" ~~~~~">
- <location
- file="src/main/AndroidManifest.xml"
- line="23"
- column="39"/>
- </issue>
-
- <issue
- id="QueryAllPackagesPermission"
- message="A `&lt;queries>` declaration should generally be used instead of QUERY_ALL_PACKAGES; see https://g.co/dev/packagevisibility for details"
- errorLine1=" &lt;uses-permission android:name=&quot;android.permission.QUERY_ALL_PACKAGES&quot; />"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/AndroidManifest.xml"
- line="6"
- column="22"/>
- </issue>
-
-</issues>
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index cfe2c7c4df..f428b876c7 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:theme="@style/Theme.App.Starting"
android:extractNativeLibs="true"
android:allowBackup="false"
- android:banner="@drawable/banner"
+ android:banner="@mipmap/ic_banner"
android:name=".MullvadApplication"
tools:ignore="DataExtractionRules,GoogleAppIndexingWarning"/>
</manifest>
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 8dc3c4e385..24c430f444 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -3,7 +3,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <!-- Suppress warning, just using queries tag is not enough for our all, we need access to all
+ packages to allow the user to select apps for split tunneling -->
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
+ tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- https://developer.android.com/guide/components/fg-service-types#system-exempted -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
@@ -20,9 +23,12 @@
android:required="false" />
<uses-feature android:glEsVersion="0x00020000"
android:required="false" />
+
<application android:name=".MullvadApplication"
+ android:banner="@mipmap/ic_banner"
android:allowBackup="false"
- android:banner="@drawable/banner"
+ android:fullBackupContent="@xml/full_backup_content"
+ android:dataExtractionRules="@xml/data_extraction_rules"
android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt
index a2485f2e99..df7d3dede0 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt
@@ -18,6 +18,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@@ -118,23 +119,13 @@ private fun Notification(notificationBannerData: NotificationData) {
.testTag(NOTIFICATION_BANNER)
) {
val (status, textTitle, textMessage, actionIcon) = createRefs()
- Box(
- modifier =
- Modifier.background(
- color =
- when (statusLevel) {
- StatusLevel.Error -> MaterialTheme.colorScheme.error
- StatusLevel.Warning -> MaterialTheme.colorScheme.warning
- StatusLevel.Info -> MaterialTheme.colorScheme.surfaceContainer
- },
- shape = CircleShape,
- )
- .size(Dimens.notificationStatusIconSize)
- .constrainAs(status) {
- top.linkTo(textTitle.top)
- start.linkTo(parent.start)
- bottom.linkTo(textTitle.bottom)
- }
+ NotificationDot(
+ statusLevel,
+ Modifier.constrainAs(status) {
+ top.linkTo(textTitle.top)
+ start.linkTo(parent.start)
+ bottom.linkTo(textTitle.bottom)
+ },
)
Text(
text = title.uppercase(),
@@ -173,24 +164,58 @@ private fun Notification(notificationBannerData: NotificationData) {
)
}
action?.let {
- IconButton(
+ NotificationAction(
+ it.icon,
+ onClick = it.onClick,
+ contentDescription = it.contentDescription,
modifier =
Modifier.constrainAs(actionIcon) {
- top.linkTo(parent.top)
- end.linkTo(parent.end)
- bottom.linkTo(parent.bottom)
- }
- .testTag(NOTIFICATION_BANNER_ACTION)
- .padding(all = Dimens.notificationEndIconPadding),
- onClick = it.onClick,
- ) {
- Icon(
- modifier = Modifier.padding(Dimens.notificationIconPadding),
- imageVector = it.icon,
- contentDescription = it.contentDescription,
- tint = MaterialTheme.colorScheme.onSurface,
- )
- }
+ top.linkTo(parent.top)
+ end.linkTo(parent.end)
+ bottom.linkTo(parent.bottom)
+ },
+ )
}
}
}
+
+@Composable
+private fun NotificationDot(statusLevel: StatusLevel, modifier: Modifier) {
+ Box(
+ modifier =
+ modifier
+ .background(
+ color =
+ when (statusLevel) {
+ StatusLevel.Error -> MaterialTheme.colorScheme.error
+ StatusLevel.Warning -> MaterialTheme.colorScheme.warning
+ StatusLevel.Info -> MaterialTheme.colorScheme.surfaceContainer
+ },
+ shape = CircleShape,
+ )
+ .size(Dimens.notificationStatusIconSize)
+ )
+}
+
+@Composable
+private fun NotificationAction(
+ imageVector: ImageVector,
+ contentDescription: String?,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ IconButton(
+ modifier =
+ modifier
+ .testTag(NOTIFICATION_BANNER_ACTION)
+ .padding(all = Dimens.notificationEndIconPadding),
+ onClick = onClick,
+ ) {
+ Icon(
+ modifier = Modifier.padding(Dimens.notificationIconPadding),
+ imageVector = imageVector,
+ contentDescription = contentDescription,
+ tint = MaterialTheme.colorScheme.onSurface,
+ )
+ }
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt
index 3d49a7afca..04f3c05a11 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt
@@ -41,6 +41,7 @@ import net.mullvad.mullvadvpn.compose.textfield.CustomTextField
import net.mullvad.mullvadvpn.compose.util.MAX_VOUCHER_LENGTH
import net.mullvad.mullvadvpn.compose.util.vouchersVisualTransformation
import net.mullvad.mullvadvpn.constant.VOUCHER_LENGTH
+import net.mullvad.mullvadvpn.lib.model.DAYS_PER_VOUCHER_MONTH
import net.mullvad.mullvadvpn.lib.model.RedeemVoucherError
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
@@ -162,18 +163,18 @@ fun RedeemVoucherDialog(
val message =
stringResource(
R.string.added_to_your_account,
- when (days) {
- 0 -> {
+ when {
+ days == 0 -> {
stringResource(R.string.less_than_one_day)
}
- in 1..59 -> {
+ days < 2 * DAYS_PER_VOUCHER_MONTH -> {
pluralStringResource(id = R.plurals.days, count = days, days)
}
else -> {
pluralStringResource(
id = R.plurals.months,
- count = days / 30,
- days / 30,
+ count = days / DAYS_PER_VOUCHER_MONTH,
+ days / DAYS_PER_VOUCHER_MONTH,
)
}
},
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/ResourcesExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/ResourcesExtensions.kt
index 11b41dd27a..9611897e76 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/ResourcesExtensions.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/ResourcesExtensions.kt
@@ -2,20 +2,20 @@ package net.mullvad.mullvadvpn.compose.extensions
import android.content.res.Resources
import net.mullvad.mullvadvpn.R
-import org.joda.time.DateTime
import org.joda.time.Duration
-import org.joda.time.Period
+
+private const val DAYS_IN_STANDARD_YEAR = 365
fun Resources.getExpiryQuantityString(accountExpiry: Duration): String {
- val expiryPeriod = Period(DateTime.now(), accountExpiry)
+ val days = accountExpiry.standardDays.toInt()
+ val years = (accountExpiry.standardDays / DAYS_IN_STANDARD_YEAR).toInt()
+
return if (accountExpiry.millis <= 0) {
getString(R.string.out_of_time)
- } else if (expiryPeriod.years > 0) {
- getRemainingText(this, R.plurals.years_left, expiryPeriod.years)
- } else if (expiryPeriod.months >= 3) {
- getRemainingText(this, R.plurals.months_left, expiryPeriod.months)
- } else if (expiryPeriod.months > 0 || expiryPeriod.days >= 1) {
- getRemainingText(this, R.plurals.days_left, expiryPeriod.days)
+ } else if (years > 1) {
+ getRemainingText(this, R.plurals.years_left, years)
+ } else if (days >= 1) {
+ getRemainingText(this, R.plurals.days_left, days)
} else {
getString(R.string.less_than_a_day_left)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
index 9dcd016767..7a3d338022 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
@@ -94,6 +94,9 @@ private fun PreviewLoginScreen(
AppTheme { LoginScreen(state = state) }
}
+private const val TOP_SPACER_WEIGHT = 1f
+private const val BOTTOM_SPACER_WEIGHT = 3f
+
@Destination<RootGraph>(style = LoginTransition::class)
@Composable
fun Login(
@@ -177,7 +180,7 @@ private fun LoginScreen(
.background(MaterialTheme.colorScheme.primary)
.verticalScroll(scrollState)
) {
- Spacer(modifier = Modifier.weight(1f))
+ Spacer(modifier = Modifier.weight(TOP_SPACER_WEIGHT))
LoginIcon(
state.loginState,
modifier =
@@ -185,7 +188,7 @@ private fun LoginScreen(
.padding(bottom = Dimens.largePadding),
)
LoginContent(state, onAccountNumberChange, onLoginClick, onDeleteHistoryClick)
- Spacer(modifier = Modifier.weight(3f))
+ Spacer(modifier = Modifier.weight(BOTTOM_SPACER_WEIGHT))
CreateAccountPanel(onCreateAccountClick, isEnabled = state.loginState is Idle)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/CustomTextField.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/CustomTextField.kt
index b64de576ee..5bdcc961e7 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/CustomTextField.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/CustomTextField.kt
@@ -13,7 +13,6 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -23,8 +22,6 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.constant.EMPTY_STRING
import net.mullvad.mullvadvpn.constant.NEWLINE_STRING
@@ -53,9 +50,6 @@ fun CustomTextField(
imeAction = ImeAction.Done,
),
) {
-
- val scope = rememberCoroutineScope()
-
// This is the same implementation as in BasicTextField.kt but with initial selection set at the
// end of the text rather than in the beginning.
// This is a fix for https://issuetracker.google.com/issues/272693535.
@@ -97,16 +91,7 @@ fun CustomTextField(
singleLine = true,
placeholder = placeholderText?.let { { Text(text = it) } },
keyboardOptions = keyboardOptions,
- keyboardActions =
- KeyboardActions(
- onDone = {
- scope.launch {
- // https://issuetracker.google.com/issues/305518328
- delay(100)
- onSubmit(value)
- }
- }
- ),
+ keyboardActions = KeyboardActions(onDone = { onSubmit(value) }),
visualTransformation = visualTransformation,
colors = colors,
isError = !isValidValue,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/EditApiAccessMethodViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/EditApiAccessMethodViewModel.kt
index 4d85ae9868..48e4ac85ac 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/EditApiAccessMethodViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/EditApiAccessMethodViewModel.kt
@@ -38,6 +38,7 @@ import net.mullvad.mullvadvpn.repository.ApiAccessRepository
import net.mullvad.mullvadvpn.util.delayAtLeast
import org.apache.commons.validator.routines.InetAddressValidator
+@Suppress("TooManyFunctions")
class EditApiAccessMethodViewModel(
private val apiAccessRepository: ApiAccessRepository,
private val inetAddressValidator: InetAddressValidator,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt
index c34b182aa6..4ddad8477b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt
@@ -43,6 +43,7 @@ import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase
import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase
import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase
+@Suppress("TooManyFunctions")
class SelectLocationViewModel(
private val relayListFilterRepository: RelayListFilterRepository,
private val availableProvidersUseCase: AvailableProvidersUseCase,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
index 7829d0ce24..5ca136341e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
@@ -43,6 +43,7 @@ sealed interface VpnSettingsSideEffect {
data object NavigateToDnsDialog : VpnSettingsSideEffect
}
+@Suppress("TooManyFunctions")
class VpnSettingsViewModel(
private val repository: SettingsRepository,
private val relayListRepository: RelayListRepository,
diff --git a/android/app/src/main/res/xml/data_extraction_rules.xml b/android/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000000..b762ef705c
--- /dev/null
+++ b/android/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Sample data extraction rules file; uncomment and customize as necessary.
+ See https://developer.android.com/about/versions/12/backup-restore#xml-changes
+ for details.
+-->
+<data-extraction-rules>
+ <cloud-backup>
+ <exclude domain="root" />
+ <exclude domain="file" />
+ <exclude domain="database" />
+ <exclude domain="sharedpref" />
+ <exclude domain="external" />
+ </cloud-backup>
+ <device-transfer>
+ <exclude domain="root" />
+ <exclude domain="file" />
+ <exclude domain="database" />
+ <exclude domain="sharedpref" />
+ <exclude domain="external" />
+ </device-transfer>
+</data-extraction-rules>
diff --git a/android/app/src/main/res/xml/full_backup_content.xml b/android/app/src/main/res/xml/full_backup_content.xml
new file mode 100644
index 0000000000..e88e6597d9
--- /dev/null
+++ b/android/app/src/main/res/xml/full_backup_content.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Full backup content file
+ See https://developer.android.com/guide/topics/manifest/application-element#fullBackupContent
+ for details.
+-->
+<full-backup-content>
+ <exclude domain="file" />
+ <exclude domain="database" />
+ <exclude domain="sharedpref" />
+ <exclude domain="external" />
+ <exclude domain="root" />
+ <exclude domain="device_file" />
+ <exclude domain="device_database" />
+ <exclude domain="device_sharedpref" />
+ <exclude domain="device_root" />
+</full-backup-content>
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt
index 560dafb24a..efa97c6ab0 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn.applist
import android.Manifest
+import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import io.mockk.every
@@ -22,6 +23,7 @@ class ApplicationsProviderTest {
unmockkAll()
}
+ @SuppressLint("UseCheckPermission")
@Test
fun `fetch all apps should work`() {
val launchWithInternetPackageName = "launch_with_internet_package_name"
@@ -75,6 +77,7 @@ class ApplicationsProviderTest {
verifyAll {
mockedPackageManager.getInstalledApplications(PackageManager.GET_META_DATA)
+ // Ensure checkPermission was invoked on all packages
listOf(
launchWithInternetPackageName,
launchWithoutInternetPackageName,
diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index f62e00c87e..24bcb0e4d0 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -71,7 +71,6 @@ buildscript {
}
}
-val baselineFile = file("$rootDir/config/baseline.xml")
val configFile = files("$rootDir/config/detekt.yml")
val projectSource = file(projectDir)
@@ -82,7 +81,6 @@ detekt {
allRules = false
config.setFrom(configFile)
source.setFrom(projectSource)
- baseline = baselineFile
parallel = true
ignoreFailures = false
autoCorrect = true
diff --git a/android/config/baseline.xml b/android/config/baseline.xml
deleted file mode 100644
index 34abe7b924..0000000000
--- a/android/config/baseline.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" ?>
-<SmellBaseline>
- <ManuallySuppressedIssues></ManuallySuppressedIssues>
- <CurrentIssues>
- <ID>CyclomaticComplexMethod:MockApiDispatcher.kt$MockApiDispatcher$override fun dispatch(request: RecordedRequest): MockResponse</ID>
- <ID>EmptyKtFile:build.gradle.kts$.build.gradle.kts</ID>
- <ID>LongMethod:NotificationBanner.kt$@Composable private fun Notification(notificationBannerData: NotificationData)</ID>
- <ID>MagicNumber:CustomTextField.kt$100</ID>
- <ID>MagicNumber:LoginScreen.kt$3f</ID>
- <ID>MagicNumber:RedeemVoucherDialog.kt$30</ID>
- <ID>MagicNumber:RedeemVoucherDialog.kt$59</ID>
- <ID>MagicNumber:ResourcesExtensions.kt$3</ID>
- <ID>NestedBlockDepth:MockApiDispatcher.kt$MockApiDispatcher$override fun dispatch(request: RecordedRequest): MockResponse</ID>
- <ID>PrintStackTrace:Extensions.kt$ex</ID>
- <ID>ReturnCount:RelayNameComparator.kt$RelayNameComparator$private infix fun List&lt;String&gt;.compareWith(other: List&lt;String&gt;): Int</ID>
- <ID>ReturnCount:TalpidVpnService.kt$TalpidVpnService$private fun createTun(config: TunConfig): CreateTunResult</ID>
- <ID>TooManyFunctions:EditApiAccessMethodViewModel.kt$EditApiAccessMethodViewModel : ViewModel</ID>
- <ID>TooManyFunctions:SelectLocationViewModel.kt$SelectLocationViewModel : ViewModel</ID>
- <ID>TooManyFunctions:VpnSettingsViewModel.kt$VpnSettingsViewModel : ViewModel</ID>
- <ID>UnusedParameter:SimpleMullvadHttpClient.kt$SimpleMullvadHttpClient$body: JSONArray? = null</ID>
- <ID>UnusedPrivateMember:ConnectivityListener.kt$ConnectivityListener$private fun finalize()</ID>
- </CurrentIssues>
-</SmellBaseline>
diff --git a/android/lib/build.gradle.kts b/android/lib/build.gradle.kts
deleted file mode 100644
index 8b13789179..0000000000
--- a/android/lib/build.gradle.kts
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/android/lib/common/src/main/AndroidManifest.xml b/android/lib/common/src/main/AndroidManifest.xml
index acaad2f3b4..cc947c5679 100644
--- a/android/lib/common/src/main/AndroidManifest.xml
+++ b/android/lib/common/src/main/AndroidManifest.xml
@@ -1,4 +1 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools">
- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
-</manifest>
+<manifest />
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparator.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparator.kt
index a1b1d3b092..4b848dde7b 100644
--- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparator.kt
+++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparator.kt
@@ -6,28 +6,32 @@ internal object RelayNameComparator : Comparator<RelayItem.Location.Relay> {
override fun compare(o1: RelayItem.Location.Relay, o2: RelayItem.Location.Relay): Int {
val partitions1 = o1.name.split(regex)
val partitions2 = o2.name.split(regex)
- return if (partitions1.size > partitions2.size) partitions1 compareWith partitions2
- else -(partitions2 compareWith partitions1)
- }
- private infix fun List<String>.compareWith(other: List<String>): Int {
- this.forEachIndexed { index, s ->
- if (other.size <= index) return 1
- val partsCompareResult = compareStringOrInt(other[index], s)
- if (partsCompareResult != 0) return partsCompareResult
- }
- return 0
+ partitions1
+ .zip(partitions2)
+ .map { (p1, p2) -> compareStringOrInt(p1, p2) }
+ .forEach {
+ if (it != 0) {
+ // Parts differed, return compare result
+ return it
+ }
+ }
+ return partitions1.size.compareTo(partitions2.size)
}
- private fun compareStringOrInt(s1: String, s2: String): Int {
- val int1 = s1.toIntOrNull()
- val int2 = s2.toIntOrNull()
- return if (int1 == null || int2 == null || int1 == int2) {
- s2.compareTo(s1)
+ private fun compareStringOrInt(p1: String, p2: String): Int {
+ val int1 = p1.toIntOrNull()
+ val int2 = p2.toIntOrNull()
+ return if (int1 is Int && int2 is Int && int1 != int2) {
+ // If both are Int and not equal (they might have leading zeros) we should compare them
+ // as numbers
+ int1.compareTo(int2)
} else {
- int2.compareTo(int1)
+ p1.compareTo(p2)
}
}
+ // Regexp that splits digit and non digit, e.g se-got-wg-101 would be ["se-got-wg-", "101"] so
+ // that the number later can be sorted, e.g 9 being listed before 10.
private val regex = "(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)".toRegex()
}
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherConstant.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherConstant.kt
new file mode 100644
index 0000000000..a27efa6bf3
--- /dev/null
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherConstant.kt
@@ -0,0 +1,3 @@
+package net.mullvad.mullvadvpn.lib.model
+
+const val DAYS_PER_VOUCHER_MONTH = 30
diff --git a/android/lib/resource/build.gradle.kts b/android/lib/resource/build.gradle.kts
index c162b25a0c..fa9cd5d63e 100644
--- a/android/lib/resource/build.gradle.kts
+++ b/android/lib/resource/build.gradle.kts
@@ -23,7 +23,6 @@ android {
lint {
lintConfig = file("lint.xml")
- baseline = file("lint-baseline.xml")
abortOnError = true
warningsAsErrors = true
}
diff --git a/android/lib/resource/lint-baseline.xml b/android/lib/resource/lint-baseline.xml
deleted file mode 100644
index d46970e0db..0000000000
--- a/android/lib/resource/lint-baseline.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.4" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.4)" variant="all" version="8.1.4">
-
- <issue
- id="ObsoleteSdkInt"
- message="This folder configuration (`v26`) is unnecessary; `minSdkVersion` is 26. Merge all the resources in this folder into `mipmap-anydpi`.">
- <location
- file="src/main/res/mipmap-anydpi-v26"/>
- </issue>
-
- <issue
- id="VectorPath"
- message="Very long vector path (917 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
- errorLine1=" &lt;path android:fillColor=&quot;#FF294D73&quot;"
- errorLine2=" ~~~~~~~~~">
- <location
- file="src/main/res/drawable/account_history_remove_pressed.xml"
- line="7"
- column="30"/>
- </issue>
-
- <issue
- id="VectorPath"
- message="Very long vector path (1165 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
- errorLine1=" &lt;path android:pathData=&quot;M74.2,74.5c-8,10.3 -29,11.9 -38.3,0.4c-0.2,-0.9 1.9,-2.5 3.2,-4.3c0.6,-0.9 1.2,-1.8 1.6,-2.7c0.6,-1.7 -0.6,-1.6 -1.4,-3.1c-0.1,-0.3 -0.3,-0.6 -0.1,-0.9c0.2,-0.6 1.1,-1 1.3,-0.9c3.9,2.6 11.3,1.8 15.8,-3.4c0,0 1.4,0.3 2.1,0.5l-2.1,-1.4l-0.1,-0.1c-0.1,0.1 -0.2,0.1 -0.3,0.2c-9.4,7.1 -15.5,4.1 -15.5,4.1c-0.2,-0.2 -0.8,-0.8 -1.3,-1.2c-6.4,-4.5 -10.9,-10.5 -13,-14.4l-0.8,4.1l0.2,-5.5l-2.7,3.8l2,-4.1c-1.5,-0.2 -2.4,-1.7 -2,-2.9c0.3,-1.3 1.9,-2.2 3.3,-1.6l0.9,-4l-0.2,4.3c0,0 0.2,0.1 0.4,0.1l2.8,-3.4l-1.9,3.3c3,-0.6 8,-0.7 13.3,-0.3l5.5,2.7c2.7,2.4 6.4,5.5 10.5,8.1L67.9,56l1.3,1.9h-1.1l2.3,2.8l-2.1,-0.3c0,0.2 2.1,2.6 2.1,2.6l-1.7,0.2c0.1,0.2 1.7,2.3 1.7,2.3l-1.3,-0.1c0.1,0.3 2,3.5 2,3.5s-0.7,-0.2 -1.1,-0.3C71.7,72.3 74.1,73 74.2,74.5zM72.8,46.2c-0.8,2.5 -3.7,6 -2.6,8.7c-0.4,-0.1 -9.4,-3.1 -11.9,-4.5c-4,-2.5 -7.6,-5.6 -10.3,-8l-0.1,-0.1L38.6,38c-0.1,-0.1 -0.2,-0.1 -0.3,-0.2c1.3,0.1 6.3,0.7 8.5,0.2c-0.4,-1.2 -0.3,-2.7 0.3,-4.1c0.9,-2 2.5,-3.3 4,-3.3c0.3,0 0.6,0.1 0.9,0.2c0.9,-0.8 1.9,-1.5 3.1,-1.9c6.3,-2.5 15.5,2 17.9,8.1C74.1,40 73.8,43.2 72.8,46.2zM52,31.6c-1.4,-0.6 -3.2,0.5 -4,2.6c-0.9,2 -0.5,4.1 0.9,4.7c1.3,0.6 3.2,-0.5 4,-2.6C53.7,34.3 53.3,32.1 52,31.6z&quot;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/res/drawable/icon_android_mono.xml"
- line="6"
- column="29"/>
- </issue>
-
- <issue
- id="VectorPath"
- message="Very long vector path (917 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
- errorLine1=" &lt;path android:fillColor=&quot;#99FFFFFF&quot;"
- errorLine2=" ~~~~~~~~~">
- <location
- file="src/main/res/drawable/icon_close.xml"
- line="7"
- column="30"/>
- </issue>
-
- <issue
- id="VectorPath"
- message="Very long vector path (1161 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
- errorLine1=" &lt;path android:pathData=&quot;M21.2552,12C21.2552,12.408 21.2182,12.792 21.1688,13.176L23.7719,15.156C24.0063,15.336 24.068,15.66 23.9199,15.924L21.4526,20.076C21.3045,20.34 20.9838,20.448 20.7001,20.34L17.6282,19.14C16.9867,19.608 16.2959,20.016 15.5433,20.316L15.0745,23.496C15.0375,23.784 14.7785,24 14.4701,24L9.5354,24C9.227,24 8.9679,23.784 8.9309,23.496L8.4621,20.316C7.7096,20.016 7.0187,19.62 6.3772,19.14L3.3054,20.34C3.034,20.436 2.7009,20.34 2.5529,20.076L0.0855,15.924C-0.0625,15.66 -0.0008,15.336 0.2336,15.156L2.8366,13.176C2.7873,12.792 2.7502,12.396 2.7502,12C2.7502,11.604 2.7873,11.208 2.8366,10.824L0.2336,8.844C-0.0008,8.664 -0.0748,8.34 0.0855,8.076L2.5529,3.924C2.7009,3.66 3.0217,3.552 3.3054,3.66L6.3772,4.86C7.0187,4.392 7.7096,3.984 8.4621,3.684L8.9309,0.504C8.9679,0.216 9.227,0 9.5354,0L14.4701,0C14.7785,0 15.0375,0.216 15.0745,0.504L15.5433,3.684C16.2959,3.984 16.9867,4.38 17.6282,4.86L20.7001,3.66C20.9715,3.564 21.3046,3.66 21.4526,3.924L23.9199,8.076C24.068,8.34 24.0063,8.664 23.7719,8.844L21.1688,10.824C21.2182,11.208 21.2552,11.592 21.2552,12ZM12,17C14.7571,17 17,14.7571 17,12C17,9.2429 14.7571,7 12,7C9.2429,7 7,9.2429 7,12C7,14.7571 9.2429,17 12,17Z&quot;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/res/drawable/icon_settings.xml"
- line="6"
- column="29"/>
- </issue>
-
- <issue
- id="IconDensities"
- message="Missing the following drawables in `drawable-hdpi`: banner.png (found in drawable-xhdpi)">
- <location
- file="src/main/res/drawable-hdpi"/>
- </issue>
-
- <issue
- id="IconDensities"
- message="Missing the following drawables in `drawable-mdpi`: banner.png (found in drawable-xhdpi)">
- <location
- file="src/main/res/drawable-mdpi"/>
- </issue>
-
- <issue
- id="IconDensities"
- message="Missing the following drawables in `drawable-xxhdpi`: banner.png (found in drawable-xhdpi)">
- <location
- file="src/main/res/drawable-xxhdpi"/>
- </issue>
-
-</issues>
diff --git a/android/lib/resource/src/main/res/drawable-xhdpi/banner.png b/android/lib/resource/src/main/res/drawable-xhdpi/banner.png
deleted file mode 100644
index da8eee678d..0000000000
--- a/android/lib/resource/src/main/res/drawable-xhdpi/banner.png
+++ /dev/null
Binary files differ
diff --git a/android/lib/resource/src/main/res/drawable/ic_banner_foreground.xml b/android/lib/resource/src/main/res/drawable/ic_banner_foreground.xml
new file mode 100644
index 0000000000..0e542f5c0d
--- /dev/null
+++ b/android/lib/resource/src/main/res/drawable/ic_banner_foreground.xml
@@ -0,0 +1,62 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:width="320dp"
+ android:height="180dp"
+ android:viewportWidth="640"
+ android:viewportHeight="360"
+ tools:ignore="VectorRaster">
+ <group android:scaleX="0.6666667"
+ android:scaleY="0.6666667"
+ android:translateX="106.666664"
+ android:translateY="60">
+ <path
+ android:pathData="M55,233.34C55,232.84 55.33,232.51 55.83,232.51H65.66C66.32,232.51 66.76,232.73 66.98,233.34L81.22,265.62H81.56L95.52,233.34C95.74,232.79 96.19,232.51 96.85,232.51H106.51C107.01,232.51 107.34,232.84 107.34,233.34V288.29C107.34,288.78 107.01,289.11 106.51,289.11H97.12C96.63,289.11 96.3,288.78 96.3,288.29V256.45H95.96L85.53,280.33C85.2,281.1 84.7,281.43 83.98,281.43H78.3C77.58,281.43 77.08,281.1 76.75,280.33L66.32,256.45H65.99V288.29C65.99,288.78 65.66,289.11 65.16,289.11H55.83C55.33,289.11 55,288.78 55,288.29V233.34Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M119.65,268.28V233.34C119.65,232.84 119.98,232.51 120.48,232.51H130.97C131.46,232.51 131.79,232.84 131.79,233.34V268.61C131.79,275.3 135.55,279.17 141.24,279.17C146.87,279.17 150.57,275.35 150.57,268.61V233.34C150.57,232.84 150.9,232.51 151.39,232.51H161.88C162.38,232.51 162.71,232.84 162.71,233.34V268.28C162.71,282.32 153.77,290 141.18,290C128.59,290.05 119.65,282.37 119.65,268.28Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M174.97,233.34C174.97,232.84 175.3,232.51 175.8,232.51H186.29C186.78,232.51 187.11,232.84 187.11,233.34V277.67C187.11,278.01 187.28,278.17 187.61,278.17H212.45C212.95,278.17 213.28,278.5 213.28,279V288.23C213.28,288.73 212.95,289.06 212.45,289.06H175.8C175.3,289.06 174.97,288.73 174.97,288.23V233.34Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M222.28,233.34C222.28,232.84 222.61,232.51 223.11,232.51H233.6C234.1,232.51 234.43,232.84 234.43,233.34V277.67C234.43,278.01 234.59,278.17 234.92,278.17H259.77C260.27,278.17 260.6,278.5 260.6,279V288.23C260.6,288.73 260.27,289.06 259.77,289.06H223.11C222.61,289.06 222.28,288.73 222.28,288.23V233.34Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M277.93,289.06C277.38,289.06 277.05,288.73 276.88,288.23L258.99,233.4C258.83,232.79 259.16,232.51 259.71,232.51H270.48C271.03,232.51 271.42,232.73 271.58,233.34L282.85,270.49H283.07L294,233.34C294.16,232.79 294.49,232.51 295.05,232.51H305.7C306.2,232.51 306.53,232.84 306.36,233.4L288.48,288.23C288.31,288.73 287.98,289.06 287.48,289.06H277.93Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M326.29,233.34C326.46,232.84 326.79,232.51 327.4,232.51H337.83C338.38,232.51 338.72,232.84 338.88,233.34L357.93,288.29C358.09,288.78 357.93,289.11 357.38,289.11H346.61C346.06,289.11 345.67,288.84 345.51,288.29L342.3,278.39H322.6L319.45,288.29C319.28,288.84 318.95,289.11 318.34,289.11H307.52C306.97,289.11 306.8,288.78 306.97,288.29L326.29,233.34ZM338.94,267.94L332.59,248.16H332.37L326.02,267.94H338.94Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M366.15,233.34C366.15,232.84 366.48,232.51 366.98,232.51H387.91C397.73,232.51 404.63,236.71 407.34,245.23C408.33,248.38 408.83,251.53 408.83,260.76C408.83,269.99 408.33,273.14 407.34,276.29C404.63,284.8 397.73,289.01 387.91,289.01H366.98C366.48,289.01 366.15,288.67 366.15,288.18V233.34ZM378.85,278.23H385.2C390.83,278.23 394.2,276.57 395.64,272.04C396.19,270.38 396.57,268.22 396.57,260.87C396.57,253.52 396.24,251.36 395.64,249.7C394.26,245.17 390.83,243.51 385.2,243.51H378.85C378.52,243.51 378.36,243.68 378.36,244.01V277.78C378.3,278.06 378.47,278.23 378.85,278.23Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M453.27,289.06C452.67,289.06 452.33,288.73 452.17,288.23L434.28,233.4C434.12,232.79 434.45,232.51 435,232.51H445.77C446.32,232.51 446.7,232.73 446.87,233.34L458.13,270.49H458.35L469.28,233.34C469.45,232.79 469.78,232.51 470.33,232.51H480.99C481.48,232.51 481.82,232.84 481.65,233.4L463.87,288.23C463.71,288.73 463.38,289.06 462.88,289.06H453.27Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M490.59,289.11C490.1,289.11 489.77,288.78 489.77,288.29V233.34C489.77,232.84 490.1,232.51 490.59,232.51H512.46C524.71,232.51 532.05,239.92 532.05,250.7C532.05,261.37 524.6,268.83 512.46,268.83H502.46C502.13,268.83 501.97,268.99 501.97,269.33V288.18C501.97,288.67 501.64,289.01 501.14,289.01H490.59V289.11ZM519.85,250.75C519.85,246.22 516.82,243.07 511.68,243.07H502.41C502.08,243.07 501.91,243.24 501.91,243.57V257.77C501.91,258.11 502.08,258.27 502.41,258.27H511.68C516.82,258.33 519.85,255.34 519.85,250.75Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M541.55,233.34C541.55,232.84 541.88,232.51 542.38,232.51H552.32C552.87,232.51 553.42,232.73 553.7,233.34L573.57,268.94H574.01V233.34C574.01,232.84 574.34,232.51 574.84,232.51H584.17C584.67,232.51 585,232.84 585,233.34V288.29C585,288.78 584.67,289.11 584.17,289.11H574.34C573.68,289.11 573.24,288.84 572.97,288.29L553.03,252.8H552.59V288.29C552.59,288.78 552.26,289.11 551.77,289.11H542.43C541.94,289.11 541.61,288.78 541.61,288.29L541.55,233.34Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M263.63,123.4L259.71,131.36L265.,123.95C265.01,124 264.68,134.62 264.68,134.62L266.17,126.6C270.15,134.18 278.92,145.84 291.24,154.52C292.17,155.18 293.39,156.34 293.78,156.78C293.78,156.78 305.54,162.75 323.64,148.93C323.81,148.82 324.03,148.71 324.2,148.6L324.47,148.77L328.45,151.42C327.07,151.04 324.42,150.37 324.42,150.37C315.69,160.43 301.51,162.09 293.89,157.01C293.55,156.78 291.68,157.56 291.35,158.66C291.13,159.27 291.35,159.93 291.62,160.43C293.17,163.31 295.49,163.03 294.38,166.4C293.61,168.23 292.51,169.99 291.29,171.65C288.75,175.08 284.78,178.12 285.16,179.95C303.16,202.17 343.74,199.07 359.2,179.23C358.98,176.35 354.45,174.97 351.3,167.95C352.19,168.23 353.51,168.61 353.51,168.56C353.51,168.5 349.76,162.42 349.59,161.81L352.02,161.98C352.02,161.98 348.82,158 348.71,157.61L351.97,157.17C351.97,157.17 347.88,152.47 347.83,152.09L351.97,152.75L347.44,147.28H349.59L347.05,143.57L326.46,135.45C318.57,130.53 311.55,124.5 306.25,119.86L295.6,114.66C285.38,113.89 275.83,114.17 269.98,115.33L273.73,108.92L268.27,115.44C267.94,115.33 267.55,115.22 267.55,115.22L267.94,106.93L266.12,114.66L263.63,123.4Z"
+ android:fillColor="#D2943B"
+ android:fillType="evenOdd"
+ tools:ignore="VectorPath" />
+ <path
+ android:pathData="M266.12,114.66C263.41,113.39 260.27,115.22 259.71,117.7C259.05,120.08 260.71,123.01 263.63,123.4C266.39,121.68 268.77,117.26 266.12,114.66Z"
+ android:fillColor="#FFCD86"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="M306.31,108.64C305.48,106.37 305.7,103.44 306.86,100.68C308.52,96.86 311.66,94.32 314.64,94.32C315.25,94.32 315.8,94.43 316.36,94.65C318.07,93.11 320.05,91.83 322.26,90.95C334.41,86.09 352.24,94.76 356.82,106.7C359.03,112.51 358.37,118.81 356.49,124.61C354.95,129.37 349.32,136.22 351.41,141.36C350.58,141.14 333.3,135.28 328.34,132.63C320.55,127.76 313.6,121.79 308.35,117.21L308.18,117.04L290.52,108.64C290.3,108.53 290.08,108.42 289.91,108.31C292.34,108.42 302,109.58 306.31,108.64Z"
+ android:fillColor="#FFD524"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="M317.35,105.18C319.02,101.38 318.53,97.49 316.27,96.5C314,95.51 310.82,97.79 309.16,101.6C307.5,105.4 307.98,109.29 310.25,110.28C312.51,111.27 315.69,108.99 317.35,105.18Z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M316.74,95.48C313.82,94.21 309.9,96.7 307.96,101.07C306.03,105.43 306.92,109.96 309.84,111.29C312.77,112.56 316.69,110.07 318.62,105.71C320.55,101.34 319.67,96.81 316.74,95.48ZM317.02,105.04C315.47,108.53 312.55,110.63 310.5,109.74C308.41,108.8 307.96,105.27 309.51,101.73C311.06,98.25 313.98,96.15 316.08,97.03C318.12,97.97 318.57,101.56 317.02,105.04Z"
+ android:fillColor="#192E45"/>
+ </group>
+</vector>
diff --git a/android/lib/resource/src/main/res/drawable/icon_android_mono.xml b/android/lib/resource/src/main/res/drawable/icon_android_mono.xml
index 0d0aa38c12..45e0acfdd5 100644
--- a/android/lib/resource/src/main/res/drawable/icon_android_mono.xml
+++ b/android/lib/resource/src/main/res/drawable/icon_android_mono.xml
@@ -1,9 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="108dp"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M74.2,74.5c-8,10.3 -29,11.9 -38.3,0.4c-0.2,-0.9 1.9,-2.5 3.2,-4.3c0.6,-0.9 1.2,-1.8 1.6,-2.7c0.6,-1.7 -0.6,-1.6 -1.4,-3.1c-0.1,-0.3 -0.3,-0.6 -0.1,-0.9c0.2,-0.6 1.1,-1 1.3,-0.9c3.9,2.6 11.3,1.8 15.8,-3.4c0,0 1.4,0.3 2.1,0.5l-2.1,-1.4l-0.1,-0.1c-0.1,0.1 -0.2,0.1 -0.3,0.2c-9.4,7.1 -15.5,4.1 -15.5,4.1c-0.2,-0.2 -0.8,-0.8 -1.3,-1.2c-6.4,-4.5 -10.9,-10.5 -13,-14.4l-0.8,4.1l0.2,-5.5l-2.7,3.8l2,-4.1c-1.5,-0.2 -2.4,-1.7 -2,-2.9c0.3,-1.3 1.9,-2.2 3.3,-1.6l0.9,-4l-0.2,4.3c0,0 0.2,0.1 0.4,0.1l2.8,-3.4l-1.9,3.3c3,-0.6 8,-0.7 13.3,-0.3l5.5,2.7c2.7,2.4 6.4,5.5 10.5,8.1L67.9,56l1.3,1.9h-1.1l2.3,2.8l-2.1,-0.3c0,0.2 2.1,2.6 2.1,2.6l-1.7,0.2c0.1,0.2 1.7,2.3 1.7,2.3l-1.3,-0.1c0.1,0.3 2,3.5 2,3.5s-0.7,-0.2 -1.1,-0.3C71.7,72.3 74.1,73 74.2,74.5zM72.8,46.2c-0.8,2.5 -3.7,6 -2.6,8.7c-0.4,-0.1 -9.4,-3.1 -11.9,-4.5c-4,-2.5 -7.6,-5.6 -10.3,-8l-0.1,-0.1L38.6,38c-0.1,-0.1 -0.2,-0.1 -0.3,-0.2c1.3,0.1 6.3,0.7 8.5,0.2c-0.4,-1.2 -0.3,-2.7 0.3,-4.1c0.9,-2 2.5,-3.3 4,-3.3c0.3,0 0.6,0.1 0.9,0.2c0.9,-0.8 1.9,-1.5 3.1,-1.9c6.3,-2.5 15.5,2 17.9,8.1C74.1,40 73.8,43.2 72.8,46.2zM52,31.6c-1.4,-0.6 -3.2,0.5 -4,2.6c-0.9,2 -0.5,4.1 0.9,4.7c1.3,0.6 3.2,-0.5 4,-2.6C53.7,34.3 53.3,32.1 52,31.6z"
android:fillColor="#000000"
- android:fillType="evenOdd" />
+ android:fillType="evenOdd"
+ tools:ignore="VectorPath" />
</vector>
diff --git a/android/lib/resource/src/main/res/mipmap-hdpi/ic_launcher.png b/android/lib/resource/src/main/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index eb38145c3c..0000000000
--- a/android/lib/resource/src/main/res/mipmap-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/android/lib/resource/src/main/res/mipmap-mdpi/ic_launcher.png b/android/lib/resource/src/main/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 13f0df6b36..0000000000
--- a/android/lib/resource/src/main/res/mipmap-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/android/lib/resource/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/lib/resource/src/main/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 2534ca44e3..0000000000
--- a/android/lib/resource/src/main/res/mipmap-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/android/lib/resource/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/lib/resource/src/main/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index b01a564765..0000000000
--- a/android/lib/resource/src/main/res/mipmap-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/android/lib/resource/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/lib/resource/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 063b31017e..0000000000
--- a/android/lib/resource/src/main/res/mipmap-xxxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/android/lib/resource/src/main/res/mipmap/ic_banner.xml b/android/lib/resource/src/main/res/mipmap/ic_banner.xml
new file mode 100644
index 0000000000..7a6010ef37
--- /dev/null
+++ b/android/lib/resource/src/main/res/mipmap/ic_banner.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/darkBlue"/>
+ <foreground android:drawable="@drawable/ic_banner_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/android/lib/resource/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/lib/resource/src/main/res/mipmap/ic_launcher.xml
index 56eaaf98c2..56eaaf98c2 100644
--- a/android/lib/resource/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/android/lib/resource/src/main/res/mipmap/ic_launcher.xml
diff --git a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt
index 905f59f313..edeec9a6fe 100644
--- a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt
+++ b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt
@@ -55,6 +55,10 @@ class ConnectivityListener {
connectivityManager.unregisterNetworkCallback(callback)
}
+ // DROID-1401
+ // This function has never been used and should most likely be merged into unregister(),
+ // along with ensuring that the lifecycle of it is correct.
+ @Suppress("UnusedPrivateMember")
private fun finalize() {
destroySender(senderAddress)
senderAddress = 0L
diff --git a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
index cf8a775e13..9470c88318 100644
--- a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
+++ b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
@@ -74,6 +74,9 @@ open class TalpidVpnService : LifecycleVpnService() {
synchronized(this) { activeTunStatus = null }
}
+ // DROID-1407
+ // Function is to be cleaned up and lint suppression to be removed.
+ @Suppress("ReturnCount")
private fun createTun(config: TunConfig): CreateTunResult {
if (prepare(this) != null) {
// VPN permission wasn't granted
diff --git a/android/test/build.gradle.kts b/android/test/build.gradle.kts
deleted file mode 100644
index 8b13789179..0000000000
--- a/android/test/build.gradle.kts
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt
index 5e702a2d80..b5dcc1d647 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt
@@ -167,7 +167,7 @@ class SimpleMullvadHttpClient(context: Context) {
): JSONArray? {
val future = RequestFuture.newFuture<JSONArray>()
val request =
- object : JsonArrayRequest(method, url, null, future, onErrorResponse) {
+ object : JsonArrayRequest(method, url, body, future, onErrorResponse) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers.put("Content-Type", "application/json")
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt
index 356cacb97e..ddb28e3937 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt
@@ -14,8 +14,7 @@ fun Buffer.getAccountNumber(): String? {
return try {
JSONObject(readUtf8()).getString("account_number")
} catch (ex: JSONException) {
- Logger.e("Unable to parse account number")
- ex.printStackTrace()
+ Logger.e("Unable to parse account number", ex)
null
}
}
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt
index a2978808d7..e230152efe 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt
@@ -32,6 +32,7 @@ class MockApiDispatcher : Dispatcher() {
private var cachedPubKeyFromAppUnderTest: String? = null
+ @Suppress("CyclomaticComplexMethod", "NestedBlockDepth")
override fun dispatch(request: RecordedRequest): MockResponse {
Logger.d("Request: $request (body=${request.body.peek().readUtf8()})")
return when (request.path ?: "") {