polarofficial / polar-ble-sdk

Repository includes SDK and code examples. More info https://polar.com/en/developers
Other
447 stars 147 forks source link

PS-FTP MTU not enabled - results with undeliverable exception #402

Open orestesgaolin opened 9 months ago

orestesgaolin commented 9 months ago

Platform on which you observed the bug:

Device on which you observed the bug:

Describe the bug

We see a lot of following exceptions and are not sure whether this is issue in how we use the SDK, or SDK itself. We believe this line is related to this error. Checked all the subscriptions to Polar SDK and each is being disposed when no longer used.

Fatal Exception: kj.g: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | kg.c: PS-FTP MTU not enabled
       at io.reactivex.rxjava3.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:372)
       at io.reactivex.rxjava3.internal.util.AtomicThrowable.tryAddThrowableOrReport(AtomicThrowable.java:52)
       at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.innerError(FlowableFlatMap.java:564)
       at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$InnerSubscriber.onError(FlowableFlatMap.java:636)
       at io.reactivex.rxjava3.internal.util.AtomicThrowable.tryTerminateConsumer(AtomicThrowable.java:94)
       at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.checkTerminate(FlowableFlatMap.java:540)
       at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.drainLoop(FlowableFlatMap.java:365)
       at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.drain(FlowableFlatMap.java:357)
       at io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onError(FlowableFlatMap.java:318)
       at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable$SingleToFlowableObserver.onError(SingleToFlowable.java:68)
       at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onError(SingleSubscribeOn.java:73)
       at io.reactivex.rxjava3.internal.operators.single.SingleDoFinally$DoFinallyObserver.onError(SingleDoFinally.java:79)
       at io.reactivex.rxjava3.internal.operators.single.SingleDoOnSubscribe$DoOnSubscribeSingleObserver.onError(SingleDoOnSubscribe.java:86)
       at io.reactivex.rxjava3.internal.operators.single.SingleCreate$Emitter.tryOnError(SingleCreate.java:95)
       at com.polar.androidcommunications.api.ble.model.gatt.client.psftp.BlePsFtpClient.lambda$request$0(BlePsFtpClient.java:253)
       at io.reactivex.rxjava3.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:40)
       at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855)
       at io.reactivex.rxjava3.internal.operators.single.SingleDoOnSubscribe.subscribeActual(SingleDoOnSubscribe.java:41)
       at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855)
       at io.reactivex.rxjava3.internal.operators.single.SingleDoFinally.subscribeActual(SingleDoFinally.java:44)
       at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855)
       at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
       at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:644)
       at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
       at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
       at java.util.concurrent.FutureTask.run(FutureTask.java:264)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:307)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at java.lang.Thread.run(Thread.java:1012)
Caused by kg.c: PS-FTP MTU not enabled
       at com.polar.androidcommunications.api.ble.model.gatt.client.psftp.BlePsFtpClient.lambda$request$0(BlePsFtpClient.java:247)
       at io.reactivex.rxjava3.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:40)
       at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855)
       at io.reactivex.rxjava3.internal.operators.single.SingleDoOnSubscribe.subscribeActual(SingleDoOnSubscribe.java:41)
       at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855)
       at io.reactivex.rxjava3.internal.operators.single.SingleDoFinally.subscribeActual(SingleDoFinally.java:44)
       at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855)
       at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
       at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:644)
       at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
       at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
       at java.util.concurrent.FutureTask.run(FutureTask.java:264)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:307)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at java.lang.Thread.run(Thread.java:1012)

Screenshots and logs

Platform: Android Version: 5.1.0

samulimaa commented 8 months ago

Hello,

Thanks for reporting this, I have created an internal ticket for further investigation.

Best regards, Samuli

jimmyzumthurm commented 4 months ago

Hi @orestesgaolin , Have you noticed this still ? I had thoughts about this and to me that case could occur if Verity Sense has dual-connection enabled, and Flow App or any other app / device has authenticated connection ongoing with the device (required to use PSFTP-MTU characteristic), and the 3rd party SDK application is also connected to device in a separate connection but it has just a normal non-authenticated connection (Verity Sense can have only 1 authenticated connection at a time, even with dual connection. This is used for example for HR service that has M1L1 security requirement so you can use Flow for sync and a wrist unit to get HR from the band). In that case the 3rd party app wouldn't the access rights to access this service (I'm guessing here it happened when trying to read offline recording files, which is using PSFTP-MTU)

It could also be possible if you try to read offline recording file before the SDK has enabled notifications for that characteristic. Maybe this function could be used : https://github.com/polarofficial/polar-ble-sdk/blob/c505d8fc3a0388dd27c406cda66b62bc567e43d7/sources/Android/android-communications/library/src/main/java/com/polar/androidcommunications/api/ble/model/gatt/client/psftp/BlePsFtpClient.java#L207 and only after that is called you could try to access this service.

orestesgaolin commented 4 months ago

Yes, we can see this happening in the wild across variety of Android devices.

Is there any way to check if the band is connected to the Polar Flow/maintains authenticated connection? I will try to reproduce it on my devices. Funnily, I try to avoid using Polar Flow on my dev devices, but maybe I should've done this more often.

I'm going to check the clientReady(), thanks for the tip! Will report later

jimmyzumthurm commented 4 months ago

Unfortunately I have no Android knowledge and I don't know if it possible to detect such thing. Usually Flow App doesn't maintain connection with Verity Sense for long as Verity Sense disconnects automatically from it after syncing data, but I don't know if from Android SDK you can detect that. I'm guessing usually Android would try to raise the security level of the connection automatically when trying to access a service characteristic that requires it, but I don't know if a failure could be detected and act upon. At least I'm guessing the BlePsftpClient clientReady could be a way of detecting that as in theory this shouldn't be called unless you have authenticated connection with the device.

@samulimaa Might have better understanding and guidance about that matter.

orestesgaolin commented 3 months ago

Hey there, just wanted to clarify the difference between authenticated connection and non-authenticated.

When we use Polar SDK's polarBleApi.connectToDevice(id) is that going to use the authenticated connection? What would be the example of non-authenticated connection? Would just listening to HR service broadcast be considered non-authenticated?