mapbox / mapbox-maps-android

Interactive, thoroughly customizable maps in native Android powered by vector tiles and OpenGL.
https://www.mapbox.com/mobile-maps-sdk
Other
468 stars 131 forks source link

Map not updating on certain Xiaomi devices using Android Auto #1413

Closed g4rb4g3 closed 2 years ago

g4rb4g3 commented 2 years ago

Environment

Observed behavior and steps to reproduce

As soon as the main app is not running in foreground on the phones screen the map on Android Auto will stop updating. Other components like speed limits, instructions and so on still update. I just ran the provided Android Auto Example app, as soon as I switch to some other app or turn off the phone screen map updates on Android Auto stop. The position icon and camera are not moving anymore and will only get back to work when the app is running in foreground again.

Expected behavior

Map updates on Android Auto while the app is not in foreground or the phones screen is turned off.

Notes / preliminary analysis

I followed https://dontkillmyapp.com/xiaomi to make sure the app doesn't get killed by the system.

I tried to update the dependencies of the sample app to see if it changes anything, but the issue is still the same.

com.mapbox.navigation:ui-androidauto:0.2.0
com.mapbox.search:mapbox-search-android-ui:1.0.0-beta.30
com.mapbox.navigation:android:2.5.0-rc.1

I've uploaded a video showing the issue, you can see that the Android Auto screen seems to freeze but the current speed is still updated. As soon as the app is in foreground on the phones screen it jumps to the current location.

https://user-images.githubusercontent.com/646435/171581735-f9a1d2f9-254e-4a82-8da5-79095065f6c1.mov

kmadsen commented 2 years ago

Hi @g4rb4g3 this issue is in the example app, so I transferred the issue.

Here's a fix for it https://github.com/mapbox/mapbox-navigation-android-examples/pull/92

SamuelBrucksch commented 2 years ago

Hi @kmadsen

This happens in our production app too and there we do not use Android Auto lib, but pure map box. So this will not fix our issue i think.

We just used the sample app to verify that it's not an issue with our code.

g4rb4g3 commented 2 years ago

@kmadsen As @SamuelBrucksch mentioned we have that issue in our own app so it is not related to the sample app. Still I tried your mapbox/mapbox-navigation-android-examples#92 PR but that did not change anything. As soon as the app is not running in foreground map updates stop. And as I wrote in the first post we face that issue on certain Xiaomi devices, it is working fine on other phones like my Pixel 3a running Android 12. So please move this issue back over to the mapbox/mapbox-maps repo and have a look at it there. Thank you! EDIT: Forgot to mention that I use a mock GPS app, so I'm not using any replay or something like that.

SamuelBrucksch commented 2 years ago

As additional information... We have 3 custom layers where we draw static data onto the map, like speed limit. The speed limit layer is still updating, so the rendering does not seem to completely stop when the main app is in background. However the map and the locationpuck is frozen.

kmadsen commented 2 years ago

Still I tried your https://github.com/mapbox/mapbox-navigation-android-examples/pull/92 PR but that did not change anything

Ok thanks for trying it. I found a different issue in the example repository then.

kmadsen commented 2 years ago

Still I tried your https://github.com/mapbox/mapbox-navigation-android-examples/pull/92 PR but that did not change anything. As soon as the app is not running in foreground map updates stop. And as I wrote in the first post we face that issue on certain Xiaomi devices, it is working fine on other phones like my Pixel 3a running Android 12.

As additional information... We have 3 custom layers where we draw static data onto the map, like speed limit. The speed limit layer is still updating, so the rendering does not seem to completely stop when the main app is in background. However the map and the locationpuck is frozen.

The camera and location have specific configuration in order to make it work correctly. The example repository is responsible for configuration. For example the AndroidManifest must specify the android:foregroundServiceType. Considering that the speed limit is updating, that indicates that the location is continuing to update.

@g4rb4g3 @SamuelBrucksch can you provide more information on what exactly you are seeing? I'm looking for someone with a Xiaomi device that can reproduce this issue. But some logs would be helpful.

Can you add logs around the camera update to ensure a location is sent to the location puck and camera, and the Mapbox sdk it is ignoring it? The maps repository has a minimal androidauto example app that should help us determine if it is a maps issue

https://github.com/mapbox/mapbox-maps-android/blob/6b0b4a0925f4655bab7c4bdc443a33343d65c881/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/CarCameraController.kt#L106

kmadsen commented 2 years ago

Fixed an issue in the navigation examples repo, but transferring this one back to maps as there may be an issue specific to Xiaomi devices

g4rb4g3 commented 2 years ago

@kmadsen Thank you for pointing me to the other sample app I like it a lot since it doesn't work at all on the Xiaomi device. 😉 It doesn't have any activity so if you just launch the app on Android Auto it is stuck on the position it got while starting up. I added some logging and you can see that the new position is incoming. I also added 2 listeners one for renderFrameStarted and another one for renderFrameFinished. Additionally I added an activity I can launch on the phone to make the map updates work. You can check out all my changes to the app here.

So from the logs you can see that there are quite some call for addOnRenderFrameStartedListener and addOnRenderFrameFinishedListener in the beginning (app started on Android Auto only). Once everything settled you can see many of these: 2022-06-07 10:44:25.374 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changePositionListener, got new position Point{type=Point, bbox=null, coordinates=[14.0318107, 48.2240837]} 2022-06-07 10:44:25.375 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changeBearingListener, got new bearing 0.0 2022-06-07 10:44:25.438 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:25.440 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changePositionListener, got new position Point{type=Point, bbox=null, coordinates=[14.031682699600694, 48.224026310360316]} 2022-06-07 10:44:25.442 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changeBearingListener, got new bearing -7.598346638515068 2022-06-07 10:44:25.458 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:25.461 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changePositionListener, got new position Point{type=Point, bbox=null, coordinates=[14.031651669195607, 48.224012397718035]} 2022-06-07 10:44:25.465 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changeBearingListener, got new bearing -9.440370377946238 2022-06-07 10:44:25.475 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener

So a new position is arriving but addOnRenderFrameStartedListener and addOnRenderFrameFinishedListener are called once per gps update mostly.

Only when I launch the activity on the phone you can see that the listeners are reporting like we would expect them to and map updates start working on Android Auto. 2022-06-07 10:44:30.381 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changePositionListener, got new position Point{type=Point, bbox=null, coordinates=[14.02916881403077, 48.22313784773048]} 2022-06-07 10:44:30.381 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changeBearingListener, got new bearing 237.4023516861871 2022-06-07 10:44:30.389 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.402 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.406 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.416 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.422 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.432 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.437 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.450 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.453 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.465 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.469 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.473 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.477 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.481 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.486 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.497 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.505 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.514 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.517 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.522 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.526 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.530 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.534 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.539 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.542 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.556 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.556 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.566 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameStartedListener 2022-06-07 10:44:30.571 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D addOnRenderFrameFinishedListener 2022-06-07 10:44:30.576 10388-10388 CarCameraController com.mapbox.maps.testapp.auto D changePositionListener, got new position Point{type=Point, bbox=null, coordinates=[14.02916881403077, 48.22313784773048]}

2flea commented 2 years ago

Is there any update on this issue? Any fix in sight? I use same phone as @g4rb4g3 - Poco F3 with Android 12 (latest update). I want to use ABRP with AndroidAuto but I need to have the app open and active on my phone all the time. Cheers, Andreas

SamuelBrucksch commented 2 years ago

@kmadsen could you please give an update on the process of this? We are getting more and more reports from Xiaomi users. As this seems to be reproducible easily, could you please rank this a bit higher so we can release an update for the affected users before the summer holidays start?

SamuelBrucksch commented 2 years ago

@pengdev @tobrun @kmadsen can anyone please comment on this? This should really affect the usage of this library for a lot of users, if it can't work on Xiaomi unless the phone screen is on...

pengdev commented 2 years ago

Hi @SamuelBrucksch thanks for reporting the issue, we are still trying to get access to a compatible Xiaomi device to reproduce this issue, will keep you posted about the progress.

CarstenWa commented 2 years ago

@pengdev it isn't just xiaomi. Have the same issues on my huawei p30 pro

xflow7 commented 2 years ago

Hi, @pengdev and @kmadsen, for what it's worth I'm also not sure how device-specific this is. I have the same problem on a Samsung S21. (I arrived here from this bug thread on the ABRP forum)

SamuelBrucksch commented 2 years ago

More and more reports incoming on this. We had to buy a Poco F3 ourself to replicate the problem. If you can't find anyone with a phone please order one so you can fix this.

SamuelBrucksch commented 2 years ago

Hi, @pengdev and @kmadsen, for what it's worth I'm also not sure how device-specific this is. I have the same problem on a Samsung S21. (I arrived here from this bug thread on the ABRP forum)

Samsung is a separate issue and not related to this. A fix will be available soon.

We got another report from Xiaomi Mi11 pro. So it seems like any Xiaomi device on Android 12 will do.

CarstenWa commented 2 years ago

Got the same Problem on an older Huawai p20 with Android 10 on it

kmadsen commented 2 years ago

I've ordered a Poco F3 but it'll be here tomorrow at some point

CarstenWa commented 2 years ago

I've ordered a Poco F3 but it'll be here tomorrow at some point

If it helps out with Huawai I will donate a bit 😁

kmadsen commented 2 years ago

I have a Xiaomi Poco F3. I was not able to reproduce on the out of the box version - on Android 11. I also tested with multiple mock GPS location apps (GPS Locations and Mock GPS with joystick).

Poco F3 with Android 12 (latest update)

I'm updating the phone to test the latest update with Android 12, but posting this because it does work on certain Xiaomi builds.

https://user-images.githubusercontent.com/3021882/180613960-63fdbbe6-0917-4b0f-8a5a-a700da347d0e.mov

g4rb4g3 commented 2 years ago

@kmadsen Thanks for the update, as pointed out in the first post the issue happens on Android 12 for sure. I did not test it with Android 11 since I did the update straight after unpacking it.

kmadsen commented 2 years ago

The system updates available are for the MIUI, so I updated to MIUI 12.5.6 and it worked again.

I'm not seeing an option to upgrade to Android 12, but am seeing an option to upgrade the MIUI (next is 13.0.4.0). EDIT reading online, and sounds like this should also update to Android 12 🤔

SamuelBrucksch commented 2 years ago

Yes MIUI 13 is Android 12. People told us this issue started after the update, so according to them it still worked on Android 11.

kmadsen commented 2 years ago

Ok sounds good, thanks! I'm about to go on a hike (test drive to the trailhead), so after the update I'll be able to see the issues on a few apps. Will dig into potential solutions when I'm back by a computer.

kmadsen commented 2 years ago

It's still working for me after the update, on the desktop head unit. I'm getting the same result as the video here https://github.com/mapbox/mapbox-maps-android/issues/1413#issuecomment-1193151608

Model: M2012K11AG MIUI version: 13.0.4Stable, 13.0.4.0(SKHMIXM) Android version: 12 SKQ1.211006.001 Android security update 2022-06-01

I'm still going for a test drive to see the non-mocked locations. But is there potentially, another setting that needs to be enabled/disabled in order to reproduce this? For example, the GPS Locations suggests this and I haven't enabled that yet.

Screen Shot 2022-07-23 at 10 17 13 AM

CarstenWa commented 2 years ago

On Android 10 it won't work also.

SamuelBrucksch commented 2 years ago

We only used the sample apps as they are and didn't do anything else. The phone screen must be off for the not moving map to show.

kmadsen commented 2 years ago

OK I am able to reproduce the OP issue locally. I'm unable to reproduce in the android-auto-app as mentioned here https://github.com/mapbox/mapbox-maps-android/issues/1413#issuecomment-1148398491. My repo steps require you to first, have an open mobile app and then close it.

EDIT: I updated the log to prove the animation is animating from start to start when app is backgrounded.

Devices reproduced on

Xiaomi MIUI 13.0.4 Android version 12 SKQ1.211006.001

Repo steps

  1. Launch an app with an Activity (qa-test-app or android-auto-app)
  2. Launch the desktop head unit (for example: $ make car)
  3. Kill the mobile app (or put app in background)
  4. Animations have stopped working
  5. Scroll the map
  6. Try to recenter the map, notice the animation will not work

Looks like an animation issue

I am able to fix the recenter button by removing the usage of AnimatorSet

        mapboxMap.setCamera(cameraOptions)
        return AnimatorSet()
//        return ifNonNull(pluginImpl) {
//
//            flyFromLowZoomToHighZoom(cameraOptions, it, transitionOptions)
//        } ?: fromLowZoomToHighZoom(cameraOptions, transitionOptions)

Video and logs

I added a log animator to the MapboxNavigationCameraTransition. The logs include an expected update (animates a value from 5.0 to 10.0). When the activity is backgrounded, the value animator will still be triggered but it animates from 5.0 to 5.0. Resulting in no movement from the animations.

https://user-images.githubusercontent.com/3021882/180879867-15a3c473-a308-48f0-bb7c-f437ed5cee06.mov

    inner class LogAnimator : ValueAnimator() {
        init {
            addPauseListener(
                onResume = { logI("onResume", "kyle_debug") },
                onPause = { logI("onPause", "kyle_debug") },
            )
            addListener(
                onStart = { logI("onStart", "kyle_debug") },
                onCancel = { logI("onCancel", "kyle_debug") },
                onEnd = { logI("onEnd", "kyle_debug") },
                onRepeat = { logI("onRepeat", "kyle_debug") },
            )
            addUpdateListener {
                logI("onUpdate ${it.animatedValue as Float}", "kyle_debug")
            }
            setFloatValues(5f, 10f)
        }
    }
2022-07-25 15:08:03.006 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onStart
2022-07-25 15:08:03.006 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:03.006 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:03.025 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:03.041 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.03501
2022-07-25 15:08:03.068 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.139059
2022-07-25 15:08:03.079 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.321965
2022-07-25 15:08:03.099 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.557135
2022-07-25 15:08:03.108 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.8664484
2022-07-25 15:08:03.121 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 6.227397
2022-07-25 15:08:03.146 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 6.60408
2022-07-25 15:08:03.157 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 7.031547
2022-07-25 15:08:03.172 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 7.447644
2022-07-25 15:08:03.192 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 7.8910856
2022-07-25 15:08:03.210 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 8.297399
2022-07-25 15:08:03.223 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 8.704385
2022-07-25 15:08:03.243 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 9.05287
2022-07-25 15:08:03.253 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 9.3752775
2022-07-25 15:08:03.270 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 9.624731
2022-07-25 15:08:03.287 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 9.824441
2022-07-25 15:08:03.306 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 9.94537
2022-07-25 15:08:03.320 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 9.998766
2022-07-25 15:08:03.336 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 10.0
2022-07-25 15:08:03.336 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onEnd
2022-07-25 15:08:04.022 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onStart
2022-07-25 15:08:04.022 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:04.022 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:05.052 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onCancel
2022-07-25 15:08:05.052 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onEnd
2022-07-25 15:08:05.055 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onStart
2022-07-25 15:08:05.055 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:05.055 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:06.043 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onCancel
2022-07-25 15:08:06.044 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onEnd
g4rb4g3 commented 2 years ago

I just updated my phone to the latest firmware: MIUI: MIUI Global 13.0.7 Stable (SKHEUXM) Android 12 SKQ1.211006.001

Still seeing the same behavior like in the first post. I added some logging to MapboxNavigationCameraTransition.kt and I see the same, as soon as the screen is off or the app is not in foreground the centerAnimator gets the same coordinates over and over. https://user-images.githubusercontent.com/646435/180968316-9ffaeec4-9090-43d6-997c-5218f52f6900.mp4

To create some nice screen captures you can use scrcpy

kmadsen commented 2 years ago

Good idea with scrcpy :). Next, wanted to find if something in Mapbox SDKs is canceling the animations. Here is an empty project, reproducing the issue without a Mapbox SDK hellocar.zip

This is most likely an issue with the MIUI system disabling animations. I am still unable to reproduce on Pixel 4XL which is running Android 12.

https://user-images.githubusercontent.com/3021882/181044841-4c1883fe-9561-4c0f-b2fd-e65465141722.mov

class MainSession : Session() {
--snip--
    init {
        lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onCreate(owner: LifecycleOwner) {
                var lastAnimator: ValueAnimator? = null
                lifecycle.coroutineScope.launch {
                    while (isActive) {
                        lastAnimator?.cancel()
                        lastAnimator = LogAnimator().apply { start() }
                        delay(1000)
                    }
                }
            }
        })
    }
}
kmadsen commented 2 years ago

I've submitted this feedback to xiaomi because this appears to be specific to MIUI https://xiaomiui.net/how-to-report-bugs-on-miui-7934/.

Also submitted a bug here https://c.mi.com/thread-4114167-1-0.html

Screenshot_2022-07-26-08-31-53-681_com miui bugreport

@g4rb4g3 @CarstenWa @xflow7 @SamuelBrucksch you've mentioned this issue is reproducible on other devices. Can you reproduce the issue with the hellocar.zip project from this https://github.com/mapbox/mapbox-maps-android/issues/1413#issuecomment-1195627554?

I would like to know if which devices contain this issue or if other devices have a different issue.

kmadsen commented 2 years ago

Another thing tested, is that there exists an Android 12 setting to disable animations. https://mcmw.abilitynet.org.uk/how-to-disable-interface-animations-in-android-12

On Xiaomi, when the animations are paused it emits the start value multiple times https://github.com/mapbox/mapbox-maps-android/issues/1413#issuecomment-1194685226. This would be at least better, if the update emitted the final value (instead of the first value twice).

2022-07-25 15:08:05.055 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onStart
2022-07-25 15:08:05.055 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:05.055 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onUpdate 5.0
2022-07-25 15:08:06.043 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onCancel
2022-07-25 15:08:06.044 qa_test_app I/Mapbox: [nav-sdk]: [kyle_debug] onEnd

Here is what happens when disabling animations on the Xiaomi device and then backgrounding the app. Notice, disabling animations works as expected (first and last value). But when backgrounding the app it only emits the first value. So this is difficult behavior that Xiaomi devices create with animations.

2022-07-26 08:59:59.918 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onEnd
2022-07-26 09:00:00.909 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onStart
2022-07-26 09:00:00.910 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onUpdate 5.0
2022-07-26 09:00:00.923 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onUpdate 10.0
2022-07-26 09:00:00.927 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onEnd
2022-07-26 09:00:01.912 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onStart
2022-07-26 09:00:01.913 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onUpdate 5.0
2022-07-26 09:00:02.916 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onCancel
2022-07-26 09:00:02.916 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onEnd
2022-07-26 09:00:02.917 13259-13259/com.mapbox.example.hellocar I/kyle_debug: onStart
SamuelBrucksch commented 2 years ago

Hi @kmadsen

great analysis. However i would not expect Xiaomi to fix this in a timely manner. Could you please check if there are other ways on how to fix or at least workaround this?

TomTom for example does not seem to rely on Animators. And we also tried the not yet so well known SDK from General Magic too, that also works without any issues.

I don't have a Xiaomi device myself, so I unfortunately can't test your sample project.

kmadsen commented 2 years ago

great analysis. However i would not expect Xiaomi to fix this in a timely manner. Could you please check if there are other ways on how to fix or at least workaround this?

Am investigating possible workarounds. The ValueAnimator uses the Choreographer, and the Mapbox SDK relies on the Choreographer for not just animations, but also map rendering.

I'm finding that, Xiaomi will not post calls made to Choreographer.getInstance().postFrameCallback when the app is backgrounded. When I'm attempting to debug the source of Choreographer on a Xiaomi device, the source code is not the same as a Pixel on the same Android version. MIUI has a custom implementation, and it is possible that the Xiaomi team has not been optimizing for Android Auto much yet. If Android Auto gets to be a super popular framework, how would Xiaomi support animations with this behavior 🤔 ?

A Mapbox solution seems to require a migration off of the Choreographer and that would take careful planning. Building a new animation and rendering framework for AA is also, not a quick fix.

yunikkk commented 2 years ago

I'm finding that, Xiaomi will not post calls made to Choreographer.getInstance().postFrameCallback when the app is backgrounded.

@kmadsen so map rendering is fully broken and not only animations, right? Even manual camera updates won't work if Choreographer is paused/disposed. Assume Xiaomi just hadn't count on Android Auto usecases and should fix this on their end. Wonder if there are tricky hacks to reenable Choreographer...

kmadsen commented 2 years ago

so map rendering is fully broken and not only animations, right?

@yunikkk Wait.. the render thread is still working. The reason is because the MapboxRenderThread is using a background thread. This will work for animations!

Here is an animator that will continue to work even when the app is backgrounded. The Xiaomi device is killing main thread Choreographer. Nice, this is a manageable work-around

https://user-images.githubusercontent.com/3021882/182428402-eb95b093-bcef-4274-962c-aae65fe29853.mov

class LogAnimation(
    val duration: Long
): Choreographer.FrameCallback {
    private var startTime = 0L
    private var isRunning = false
    private var handlerThread: HandlerThread? = null
    private var handler: Handler? = null

    fun start() {
        isRunning = true
        startTime = System.nanoTime()
        handlerThread = HandlerThread(HANDLE_THREAD_NAME, THREAD_PRIORITY_DISPLAY).apply {
            start()
            handler = Handler(this.looper)
        }
        post {
            Choreographer.getInstance().postFrameCallback(this)
        }
        Log.i("animation_debug", "LogAnimation onStart")
    }

    private fun post(task: () -> Unit) {
        handler?.let {
            val message = Message.obtain(it, task)
            message.obj = EVENT
            it.sendMessageDelayed(message, 0)
        } ?: logW("animation_debug", "Animation thread was not started, ignoring event")
    }

    fun cancel() {
        handler?.removeCallbacksAndMessages(EVENT)
        handlerThread?.quitSafely()
        handler = null
        if (isRunning) {
            Log.i("animation_debug", "LogAnimation onCancel")
        }
        isRunning = false
    }

    @WorkerThread
    override fun doFrame(frameTimeNanos: Long) {
        val timeDiff = (frameTimeNanos - startTime) / 1000000.0
        if (isRunning) {
            if (timeDiff >= duration) {
                Log.i("animation_debug", "LogAnimation onCompleted $timeDiff")
                isRunning = false
            } else {
                Choreographer.getInstance().postFrameCallback(this@LogAnimation)
                Log.i("animation_debug", "LogAnimation onUpdate $timeDiff")
            }
        }
    }

    companion object {
        private const val HANDLE_THREAD_NAME = "animation_thread"
        private val EVENT: Any = Object()
    }
}
SamuelBrucksch commented 2 years ago

Great progress. Let me know once there is a snapshot or beta version with the workaround implemented, so we can try it in our app.

rychuelektryk commented 2 years ago

Hi, great investigation. Any news?

kmadsen commented 2 years ago

This will take some time. It is an odd behavior from Xiaomi and Android Auto, to require animations to be started from a background thread.

There are some assumptions that animations are started from the main thread, and we use android animator framework for location and camera animations.

SamuelBrucksch commented 2 years ago

Hi @kmadsen

can you please provide a rough estimate when this will be fixed? We are losing more and more users due to this.

kiryldz commented 2 years ago

Hi @kmadsen

can you please provide a rough estimate when this will be fixed? We are losing more and more users due to this.

@SamuelBrucksch I've drafted implementation to allow using background thread for animations here. Next step is to incorporate that into AA + Nav SDK if needed.

Rough optimistic estimate: v10.9.0-beta.1 Maps release, happening in 3 weeks.

SamuelBrucksch commented 2 years ago

Ok that sounds great. Please let me know as soon as there is a snapshot version we can use for testing. We only use Mapbox Maps and not the AA / Nav SDK, so once the change is in mapbox we can already test this.

kiryldz commented 2 years ago

@SamuelBrucksch you could try 10.8.0-beta.1-MAPSAND-395-introduce-runtime-option-to-run-animators-on-non-main-thread-2dcb37457-SNAPSHOT, just add additional mirror as described in https://github.com/mapbox/mapbox-maps-android/blob/main/DEVELOPING.md#working-with-snapshots.

SamuelBrucksch commented 2 years ago

I will, is there anything we have to do in our code too? In the PR i saw that you can now switch between background and main runner. Is that done automatically or do I have to switch myself for certain devices?

kiryldz commented 2 years ago

I will, is there anything we have to do in our code too? In the PR i saw that you can now switch between background and main runner. Is that done automatically or do I have to switch myself for certain devices?

That snapshot provided above does not yet have AA related code that @kmadsen added so everything should be enabled from your end for now.

SamuelBrucksch commented 2 years ago

Ok so if we notice, that we have some problematic phones like Xiaomi on Android 12+, i just have to call AnimationThreadController.useBackgroundThread() before initializing mapbox? Or is there anything else i have to do?

SamuelBrucksch commented 2 years ago

No matter what i try, i always end up with this exception:

2022-09-02 10:25:52.380 14090-14181/? E/AndroidRuntime: FATAL EXCEPTION: MapboxAnimThread
    Process: com.iternio.abrpapp, PID: 14090
    java.lang.RuntimeException: Function 'postOnAnimatorThread' could not be used from non-main thread when 'useBackgroundThread()' was not called beforehand!
        at com.mapbox.maps.threading.AnimationThreadController.postOnAnimatorThread(AnimationThreadController.kt:89)
        at com.mapbox.maps.plugin.animation.animator.CameraAnimator.addListener(CameraAnimator.kt:102)
        at android.animation.AnimatorSet.addAnimationEndListener(AnimatorSet.java:1248)
        at android.animation.AnimatorSet.startAnimation(AnimatorSet.java:1189)
        at android.animation.AnimatorSet.start(AnimatorSet.java:729)
        at android.animation.AnimatorSet.start(AnimatorSet.java:684)
        at com.mapbox.maps.plugin.animation.CameraAnimationsPluginImpl$startHighLevelAnimation$2$1.invoke(CameraAnimationsPluginImpl.kt:903)
        at com.mapbox.maps.plugin.animation.CameraAnimationsPluginImpl$startHighLevelAnimation$2$1.invoke(CameraAnimationsPluginImpl.kt:903)
        at com.mapbox.maps.threading.AnimationThreadController.postOnAnimatorThread$lambda-2(AnimationThreadController.kt:85)
        at com.mapbox.maps.threading.AnimationThreadController.$r8$lambda$nE-XMEhVlqLA1g9jOyl1_QBh_Io(Unknown Source:0)
        at com.mapbox.maps.threading.AnimationThreadController$$ExternalSyntheticLambda0.run(Unknown Source:2)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.os.HandlerThread.run(HandlerThread.java:67)

gradle:

    implementation("com.mapbox.maps:android:10.8.0-beta.1-MAPSAND-395-introduce-runtime-option-to-run-animators-on-non-main-thread-2dcb37457-SNAPSHOT")
    implementation('com.mapbox.plugin:maps-locationcomponent:10.8.0-beta.1-MAPSAND-395-introduce-runtime-option-to-run-animators-on-non-main-thread-2dcb37457-SNAPSHOT')

I call AnimationThreadController.useBackgroundThread() in onSurfaceAvailable() before we initialize mapbox, tried it at the end when all is initialized before we actually call any animations but it ended up in the same result. Any advice @kiryldz ?

The error only happens if i actually call useBackgroundThread.

kiryldz commented 2 years ago

@SamuelBrucksch - if you have some preconditions like (AA + Xiaomi + Android 12+) - then better better enable that for this use-case only. Additionally I'd advise to run useBackgroundThread() only when going to background on device (locking the screen) and use useMainThread() everywhere else.

About the exception - I did publish latest snapshot 10.8.0-beta.1-MAPSAND-395-introduce-runtime-option-to-run-animators-on-non-main-thread-6d5eab9d4-SNAPSHOT based on this PR, hopefully it should fix it. Also you could take a look in the same PR how Kyle implemented enabling background animation thread for AA+Xiaomi case only when going to background and then enabling main animation thread again when returning to the foreground.

SamuelBrucksch commented 2 years ago

Thanks @kiryldz it seems to work now, tried it on a non Xiaomi phone with background always on. However it seems to have some hickups in the animator. Please check the video below

https://user-images.githubusercontent.com/8776268/188110647-72d25b05-4390-478b-b56d-c848664b5ed8.mp4

Is that something than can also be fixed easily? Because those jumps are quite distracting.

kiryldz commented 2 years ago

Thanks @kiryldz it seems to work now, tried it on a non Xiaomi phone with background always on. However it seems to have some hickups in the animator. Please check the video below

PXL_20220902_093231282.mp4 Is that something than can also be fixed easily? Because those jumps are quite distracting.

Well, it could be tonns of things...

  1. Are you using ViewportPlugin?
  2. Could you please enable CameraAnimationsPlugin.debugMode and take a look at the logs?