Skip to content

Commit 1bfa133

Browse files
test: full ViewModel coverage, flow cancellation fixes, no-SIM state, lint cleanup (#37)
Tests (313 -> 363, all 30 features covered) - DashboardViewModel: hardware list, last-used persistence, recent-alert cap - WiFi, BLE, GPS, cell tower, tracker, rogue AP, deauth and signal logger ViewModels: start/stop, auto-stop timers, error surfacing, alert-center forwarding, dedup and reset paths - CellTowerAnalyzer: SIM-absent and empty states - core/testing/MainDispatcherRule for viewModelScope tests Production fixes the tests and lint surfaced - CellTowerAnalyzer and UltrasonicAnalyzer caught the collector's cancellation inside their flow builders and emitted into a cancelled flow ("flow exception transparency violated"). State is now built inside the try and emitted outside it; cancellation is rethrown. - Cell Tower screen explains when no serving cell can appear: new CellTowerState.simAbsent (from TelephonyManager.simState) drives a "No SIM card detected" card instead of an unexplained empty area. - DeviceInfo is built via DeviceInfo.fromBuild() (null-safe) and provided by Hilt, so DashboardViewModel no longer reads android.os.Build in a constructor default that is null on the JVM. - Signal Logger no longer counts every device in the first scan as "new". Lint 149 -> 20 warnings - String.format now passes Locale.US (28 sites) - Dropped empty super.onCleared() calls (24 ViewModels) - CellInfo.UNAVAILABLE inlined as a local constant for minSdk 26 - KTX: SharedPreferences.edit {}, createBitmap, Bitmap.set, toColorInt, mutableIntStateOf - Modifier is the first optional parameter on three composables - Removed unused strings, colours and the unused ic_splash / mipmap ic_notification bitmaps; mipmap-anydpi-v26 merged into mipmap-anydpi - Removed the obsolete SDK 26 check, the redundant activity label and the hardcoded /sdcard path Remaining warnings are dependency version nudges, the branding vector size, resource shrinking and identical round/regular launcher bitmaps. Verified on Vivo V2036 (Android 13): splash, launcher icon, cell tower no-SIM card, ultrasonic start/stop with no flow violations or crashes. Claude-Session: https://claude.ai/code/session_011kW3RTWkhP74LwWy1UFbwt
1 parent cc8e075 commit 1bfa133

73 files changed

Lines changed: 1163 additions & 172 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@
109109
android:name=".MainActivity"
110110
android:exported="true"
111111
android:launchMode="singleTask"
112-
android:label="@string/app_name"
113112
android:theme="@style/Theme.ZeroDroid.Splash">
114113
<intent-filter>
115114
<action android:name="android.intent.action.MAIN" />

app/src/main/java/com/abhishek/zerodroid/core/di/HardwareModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.abhishek.zerodroid.core.di
22

33
import android.content.Context
44
import com.abhishek.zerodroid.core.hardware.HardwareChecker
5+
import com.abhishek.zerodroid.features.dashboard.DeviceInfo
56
import dagger.Module
67
import dagger.Provides
78
import dagger.hilt.InstallIn
@@ -17,4 +18,8 @@ object HardwareModule {
1718
@Singleton
1819
fun provideHardwareChecker(@ApplicationContext context: Context): HardwareChecker =
1920
HardwareChecker(context)
21+
22+
@Provides
23+
@Singleton
24+
fun provideDeviceInfo(): DeviceInfo = DeviceInfo.fromBuild()
2025
}

app/src/main/java/com/abhishek/zerodroid/core/di/SystemServiceModule.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import android.hardware.usb.UsbManager
88
import android.net.wifi.WifiManager
99
import android.net.wifi.aware.WifiAwareManager
1010
import android.nfc.NfcAdapter
11-
import android.os.Build
1211
import android.telephony.TelephonyManager
1312
import dagger.Module
1413
import dagger.Provides
@@ -59,7 +58,5 @@ object SystemServiceModule {
5958
@Provides
6059
@Singleton
6160
fun provideWifiAwareManager(@ApplicationContext context: Context): WifiAwareManager? =
62-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
63-
context.getSystemService(Context.WIFI_AWARE_SERVICE) as? WifiAwareManager
64-
} else null
61+
context.getSystemService(Context.WIFI_AWARE_SERVICE) as? WifiAwareManager
6562
}

app/src/main/java/com/abhishek/zerodroid/core/ui/EthicalUseDialog.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.compose.runtime.setValue
1313
import androidx.compose.ui.platform.LocalContext
1414
import androidx.compose.ui.res.stringResource
1515
import com.abhishek.zerodroid.R
16+
import androidx.core.content.edit
1617

1718
private const val PREFS_NAME = "zerodroid_prefs"
1819
private const val KEY_ETHICAL_ACCEPTED = "ethical_use_accepted"
@@ -41,7 +42,7 @@ fun EthicalUseDialog() {
4142
},
4243
confirmButton = {
4344
TextButton(onClick = {
44-
prefs.edit().putBoolean(KEY_ETHICAL_ACCEPTED, true).apply()
45+
prefs.edit { putBoolean(KEY_ETHICAL_ACCEPTED, true) }
4546
accepted = true
4647
}) {
4748
Text(

app/src/main/java/com/abhishek/zerodroid/features/ble/domain/BleDistanceEstimator.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.abhishek.zerodroid.features.ble.domain
22

33
import kotlin.math.pow
4+
import java.util.Locale
45

56
object BleDistanceEstimator {
67
private const val DEFAULT_TX_POWER = -59
@@ -15,9 +16,9 @@ object BleDistanceEstimator {
1516
fun getDistanceLabel(distanceM: Double): String = when {
1617
distanceM < 0 -> "Unknown"
1718
distanceM < 0.5 -> "Immediate"
18-
distanceM < 2.0 -> "Near (${String.format("%.1f", distanceM)}m)"
19-
distanceM < 10.0 -> "Medium (${String.format("%.1f", distanceM)}m)"
20-
else -> "Far (${String.format("%.0f", distanceM)}m)"
19+
distanceM < 2.0 -> "Near (${String.format(Locale.US, "%.1f", distanceM)}m)"
20+
distanceM < 10.0 -> "Medium (${String.format(Locale.US, "%.1f", distanceM)}m)"
21+
else -> "Far (${String.format(Locale.US, "%.0f", distanceM)}m)"
2122
}
2223

2324
fun getProximityLabel(distanceM: Double): String = when {

app/src/main/java/com/abhishek/zerodroid/features/ble/ui/HciSnoopScreen.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import com.abhishek.zerodroid.ui.theme.TerminalAmber
5757
import com.abhishek.zerodroid.ui.theme.TerminalCyan
5858
import com.abhishek.zerodroid.ui.theme.TerminalGreen
5959
import com.abhishek.zerodroid.ui.theme.TerminalRed
60+
import java.util.Locale
6061

6162
@Composable
6263
fun HciSnoopPanel(viewModel: HciSnoopViewModel) {
@@ -238,7 +239,7 @@ private fun LogInfoCard(log: HciSnoopLog, loadedFrom: String?) {
238239
log.fileSize < 0 -> "unknown"
239240
log.fileSize < 1024 -> "${log.fileSize} B"
240241
log.fileSize < 1024 * 1024 -> "${log.fileSize / 1024} KB"
241-
else -> String.format("%.1f MB", log.fileSize / (1024.0 * 1024.0))
242+
else -> String.format(Locale.US, "%.1f MB", log.fileSize / (1024.0 * 1024.0))
242243
}
243244

244245
val cmdCount = log.packets.count { it.packetType == HciPacketType.Command }
@@ -340,7 +341,7 @@ private fun PacketCard(packet: HciPacket) {
340341
val hours = (totalSeconds / 3600) % 24
341342
val minutes = (totalSeconds % 3600) / 60
342343
val seconds = totalSeconds % 60
343-
val timeStr = String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, millis)
344+
val timeStr = String.format(Locale.US, "%02d:%02d:%02d.%03d", hours, minutes, seconds, millis)
344345

345346
TerminalCard {
346347
Column(

app/src/main/java/com/abhishek/zerodroid/features/ble/viewmodel/BleViewModel.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ class BleViewModel @Inject constructor(
9393
}
9494

9595
override fun onCleared() {
96-
super.onCleared()
9796
stopScan()
9897
}
9998

app/src/main/java/com/abhishek/zerodroid/features/ble/viewmodel/GattViewModel.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ class GattViewModel @Inject constructor(
193193
}
194194

195195
override fun onCleared() {
196-
super.onCleared()
197196
explorer.close()
198197
}
199198

app/src/main/java/com/abhishek/zerodroid/features/ble/viewmodel/HciSnoopViewModel.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class HciSnoopViewModel @Inject constructor(
4040
companion object {
4141
private val KNOWN_LOG_PATHS = listOf(
4242
"/data/misc/bluetooth/logs/btsnoop_hci.log",
43-
"/sdcard/btsnoop_hci.log",
4443
"/data/log/bt/btsnoop_hci.log",
4544
"/storage/emulated/0/btsnoop_hci.log"
4645
)

app/src/main/java/com/abhishek/zerodroid/features/bluetooth_classic/ui/SdpServicePanel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ fun SdpServicePanel(
6060
deviceName: String?,
6161
services: List<SdpServiceInfo>,
6262
isQuerying: Boolean,
63-
isCached: Boolean = false,
6463
onQuerySdp: () -> Unit,
6564
onDismiss: () -> Unit,
66-
modifier: Modifier = Modifier
65+
modifier: Modifier = Modifier,
66+
isCached: Boolean = false
6767
) {
6868
TerminalCard(modifier = modifier.fillMaxWidth()) {
6969
Column(

0 commit comments

Comments
 (0)