ge0rg / aprsdroid

APRSdroid - Geo-Location for Radio Amateurs
https://aprsdroid.org/
GNU General Public License v2.0
516 stars 101 forks source link

Pull initial Digirig support #382

Open bxlentpartyon opened 3 months ago

bxlentpartyon commented 3 months ago

Pull Digirig support into master.

penguin359 commented 3 months ago

While testing a build of this PR, I am getting an immediate crash when I try to "Start Tracking" after enabling DigiRig in the settings. I have not had a chance to dig deeper yet:

08-03 01:45:12.579 31590 31590 D APRSdroid.Service: onStartCommand: Intent { act=org.aprsdroid.app.SERVICE
cmp=org.aprsdroid.app/.AprsService }, 0, 1
08-03 01:45:12.593 31590 31590 D APRSdroid.Service: addPost: null - APRS Service started: SmartBeaconingΓäó Position,
Audio (AFSK), Digirig.
08-03 01:45:12.610 31590 31590 E AndroidRuntime: Process: org.aprsdroid.app, PID: 31590
08-03 01:45:12.610 31590 31590 E AndroidRuntime: java.lang.RuntimeException: Unable to start service
org.aprsdroid.app.AprsService@60daa5c with Intent { act=org.aprsdroid.app.SERVICE cmp=org.aprsdroid.app/.AprsService
}: java.lang.IllegalArgumentException: org.aprsdroid.app: Targeting S+ (version 31 and above) requires that one of
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
08-03 01:45:12.610 31590 31590 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: org.aprsdroid.app:
Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a
PendingIntent.
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at org.aprsdroid.app.DigiRig.<init>(DigiRig.scala:60)
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at
org.aprsdroid.app.AprsBackend$$anonfun$8.apply(AprsBackend.scala:102)
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at
org.aprsdroid.app.AprsBackend$$anonfun$8.apply(AprsBackend.scala:102)
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at
org.aprsdroid.app.AprsBackend$.instanciateUploader(AprsBackend.scala:170)
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at org.aprsdroid.app.AprsService.startPoster(AprsService.scala:175)
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at org.aprsdroid.app.AprsService.handleStart(AprsService.scala:164)
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at org.aprsdroid.app.AprsService.onStartCommand(AprsService.scala:96)
penguin359 commented 3 months ago

OK, well, I was able to bypass that crash by adding a PendingIntent.FLAG_IMMUTABLE to the PendingIntent(), but now it is crashing further down while requesting permissions. I did see the pop-up asking me to grant permission to access the AIOC adapter I have attached:

08-03 02:04:03.286  4903  4903 D APRSdroid.Storage: open(): instanciating StorageDatabase
08-03 02:04:03.305  4903  4903 D APRSdroid.Service: addPost: null - APRS Service started: SmartBeaconingΓäó Position,
Audio (AFSK), Digirig.
08-03 02:04:03.321  4903  4903 D APRSdroid.Digirig: Digirig.requestPermissions
08-03 02:04:03.325  4903  4903 I APRSdroid.Digirig: Found USB device 1209:7388, requesting permissions.
08-03 02:04:03.326  4903  4927 D APRSdroid.AfskDemod: running...
08-03 02:04:03.330  4903  4903 D APRSdroid.Digirig: onReceive: Intent { act=org.aprsdroid.app.DigiRig.PERM flg=0x10 }
08-03 02:04:03.334  4903  4903 E AndroidRuntime: Process: org.aprsdroid.app, PID: 4903
08-03 02:04:03.334  4903  4903 E AndroidRuntime: java.lang.RuntimeException: Error receiving broadcast Intent {
act=org.aprsdroid.app.DigiRig.PERM flg=0x10 } in org.aprsdroid.app.DigiRig$$anon$1@631ed9e
08-03 02:04:03.334  4903  4903 E AndroidRuntime:        at org.aprsdroid.app.DigiRig$$anon$1.onReceive(DigiRig.scala:81)
bxlentpartyon commented 3 months ago

It sounds like you might not be testing with a Digirig?

Please let me know if I'm wrong about that, and I'll definitely look into it. However, if your issues are with different hardware, I think they should be considered a separate effort from this PR.

penguin359 commented 3 months ago

You are correct that I am not using a DigiRig for my testing. I am trying to get it to work with AIOC, however the two crashes I posted don't seem to have anything to do with the hardware, but with how PendingIntents are handles on newer Android API levels. What version of Android did you develop this under?

I am using a Pixel 7 Pro with Android 13 (API Level 33). Can you try this under the Android Emulator with API level 13? You will need to set up USB passthrough which seems possible, but I haven't done it before myself.

penguin359 commented 3 months ago

OK, I finally understand what the crash is. The fix is merely that you need to pass a flag in when creating the PendingIntent for the broadcast receiver. The fourth argument can no longer just be zero as of API level 31. This is due to a security change in the Android 12 (API level 31) where they made the default to be immutable and added a flag for selecting it explicitly to be mutable rather than immutable. My mistake in trying to fix the first crash is that I set the flag to be immutable which doesn't work in this situation leading to the second crash I posted above.

To sum up, please add PendingIntent.FLAG_MUTABLE to the flags (4th argument) of PendingIntent.getBroadcast() and that will prevent a hard crash on Android 12 and newer. Then, also verify that Android 11 and older still works.

You can read more about that here: PendingIntent.FLAG_MUTABLE

bxlentpartyon commented 3 months ago

I'll test this on my device, but I'd still argue that building for a different Android target than the official release is outside the scope of the work that I'm doing here. I specifically set up my environment to build exactly like the production version so that I didn't have to fight with issues that don't exist in production.

penguin359 commented 3 months ago

I am a little confused at to what you are referring to. I am building the for the official SDK target that the upstream APRSdroid is targeted for. The targetSdkVersion in build.gradle is API level 33 which means it must follow all requirements of that API version. The specific crash I was hitting is documented in the officlal Android documentation under PendingIntent.FLAG_MUTABLE. This issue has nothing to do with the DigiRig hardware support itself, but how PendingIntent needs to be used with a BroadcastReceiver. Here is the crash as I hit it describing the issue:

08-03 01:45:12.610 31590 31590 E AndroidRuntime: java.lang.RuntimeException: Unable to start service
org.aprsdroid.app.AprsService@60daa5c with Intent { act=org.aprsdroid.app.SERVICE cmp=org.aprsdroid.app/.AprsService
}: java.lang.IllegalArgumentException: org.aprsdroid.app: Targeting S+ (version 31 and above) requires that one of
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
08-03 01:45:12.610 31590 31590 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: org.aprsdroid.app:
Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a
PendingIntent.
08-03 01:45:12.610 31590 31590 E AndroidRuntime:        at org.aprsdroid.app.DigiRig.<init>(DigiRig.scala:60)

What Android version are you testing under? This crash will only be seen under Android 12 (API level 31) and newer. If you are testing under an older Android release, you won't see any crash and this patch shouldn't change any behavior, although I haven't been able to test it yet under older Android.

penguin359 commented 3 months ago

I apologize if I've confused things by bringing up the AIOC board, but my recent comments related to the crash I am seeing are not specific to that board. I've sent you a PR with the fix I am talking about in bxlentpartyon/aprsdroid#1 and I expect it to be a simple patch to review. This issue should also affect the DigiRig on newer Android versions.

I am also trying to expand your code to support the AIOC board that I have, but that is above and beyond what is in your PR and I am not expecting you to have to do anything. Once I can get this board also working, I'll create a PR to send to either you or @ge0rg, if your PR is approved and merged in by that time. This is great progress you have made and I am pleased to help beta test the code on my set-up!

bxlentpartyon commented 3 months ago

I got myself confused looking at the error that you hit here - I'm now understanding that this is an actual issue with my branch, just not one that I'm hitting, because I'm using a pretty old device. I will pick your commit on top of my branch so that it gets included with this PR, since I do believe that it probably belongs with it.

Apologies for the confusion here!

bxlentpartyon commented 3 months ago

Branch has been updated - I'm still doing some testing, but, as you mentioned, the patch is pretty simple, so I'm not concerned that pulling it in is going to have unintended side-effects.

Thanks for the additional improvement here!

skteagle commented 1 month ago

Any update on this? I just found this branch and seems like this is exactly the problem I am facing on my Alinco DR-735T and Digirig trying to run on my Samsung A9+.

bxlentpartyon commented 1 month ago

I don't think I ever ran my own build with @penguin359's fix for this, so that is likely why you're still seeing the issue. I will try to run a build tonight with the fix in place and post another release.

bxlentpartyon commented 1 month ago

I realized after looking at this some more that I did actually post a more recent release, but I didn't link it over on the issue, or on here. Did you try this release:

https://github.com/bxlentpartyon/aprsdroid/releases/tag/digirig-v1.1

Or just the one that I linked over in https://github.com/ge0rg/aprsdroid/pull/382 a while back? @skteagle

skteagle commented 1 month ago

I did download and tried to install that release. I am getting this invalid error when I try and install that version. Screenshot_20241003_085848_Package installer

adamberson commented 3 weeks ago

Thanks for these efforts, I've been watching for a while. I tested the 1.1 build.

On several occasions I had a situation where upon transmission I get: USB device detached APRS Service Stopped

Presumably RF is putting the digirig/phone into a bad state so the transmitter stays keyed indefinitely which is discussed in the digirig troubleshooting.

Likely this can't be solved in APRSDroid, but it's a potential problem with RTS control that people should be aware of. If you've already lost control of the port/RTS then presumably this won't work, but I wonder if there could be other locations in the code where it would make sense to attempt setRTS(false) - e.g. upon termination of the UsbThread or during some other crash handling.

na7q commented 3 weeks ago

Thanks for these efforts, I've been watching for a while. I tested the 1.1 build.

On several occasions I had a situation where upon transmission I get: USB device detached APRS Service Stopped

Presumably RF is putting the digirig/phone into a bad state so the transmitter stays keyed indefinitely which is discussed in the digirig troubleshooting.

Likely this can't be solved in APRSDroid, but it's a potential problem with RTS control that people should be aware of. If you've already lost control of the port/RTS then presumably this won't work, but I wonder if there could be other locations in the code where it would make sense to attempt setRTS(false) - e.g. upon termination of the UsbThread or during some other crash handling.

Definitely would need a ferrite with this kind of setup.