fix(aprs): the login line was malformed, and the refusal was invisible
An auditor ran the plan's own release gate against live APRS-IS servers. It failed at
the login step, on every server tried:
sent: user N0CALL pass -1 vers Look4Sat-4.5.4
got: # Invalid login: software name and version are not separated by a space
Reproduced on euro.aprs2.net and noam.aprs2.net, aprsc 2.1.21. `vers` takes TWO tokens,
a software name and a version. An earlier commit read the rule "softwarename must not
contain a space" as "the field must be one token" and hyphenated the space between them
- and the unit test asserted that as correct, so the mistake was frozen in place.
Worse than the malformed line was what happened next. `# Invalid login:` is a comment
but not a logresp, so parse skipped it as keepalive chatter; the login then timed out
into Unknown, which is deliberately treated as "may be working"; so `ok = sent &&
!refused` was true and the operator was shown "APRS: report sent OK" for a login the
server had refused. That is v4.6.0's defining defect - every send reported successful
regardless of outcome - still live on the exact path every operator takes. The rebuild
narrowed it rather than closing it.
Both halves are fixed: the name and version stay separate tokens with whitespace
collapsed within each, and a refusal comment is classified as a refusal before the
logresp test. A socket test now replays the server's actual bytes.
Three smaller things from the same review:
The foreground service type goes back to dataSync. The previous commit chose location
to escape dataSync's six-hour cap, but a location-typed service is refused outright
unless a location runtime permission has already been granted, and the settings card
requests only notifications - so it would have failed silently for anyone who declined
location access. The cap that prompted the switch applies only when targetSdk is 35 or
higher, which this project does not declare. A test now reads the manifest and the
service source and fails if they disagree, which is the only way this class of defect
is visible from a JVM test.
The version string in the login was 4.5.4 while the app was 4.6.0. Now split into name
and version and corrected, though it is still hardcoded - core:data has no BuildConfig,
so passing it in properly is a separate change.
The passcode hint said "empty = auto-computed from callsign" in all five locales. The
app stopped doing that two commits ago; it now connects receive-only, and the hint says
so. It was the first thing an operator read next to the field, promising the behaviour
that was deliberately removed.
Not fixed, and known: the notification body is rebuilt from the previous cycle's state
so it can show a stale verdict, a deliberate receive-only choice is still styled as an
error, and no last-success timestamp exists - so an operator still cannot establish
whether their station has ever reached the network.
This commit is contained in:
1 parent
0208a577c4
commit
321cd8f2fa
13 files changed
+297
-56
No files matched your search
@@ -16,12 +16,14 @@
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<!--
|
||||
location, not dataSync: dataSync foreground services are capped at six hours in any
|
||||
24-hour window and then stopped by the system, which would silently end a beacon meant
|
||||
to run all day. The service reads the station position, falling back to GPS, so location
|
||||
describes what it actually does.
|
||||
dataSync rather than location. The location type is refused outright unless a location
|
||||
runtime permission has already been granted - startForeground throws SecurityException -
|
||||
and this service reads the station position the operator typed into settings, so demanding
|
||||
location access to beacon a fixed QTH is both wrong and a way to fail silently for anyone
|
||||
who declined it. The dataSync six-hour cap that prompted the earlier switch applies only
|
||||
when targetSdk is 35 or higher, which this project does not declare.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<!--
|
||||
Doze suspends network access and ignores wake locks even for a foreground service, so a
|
||||
coroutine delay wakes up on time and then cannot reach the network. An exact alarm with
|
||||
@@ -64,6 +66,6 @@
|
||||
<service
|
||||
android:name="com.rtbishop.look4sat.app.AprsForegroundService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="location" />
|
||||
android:foregroundServiceType="dataSync" />
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -152,13 +152,12 @@ class AprsForegroundService : Service() {
|
||||
try {
|
||||
val notif = buildNotification(cfg)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// Must match the manifest attribute or the platform refuses the call: AOSP checks the
|
||||
// passed type is a subset of the declared one, and location (0x08) does not contain
|
||||
// dataSync (0x01). Changing the manifest without changing this line stopped the
|
||||
// service dead on Android 10 and later - the IllegalArgumentException was caught
|
||||
// below and turned into stopSelf(), so APRS did nothing and reported nothing while
|
||||
// the settings switch stayed on.
|
||||
startForeground(NOTIF_ID, notif, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION)
|
||||
// Must match the manifest attribute exactly: AOSP checks the passed type is a
|
||||
// subset of the declared one and throws otherwise, which the catch below turns
|
||||
// into a silent stopSelf(). Declaring location instead would additionally require
|
||||
// a granted location permission before this call, and the settings card asks only
|
||||
// for notifications - so that combination fails silently too.
|
||||
startForeground(NOTIF_ID, notif, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
|
||||
} else {
|
||||
startForeground(NOTIF_ID, notif)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user