android: fix all linter warnings and treat warnings as errors (#521)

#Updates tailscale/corp#22284

Fixes and/or explicitly suppresses all linter warnings and
we will now fail the build if new warnings are introduced.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
pull/522/head
Jonathan Nobels 2 months ago committed by GitHub
parent 08ae018468
commit f8f2ee029a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -54,6 +54,10 @@ android {
targetCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17
} }
lintOptions {
warningsAsErrors true
}
kotlinOptions { kotlinOptions {
jvmTarget = "17" jvmTarget = "17"
} }

@ -15,10 +15,11 @@ object AppSourceChecker {
val packageName = context.packageName val packageName = context.packageName
Log.d(TAG, "Package name: $packageName") Log.d(TAG, "Package name: $packageName")
val installerPackageName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val installerPackageName =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
packageManager.getInstallSourceInfo(packageName).installingPackageName packageManager.getInstallSourceInfo(packageName).installingPackageName
} else { } else {
packageManager.getInstallerPackageName(packageName) @Suppress("deprecation") packageManager.getInstallerPackageName(packageName)
} }
Log.d(TAG, "Installer package name: $installerPackageName") Log.d(TAG, "Installer package name: $installerPackageName")
@ -30,5 +31,5 @@ object AppSourceChecker {
null -> "unknown" null -> "unknown"
else -> "unknown($installerPackageName)" else -> "unknown($installerPackageName)"
} }
} }
} }

@ -60,6 +60,7 @@ public class QuickToggleService extends TileService {
} }
} }
@SuppressWarnings("deprecation")
@Override @Override
public void onClick() { public void onClick() {
boolean r; boolean r;
@ -77,6 +78,7 @@ public class QuickToggleService extends TileService {
// Request code for opening activity. // Request code for opening activity.
startActivityAndCollapse(PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); startActivityAndCollapse(PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
} else { } else {
// Deprecated, but still required for older versions.
startActivityAndCollapse(i); startActivityAndCollapse(i);
} }
} }

@ -22,7 +22,7 @@ object Permissions {
@Composable @Composable
get() { get() {
val permissionStates = rememberMultiplePermissionsState(permissions = all.map { it.name }) val permissionStates = rememberMultiplePermissionsState(permissions = all.map { it.name })
return all.zip(permissionStates.permissions).filter { (permission, state) -> return all.zip(permissionStates.permissions).filter { (_, state) ->
!state.status.isGranted && !state.status.shouldShowRationale !state.status.isGranted && !state.status.shouldShowRationale
} }
} }

@ -44,7 +44,8 @@ fun AppTheme(useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable
// margins in list items. // margins in list items.
bodyMedium = MaterialTheme.typography.bodyMedium.copy(fontSize = 16.sp)) bodyMedium = MaterialTheme.typography.bodyMedium.copy(fontSize = 16.sp))
val systemUiController = rememberSystemUiController() // TODO: Migrate to Activity.enableEdgeToEdge
@Suppress("deprecation") val systemUiController = rememberSystemUiController()
DisposableEffect(systemUiController, useDarkTheme) { DisposableEffect(systemUiController, useDarkTheme) {
systemUiController.setStatusBarColor(color = colors.surfaceContainer) systemUiController.setStatusBarColor(color = colors.surfaceContainer)
@ -446,7 +447,6 @@ val ColorScheme.disabled: Color
val ColorScheme.searchBarColors: TextFieldColors val ColorScheme.searchBarColors: TextFieldColors
@Composable @Composable
get() { get() {
val defaults = OutlinedTextFieldDefaults.colors()
return OutlinedTextFieldDefaults.colors( return OutlinedTextFieldDefaults.colors(
focusedLeadingIconColor = MaterialTheme.colorScheme.onSurface, focusedLeadingIconColor = MaterialTheme.colorScheme.onSurface,
unfocusedLeadingIconColor = MaterialTheme.colorScheme.onSurface, unfocusedLeadingIconColor = MaterialTheme.colorScheme.onSurface,

@ -15,7 +15,7 @@ import com.tailscale.ipn.ui.util.AndroidTVUtil.isAndroidTV
object AndroidTVUtil { object AndroidTVUtil {
fun isAndroidTV(): Boolean { fun isAndroidTV(): Boolean {
val pm = UninitializedApp.get().packageManager val pm = UninitializedApp.get().packageManager
return (pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION) || return (pm.hasSystemFeature(@Suppress("deprecation") PackageManager.FEATURE_TELEVISION) ||
pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
} }
} }

@ -61,7 +61,7 @@ fun ExitNodePicker(
if (forcedExitNodeId != null) { if (forcedExitNodeId != null) {
Text( Text(
text = text =
managedByOrganization?.let { managedByOrganization.value?.let {
stringResource(R.string.exit_node_mdm_orgname, it) stringResource(R.string.exit_node_mdm_orgname, it)
} ?: stringResource(R.string.exit_node_mdm), } ?: stringResource(R.string.exit_node_mdm),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,

@ -25,7 +25,10 @@ import com.tailscale.ipn.ui.viewModel.IpnViewModel
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MDMSettingsDebugView(backToSettings: BackNavigation, model: IpnViewModel = viewModel()) { fun MDMSettingsDebugView(
backToSettings: BackNavigation,
@Suppress("UNUSED_PARAMETER") model: IpnViewModel = viewModel()
) {
Scaffold(topBar = { Header(R.string.current_mdm_settings, onBack = backToSettings) }) { Scaffold(topBar = { Header(R.string.current_mdm_settings, onBack = backToSettings) }) {
innerPadding -> innerPadding ->
LazyColumn(modifier = Modifier.padding(innerPadding)) { LazyColumn(modifier = Modifier.padding(innerPadding)) {

@ -251,7 +251,7 @@ fun MainView(
} }
} }
currentPingDevice?.let { peer -> currentPingDevice?.let { _ ->
ModalBottomSheet(onDismissRequest = { viewModel.onPingDismissal() }) { ModalBottomSheet(onDismissRequest = { viewModel.onPingDismissal() }) {
PingView(model = viewModel.pingViewModel) PingView(model = viewModel.pingViewModel)
} }

@ -23,14 +23,16 @@ import com.tailscale.ipn.R
import com.tailscale.ipn.mdm.MDMSettings import com.tailscale.ipn.mdm.MDMSettings
import com.tailscale.ipn.ui.viewModel.IpnViewModel import com.tailscale.ipn.ui.viewModel.IpnViewModel
@Suppress("UNUSED_PARAMETER")
@Composable @Composable
fun ManagedByView(backToSettings: BackNavigation, model: IpnViewModel = viewModel()) { fun ManagedByView(backToSettings: BackNavigation, model: IpnViewModel = viewModel()) {
Scaffold(topBar = { Header(R.string.managed_by, onBack = backToSettings) }) { innerPadding -> Scaffold(topBar = { Header(R.string.managed_by, onBack = backToSettings) }) { _ ->
Column( Column(
verticalArrangement = verticalArrangement =
Arrangement.spacedBy(space = 20.dp, alignment = Alignment.CenterVertically), Arrangement.spacedBy(space = 20.dp, alignment = Alignment.CenterVertically),
horizontalAlignment = Alignment.Start, horizontalAlignment = Alignment.Start,
modifier = Modifier.fillMaxWidth().safeContentPadding().verticalScroll(rememberScrollState())) { modifier =
Modifier.fillMaxWidth().safeContentPadding().verticalScroll(rememberScrollState())) {
val managedByOrganization = val managedByOrganization =
MDMSettings.managedByOrganizationName.flow.collectAsState().value.value MDMSettings.managedByOrganizationName.flow.collectAsState().value.value
val managedByCaption = MDMSettings.managedByCaption.flow.collectAsState().value.value val managedByCaption = MDMSettings.managedByCaption.flow.collectAsState().value.value

@ -32,6 +32,7 @@ import kotlinx.coroutines.launch
import java.time.Duration import java.time.Duration
class MainViewModelFactory(private val vpnViewModel: VpnViewModel) : ViewModelProvider.Factory { class MainViewModelFactory(private val vpnViewModel: VpnViewModel) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MainViewModel::class.java)) { if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
return MainViewModel(vpnViewModel) as T return MainViewModel(vpnViewModel) as T

Loading…
Cancel
Save