Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

ANR adding a polyline #11440

Closed
RoProducts opened this issue Mar 13, 2018 · 23 comments
Closed

ANR adding a polyline #11440

RoProducts opened this issue Mar 13, 2018 · 23 comments
Labels
Android Mapbox Maps SDK for Android needs information

Comments

@RoProducts
Copy link

**Platform:Android
**Mapbox SDK version:5.5.0

Steps to trigger behavior

  1. Create a SupportMapFragment inside a ViewPager
  2. Add a polyline on the map

Expected behavior

Overlay is displayed and map is responsive

Actual behavior

map freezes

I'm using ANRWatchDog to get the stack trace.

This issue has been reported in #9709 and is marked as resolved. But it seems to appear still.
This was happening even more often when I was not using SupportMapFragment but added a mapView (and its lifecycle) to a android.support.v4.app.Fragment programmatically. Using SupportMapFragment seemed to have solved it, but now I faced it again.

Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Apollo Dispatcher (state = TIMED_WAITING)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
at java.lang.reflect.Method.invoke(Native Method)
at android.app.ActivityThread.main(ActivityThread.java:6692)
at android.os.Looper.loop(Looper.java:136)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.MessageQueue.nativePollOnce(Native Method)
at com.mapbox.mapboxsdk.maps.NativeMapView.onMapChanged(NativeMapView.java:862)
at com.mapbox.mapboxsdk.maps.MapView.onMapChange(MapView.java:575)
at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapChanged(MapView.java:1060)
at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapReady(MapView.java:1075)
at ch.jespr.jespr.ui.fragment.MapboxRaceFragment.onMapReady(MapboxRaceFragment.java:129)
at ch.jespr.jespr.ui.overlay.OverlayManager.addRace(OverlayManager.java:377)
at com.mapbox.mapboxsdk.maps.MapboxMap.addPolyline(MapboxMap.java:1312)
at com.mapbox.mapboxsdk.maps.AnnotationManager.addPolyline(AnnotationManager.java:244)
at com.mapbox.mapboxsdk.maps.PolylineContainer.addBy(PolylineContainer.java:31)
at com.mapbox.mapboxsdk.maps.NativeMapView.addPolyline(NativeMapView.java:404)
at com.mapbox.mapboxsdk.maps.NativeMapView.nativeAddPolylines(Native Method)
at com.mapbox.mapboxsdk.maps.NativeMapView.onMapChanged(NativeMapView.java:862)
at com.mapbox.mapboxsdk.maps.MapView.onMapChange(MapView.java:575)
at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapChanged(MapView.java:1065)
at com.mapbox.mapboxsdk.maps.MapboxMap.onUpdateRegionChange(MapboxMap.java:191)
at com.mapbox.mapboxsdk.maps.AnnotationManager.update(AnnotationManager.java:90)
at com.mapbox.mapboxsdk.annotations.MarkerViewManager.update(MarkerViewManager.java:471)
at com.mapbox.mapboxsdk.annotations.MarkerViewManager.invalidateViewMarkersInVisibleRegion(MarkerViewManager.java:485)
at com.mapbox.mapboxsdk.maps.MapboxMap.getMarkerViewsInRect(MapboxMap.java:1274)
at com.mapbox.mapboxsdk.maps.AnnotationManager.getMarkerViewsInRect(AnnotationManager.java:208)
at com.mapbox.mapboxsdk.maps.MarkerContainer.obtainViewsIn(MarkerContainer.java:171)
at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations(NativeMapView.java:471)
at com.mapbox.mapboxsdk.maps.NativeMapView.nativeQueryPointAnnotations(Native Method)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main (state = RUNNABLE)
com.github.anrwatchdog.ANRError: Application Not Responding

@LukasPaczos LukasPaczos added the Android Mapbox Maps SDK for Android label Mar 13, 2018
@LukasPaczos
Copy link
Member

Thanks for reaching out @RoProducts.
Using a map in the ViewPager isn't a completely supported use-case.
That said you could:

  • ensure, that when using a Fragment (not SupportMapFragment), MapView#onDestroy is called from fragment's #onDestroyView
  • ensure, that polyline is added to the map from the main thread
  • use the map in a TextureView mode (by setting a flag in XML or passing it with MapboxMapOptions)

Let us know if any of the above helps.

@RoProducts
Copy link
Author

Thank you, unfortunately these hints do not resolve the issue, still happening occasionally.

Why is ViewPager not completely supported ?

@LukasPaczos
Copy link
Member

We are currently using GLSurfaceView to render the map which "makes a hole" in the view hierarchy to render the contents. Per official documentation, this type of view shouldn't be manipulated once initialized and that's what ViewPager is basically doing, it's trying to animate that surface and change its position.

Tagging @tobrun here for more context.

@tobrun
Copy link
Member

tobrun commented Mar 14, 2018

@RoProducts could you add some code to this issue or provide us with a minimal reproducible example?

@RoProducts
Copy link
Author

RoProducts commented Mar 15, 2018

Sure. Actually this is happening also outside the ViewPager after a standard fragment transaction.

I'm having an activity in which a (race) setup is done in several steps. The last step is to show the race on the map. For this I'm extending SupportMapFragment. I'm creating the Fragment this way :

MapboxMapOptions options = new MapboxMapOptions();
                    options.styleUrl(Style.OUTDOORS);
                    options.camera(new CameraPosition.Builder()
                            .target(lastLocation.getLocation())
                            .zoom(12)
                            .build());

                    raceFragment = MapboxRaceFragment.newInstance(options);

                    raceFragment.getMapAsync(new OnMapReadyCallback() {
                        @Override
                        public void onMapReady(MapboxMap mapboxMap) {

                            raceFragment.onMapReady(mapboxMap);
                        }
                    });

In onCreateView of the fragment I'm getting the MapView from SupportMapFragment and add it to the Framelayout of my layout :

 @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final MapView mapView = (MapView) super.onCreateView(inflater, container, savedInstanceState);

        final View view = inflater.inflate(R.layout.fragment_race_mapbox, null);

        FrameLayout frameLayout = view.findViewById(R.id.map_view_container);
        frameLayout.addView(mapView);

        [...]

        return view;
    }

The lifecycle of the map is handled by SupportMapFragment then.

The actual issue happens "onMapReady" when adding the "race" (a polyline and two markers) to the mapview :

    public void onMapReady(final MapboxMap mapboxMap){

        log("race fragment map onMapReady");
        mapboxMap.getUiSettings().setLogoEnabled(false);
        mapboxMap.getUiSettings().setAttributionEnabled(false);
        mMap = mapboxMap;

        if (mapboxMap.getCameraPosition().target == null || mapboxMap.getCameraPosition().target.getLatitude() == 0) {
            log("race fragment need to acquire");

            if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ((JesprActivity) getActivity()).permissionNecessary(Manifest.permission.ACCESS_FINE_LOCATION, JesprActivity.PermissionIntent.MAP))) {
                log("has location permission");
                useLastKnownLocationAndAcquire();
            }
        }

        getOverlayManager().addMapMovementListener();


//        getOverlayManager().addRace(race, true, true);
        //there are still issues here :-( // at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations(NativeMapView.java:471)

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {

                if(race != null) {
                    getOverlayManager().addRace(race,true, true);
                }
            }
        });
    }

addRace does the following :

  /**
     * add a race to this map
     * consisting in adding a polyline containing the locations of the race
     * if @param addRaceMarker adding a marker at start and finish
     * if @param centerOnFirstRaceLocation centers the map on the first location of the race
     * @param race the race
     * @param addRaceMarker if to add markers at start and finish
     * @param centerOnFirstRaceLocation if to center the map on the first location of the race
     */
    public void addRace(final JesprRace race, final boolean addRaceMarker, boolean centerOnFirstRaceLocation){

        if(race == null || race.getRideLocations() == null || race.getRideLocations().size() < 2){
            Log.w(TAG, "race null or not enough locations available");
            return;
        }

        getRacePolylinePoints().clear();

        for(RideLocation location : race.getRideLocations()){
            getRacePolylinePoints().add(location.getLocation());
        }

        racePolyline = getMap().addPolyline(new PolylineOptions()
                .color(ContextCompat.getColor(context, R.color.map_color_race))
                .addAll(getRacePolylinePoints())
                .width(Constants.MAP_POLYLINE_WIDTH));

        if(BuildConfig.DEBUG) {
            Log.i(TAG, "race polyline of " + owner + " added");
        }
        if(addRaceMarker) {

            raceStart = getMap().addMarker(new MarkerViewOptions()
                    .position(race.getRideLocations().get(0).getLocation())
                    .anchor(.5f,.5f)
                    .title(context.getString(R.string.start))
                    .icon(IconFactory.getInstance(context).fromBitmap(getBitmapForDrawableAndTint(ContextCompat.getDrawable(context, R.drawable.ic_flag_black_48dp), R.color.map_color_race_marker)))
            );

            raceDest = getMap().addMarker(new MarkerViewOptions()
                    .position(race.getRideLocations().get(race.getRideLocations().size() - 1).getLocation())
                    .anchor(.5f,.5f)
                    .title(context.getString(R.string.finish))
                    .icon(IconFactory.getInstance(context).fromBitmap(getBitmapForDrawableAndTint(ContextCompat.getDrawable(context, R.drawable.ic_flag_black_48dp), R.color.map_color_race_marker)))
            );
        }

        if(centerOnFirstRaceLocation) {
            getMap().animateCamera(CameraUpdateFactory.newLatLng(getRacePolylinePoints().get(0)));
        }
    }

As described before occasionally this freezes at
com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations(NativeMapView.java:471)
see stacktrace above.
The locations of the race are all valid, none is null or (0,0).

To clarify : I'm using this fragment twice, in the race setup and in a ViewPager environment which is the main screen of this app providing different fragments. The issue is happening in both environments, always after inflating the layout and adding the race onMapReady.

I'm only recently extending SupportMapFragment, this was also happening when defining the mapview in XML in my own layout and handling the mapview lifecyle myself. Initially it seemed to resolve to use SupportMapFragment as I could inflate the fragment for about 10-15 cycles without issues. But some days later it freezed again.

Thank you

@tobrun
Copy link
Member

tobrun commented Mar 15, 2018

@RoProducts It's not advised to extend SupportMapFragment in the way you are doing. MapView is already inflated and added to the layout container, you are readding it which is not allowed. If you want other content in your Fragment besides the basic map you will need to roll your own fragment that extends from Fragment. Feel free to reach out if you hit any other issue but root cause has been identified. Closing.

@tobrun tobrun closed this as completed Mar 15, 2018
@RoProducts
Copy link
Author

RoProducts commented Mar 15, 2018

I do not agree. Maybe you missed the last paragraph :

I'm only recently extending SupportMapFragment, this was also happening when defining the mapview in XML in my own layout and handling the mapview lifecyle myself. Initially it seemed to resolve to use SupportMapFragment as I could inflate the fragment for about 10-15 cycles without issues. But some days later it freezed again.

I'm doing this rather unusual way of extending SupportMapFragment only to overcome this issue.

@tobrun
Copy link
Member

tobrun commented Mar 15, 2018

could you point out which line is causing a freeze?

@RoProducts
Copy link
Author

As described before occasionally this freezes at
com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations(NativeMapView.java:471)
see stacktrace above.

@tobrun tobrun reopened this Mar 16, 2018
@RoProducts
Copy link
Author

Fyi : I did not find a way to overcome this issue. I'm using now a LineString in a LineLayer to add my polyline to the map. This is currently working without issues.

@olliSP
Copy link

olliSP commented Mar 27, 2018

I am also struggling with this issue.

I can replicate ANR quite easily with OnePlus3 (API 26) by adding hundreds of Polylines. No ViewPagers or tricks with GLSurfaceView in use. Curiously, Samsung S8 (API 26) works better but eventually ANR is caught also there.

Here are couple of ANR stack traces from ANRWatchDog:

================================================================
com.github.anrwatchdog.ANRError: Application Not Responding
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main (state = RUNNABLE)
: at com.mapbox.mapboxsdk.maps.NativeMapView.nativeQueryPointAnnotations(Native Method)
: at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations(NativeMapView.java:471)
: at com.mapbox.mapboxsdk.maps.MarkerContainer.obtainViewsIn(MarkerContainer.java:171)
: at com.mapbox.mapboxsdk.maps.AnnotationManager.getMarkerViewsInRect(AnnotationManager.java208)
: at com.mapbox.mapboxsdk.maps.MapboxMap.getMarkerViewsInRect(MapboxMap.java:1278)
: at com.mapbox.mapboxsdk.annotations.MarkerViewManager.invalidateViewMarkersInVisibleRegion(MarkerViewManager.java:485)
: at com.mapbox.mapboxsdk.annotations.MarkerViewManager$1.onPreDraw(MarkerViewManager.java:44)
: at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:977)
: at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2368)
: at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1410)
: at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6834)
: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
: at android.view.Choreographer.doCallbacks(Choreographer.java:778)
: at android.view.Choreographer.doFrame(Choreographer.java:713)
: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
: at android.os.Handler.handleCallback(Handler.java:789)
: at android.os.Handler.dispatchMessage(Handler.java:98)
: at android.os.Looper.loop(Looper.java:164)
: at android.app.ActivityThread.main(ActivityThread.java:6809)
: at java.lang.reflect.Method.invoke(Native Method)
: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

================================================================
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main (state = RUNNABLE)
: at com.mapbox.mapboxsdk.maps.NativeMapView.nativeQueryPointAnnotations(Native Method)
: at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations(NativeMapView.java:471)
: at com.mapbox.mapboxsdk.maps.MarkerContainer.obtainViewsIn(MarkerContainer.java:171)
: at com.mapbox.mapboxsdk.maps.AnnotationManager.getMarkerViewsInRect(AnnotationManager.java:208)
: at com.mapbox.mapboxsdk.maps.MapboxMap.getMarkerViewsInRect(MapboxMap.java:1278)
: at com.mapbox.mapboxsdk.annotations.MarkerViewManager.invalidateViewMarkersInVisibleRegion(MarkerViewManager.java:485)
: at com.mapbox.mapboxsdk.annotations.MarkerViewManager.update(MarkerViewManager.java:471)
: at com.mapbox.mapboxsdk.maps.AnnotationManager.update(AnnotationManager.java:90)
: at com.mapbox.mapboxsdk.maps.MapboxMap.onUpdateRegionChange(MapboxMap.java:196)
: at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapChanged(MapView.java:1065)
: at com.mapbox.mapboxsdk.maps.MapView.onMapChange(MapView.java:575)
: at com.mapbox.mapboxsdk.maps.NativeMapView.onMapChanged(NativeMapView.java:862)
: at com.mapbox.mapboxsdk.maps.NativeMapView.nativeAddPolylines(Native Method)
: at com.mapbox.mapboxsdk.maps.NativeMapView.addPolyline(NativeMapView.java:404)
: at com.mapbox.mapboxsdk.maps.PolylineContainer.addBy(PolylineContainer.java:31)
: at com.mapbox.mapboxsdk.maps.AnnotationManager.addPolyline(AnnotationManager.java:244)
: at com.mapbox.mapboxsdk.maps.MapboxMap.addPolyline(MapboxMap.java:1316)

I'm not 100% sure about this, but I recall version 5.3 was working ok.

@hurrba
Copy link

hurrba commented Jul 20, 2018

@tobrun @LukasPaczos any updates on this?

edit: The issue seems to be with the new GLSurfaceView. Forcing mapbox_renderTextureMode="true" has helped.

@deinlandel
Copy link

I keep getting ANRs with mapbox and similar stacktraces. mapbox_renderTextureMode didn't help.

@rohitr308
Copy link

Any updates on this issue. We are getting a lot of ANRs

@cvance
Copy link

cvance commented Aug 28, 2018

@rohitr308 I fixed all of the ANRs we were seeing (related to mapbox) by switching off annotations. I now use SymbolLayers with Geojson sources and have seen an improvement in performance and almost no ANRs.

@rohitr308
Copy link

@cvance Thank you. How do I turn off the annotation? Looks like GeoJson works fine for static locations. How about locations that change constantly?

@cvance
Copy link

cvance commented Aug 28, 2018

You're adding a polyline annotation to the map right? If so try something like this instead.

Source polylineSource = new GeoJsonSource(POLYLINE_SOURCE, Feature.fromGeometry(LineString.fromLngLats(lineString))); map.addSource(polylineSource); Layer polylineLayer = new LineLayer(POLYLINE_LAYER, POLYLINE_SOURCE) .withProperties(PropertyFactory.lineColor(ContextCompat.getColor(context, R.color.navy)), PropertyFactory.lineOpacity(0.9f)); map.addLayer(polylineLayer);

then if you need to change the location. You can do so by keeping a reference to the source but I'd suggest getting it from the map. Then just update the geojson and the layer will automatically update.

GeoJsonSource polylineSource = map.getSourceAs(POLYLINE_SOURCE); polylineSource.setGeoJson(Feature.fromGeometry(LineString.fromLngLats(lineString)));

Someone from Mapbox can correct me if I'm wrong or there is better documentation but I've had success doing it this way.

@jsun-dd
Copy link

jsun-dd commented Aug 30, 2018

@cvance thanks a lot for the above suggestion. A strange thing happens when we add polylines via the above. They appear, then disappear... Not entirely sure why. If we switch to map.addPolyline - then they stay all the time. Might you know what we're running into?

@jsun-dd
Copy link

jsun-dd commented Aug 30, 2018

And an update for Mapbox:

We're getting this same stack trace on SDK 5.5.3. Thinking the cause is likely OOM or such. Will help to know what it might be. We're adding a polygon and a polyline to the map, about 20 of them at a time.
Code looks like below.

 private void addHeatmapRegion(List<LatLng> decodedPolyline, @ColorInt int fillColor) {
        // Draw the polygon with fill color
        PolygonOptions polygonOptions = new PolygonOptions();
        polygonOptions.addAll(decodedPolyline);
        polygonOptions.fillColor(fillColor);
        mapboxMap.addPolygon(polygonOptions);

        // Work around for Mapbox polygon stroke width bug:
        // https://github.com/mapbox/mapbox-gl-native/issues/324, and
        // https://github.com/mapbox/react-native-mapbox-gl/issues/435
        // Draw the border polyline with the same points on top of the polygon.
        PolylineOptions polylineOptions = new PolylineOptions()
                .addAll(decodedPolyline)
                .color(Color.WHITE)
                .width(2f);
        mapboxMap.addPolyline(polylineOptions);
    }

Stacktrace looks like below:

"main" tid=1 Native 
"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 obj=0x744e7580 self=0xac504400
  | sysTid=23790 nice=0 cgrp=default sched=0/0 handle=0xaf3bd534
  | state=S schedstat=( 0 0 0 ) utm=1275 stm=282 core=0 HZ=100
  | stack=0xbe10e000-0xbe110000 stackSize=8MB
  | held mutexes=
  #00  pc 000000000001778c  /system/lib/libc.so (syscall+28)
  #01  pc 000000000004706d  /system/lib/libc.so (_ZL24__pthread_cond_timedwaitP23pthread_cond_internal_tP15pthread_mutex_tbPK8timespec+102)
  #02  pc 000000000030e805  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #03  pc 000000000030ed09  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #04  pc 0000000000256ea1  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #05  pc 00000000002554c5  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #06  pc 000000000025589d  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #07  pc 000000000005b9e7  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #08  pc 000000000006c111  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #09  pc 000000000006c153  /data/app/com.doordash.driverapp-2/lib/arm/libmapbox-gl.so (???)
  #10  pc 0000000000aabab5  /data/app/com.doordash.driverapp-2/oat/arm/base.odex (Java_com_mapbox_mapboxsdk_maps_NativeMapView_nativeQueryPointAnnotations__Landroid_graphics_RectF_2+96)
  at com.mapbox.mapboxsdk.maps.NativeMapView.nativeQueryPointAnnotations (NativeMapView.java)
  at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations (NativeMapView.java:471)
  at com.mapbox.mapboxsdk.maps.MarkerContainer.obtainViewsIn (MarkerContainer.java:171)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.getMarkerViewsInRect (AnnotationManager.java:208)
  at com.mapbox.mapboxsdk.maps.MapboxMap.getMarkerViewsInRect (MapboxMap.java:1275)
  at com.mapbox.mapboxsdk.annotations.MarkerViewManager.invalidateViewMarkersInVisibleRegion (MarkerViewManager.java:485)
  at com.mapbox.mapboxsdk.annotations.MarkerViewManager.update (MarkerViewManager.java:471)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.update (AnnotationManager.java:90)
  at com.mapbox.mapboxsdk.maps.MapboxMap.onUpdateRegionChange (MapboxMap.java:192)
  at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapChanged (MapView.java:1065)
  at com.mapbox.mapboxsdk.maps.MapView.onMapChange (MapView.java:575)
  at com.mapbox.mapboxsdk.maps.NativeMapView.onMapChanged (NativeMapView.java:862)
  at com.mapbox.mapboxsdk.maps.NativeMapView.nativeAddPolylines (NativeMapView.java)
  at com.mapbox.mapboxsdk.maps.NativeMapView.addPolyline (NativeMapView.java:404)
  at com.mapbox.mapboxsdk.maps.PolylineContainer.addBy (PolylineContainer.java:31)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.addPolyline (AnnotationManager.java:244)
  at com.mapbox.mapboxsdk.maps.MapboxMap.addPolyline (MapboxMap.java:1313)
  at com.doordash.driverapp.ui.common.DasherMapFragment.drawPolyLine (DasherMapFragment.java:270)
  at com.doordash.driverapp.ui.common.DasherMapFragment.drawPolyLine (DasherMapFragment.java:280)
  at com.doordash.driverapp.ui.common.DasherMapFragment.redrawMap (DasherMapFragment.java:184)
  at com.doordash.driverapp.ui.onDash.common.map.OnADashMapFragment.redrawMap (OnADashMapFragment.java:119)
  at com.doordash.driverapp.ui.common.DasherMapFragment$1.onNext (DasherMapFragment.java:256)
  at com.doordash.driverapp.ui.common.DasherMapFragment$1.onNext (DasherMapFragment.java:244)
  at rx.observers.SafeSubscriber.onNext (SafeSubscriber.java:134)
  at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call (OperatorObserveOn.java:224)
  at rx.android.schedulers.LooperScheduler$ScheduledAction.run (LooperScheduler.java:107)
  at android.os.Handler.handleCallback (Handler.java:751)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6311)
  at java.lang.reflect.Method.invoke! (Native method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:872)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:762)

@jsun-dd
Copy link

jsun-dd commented Aug 31, 2018

An update on the issue above.

We removed the calls to "addPolyline". And now have ANR in MapboxMap.clear(), and MapboxMap.addPolygon which are all in the same "redrawMap" sequence.

Repro Steps:
It's not a 100% repro ANR. So difficult to nail down.
On Nexus 5, API 23.

  1. Launch Map Activity 1
  2. Destroy Map Activity 1
  3. Launch Map Activity 2
  4. Destroy Map Activity 2
  5. Launch Map Activity 1

Actual Results:
Map will reach ANR in one of the "addPolyline", "clear()", or "addPolygon" calls in one of the maps.

Map 1:
calls the below sequence on 3 triggers:

mapBoxMap.clear();
repeat the following in a loop of about 20x:
mapBoxMap.addPolygon
mapBoxMap.addPolyline

Triggers (occurs 3x total around time of onMapReady) :

  • 1x onMapReady
  • 2x onSuccess - callback from an rxjava Observable on our internal API call.
  1. Map 2:
    calls
    mapboxMap.clear()
    mapboxMap.addPolyline

on 2 triggers:

  • onMapReady - callback from MapBox
  • onSuccess - callback from an rxjava Observable on our internal API call.

We get a mixture of ANRs in "addPolyline", "addPolygon", and "clear()" . Above was one of the "addPolyline" ANRs. Below are the "addPolygon" and "clear()" stack traces.

mapboxMap.addPolygon

"main" tid=1 Native 
"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 obj=0x7513d5b0 self=0xb2604400
  | sysTid=19157 nice=-10 cgrp=default sched=0/0 handle=0xb5512534
  | state=S schedstat=( 0 0 0 ) utm=2881 stm=680 core=1 HZ=100
  | stack=0xbe4a4000-0xbe4a6000 stackSize=8MB
  | held mutexes=
  #00  pc 000000000001780c  /system/lib/libc.so (syscall+28)
  #01  pc 000000000004749d  /system/lib/libc.so (_ZL24__pthread_cond_timedwaitP23pthread_cond_internal_tP15pthread_mutex_tbPK8timespec+102)
  #02  pc 000000000030e805  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #03  pc 000000000030ed09  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #04  pc 0000000000256ea1  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #05  pc 00000000002554c5  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #06  pc 000000000025589d  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #07  pc 000000000005b9e7  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #08  pc 000000000006c111  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #09  pc 000000000006c153  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #10  pc 00000000000caa3d  /data/app/com.doordash.driverapp-1/oat/arm/base.odex (Java_com_mapbox_mapboxsdk_maps_NativeMapView_nativeQueryPointAnnotations__Landroid_graphics_RectF_2+96)
  at com.mapbox.mapboxsdk.maps.NativeMapView.nativeQueryPointAnnotations (NativeMapView.java)
  at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations (NativeMapView.java:471)
  at com.mapbox.mapboxsdk.maps.MarkerContainer.obtainViewsIn (MarkerContainer.java:171)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.getMarkerViewsInRect (AnnotationManager.java:208)
  at com.mapbox.mapboxsdk.maps.MapboxMap.getMarkerViewsInRect (MapboxMap.java:1275)
  at com.mapbox.mapboxsdk.annotations.MarkerViewManager.invalidateViewMarkersInVisibleRegion (MarkerViewManager.java:485)
  at com.mapbox.mapboxsdk.annotations.MarkerViewManager.update (MarkerViewManager.java:471)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.update (AnnotationManager.java:90)
  at com.mapbox.mapboxsdk.maps.MapboxMap.onUpdateRegionChange (MapboxMap.java:192)
  at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapChanged (MapView.java:1065)
  at com.mapbox.mapboxsdk.maps.MapView.onMapChange (MapView.java:575)
  at com.mapbox.mapboxsdk.maps.NativeMapView.onMapChanged (NativeMapView.java:862)
  at com.mapbox.mapboxsdk.maps.NativeMapView.nativeAddPolygons (NativeMapView.java)
  at com.mapbox.mapboxsdk.maps.NativeMapView.addPolygon (NativeMapView.java:419)
  at com.mapbox.mapboxsdk.maps.PolygonContainer.addBy (PolygonContainer.java:31)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.addPolygon (AnnotationManager.java:220)
  at com.mapbox.mapboxsdk.maps.MapboxMap.addPolygon (MapboxMap.java:1344)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment.drawHeatMap (DashboardMapFragment.java:205)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment.redrawMap (DashboardMapFragment.java:166)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment.lambda$observeAvailableTimeSlots$0$DashboardMapFragment (DashboardMapFragment.java:107)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment$$Lambda$0.accept (DashboardMapFragment.java)
  at io.reactivex.internal.observers.LambdaObserver.onNext (LambdaObserver.java:63)
  at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal (ObservableObserveOn.java:200)
  at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run (ObservableObserveOn.java:252)
  at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run (HandlerScheduler.java:109)
  at android.os.Handler.handleCallback (Handler.java:751)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6351)
  at java.lang.reflect.Method.invoke! (Native method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:896)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:786)


mapboxMap.clear()


"main" tid=1 Native 
"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 obj=0x747525c8 self=0xb3a04400
  | sysTid=4297 nice=-10 cgrp=default sched=0/0 handle=0xb6ce7534
  | state=S schedstat=( 97257873676 69669866104 239035 ) utm=8211 stm=1514 core=4 HZ=100
  | stack=0xbe5dc000-0xbe5de000 stackSize=8MB
  | held mutexes=
  #00  pc 0000000000017628  /system/lib/libc.so (syscall+28)
  #01  pc 00000000000471ad  /system/lib/libc.so (_ZL24__pthread_cond_timedwaitP23pthread_cond_internal_tP15pthread_mutex_tbPK8timespec+102)
  #02  pc 000000000030e805  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #03  pc 000000000030ed09  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #04  pc 0000000000256ea1  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #05  pc 00000000002554c5  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #06  pc 000000000025589d  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #07  pc 000000000005b9e7  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #08  pc 000000000006c111  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #09  pc 000000000006c153  /data/app/com.doordash.driverapp-1/lib/arm/libmapbox-gl.so (???)
  #10  pc 00000000002c28f5  /data/app/com.doordash.driverapp-1/oat/arm/base.odex (Java_com_mapbox_mapboxsdk_maps_NativeMapView_nativeQueryPointAnnotations__Landroid_graphics_RectF_2+96)
  at com.mapbox.mapboxsdk.maps.NativeMapView.nativeQueryPointAnnotations (NativeMapView.java)
  at com.mapbox.mapboxsdk.maps.NativeMapView.queryPointAnnotations (NativeMapView.java:471)
  at com.mapbox.mapboxsdk.maps.MarkerContainer.obtainViewsIn (MarkerContainer.java:171)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.getMarkerViewsInRect (AnnotationManager.java:208)
  at com.mapbox.mapboxsdk.maps.MapboxMap.getMarkerViewsInRect (MapboxMap.java:1275)
  at com.mapbox.mapboxsdk.annotations.MarkerViewManager.invalidateViewMarkersInVisibleRegion (MarkerViewManager.java:485)
  at com.mapbox.mapboxsdk.annotations.MarkerViewManager.update (MarkerViewManager.java:471)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.update (AnnotationManager.java:90)
  at com.mapbox.mapboxsdk.maps.MapboxMap.onUpdateRegionChange (MapboxMap.java:192)
  at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onMapChanged (MapView.java:1065)
  at com.mapbox.mapboxsdk.maps.MapView.onMapChange (MapView.java:575)
  at com.mapbox.mapboxsdk.maps.NativeMapView.onMapChanged (NativeMapView.java:862)
  at com.mapbox.mapboxsdk.maps.NativeMapView.nativeRemoveAnnotations (NativeMapView.java)
  at com.mapbox.mapboxsdk.maps.NativeMapView.removeAnnotations (NativeMapView.java:464)
  at com.mapbox.mapboxsdk.maps.AnnotationContainer.removeNativeAnnotations (AnnotationContainer.java:83)
  at com.mapbox.mapboxsdk.maps.AnnotationContainer.removeAll (AnnotationContainer.java:76)
  at com.mapbox.mapboxsdk.maps.AnnotationManager.removeAnnotations (AnnotationManager.java:165)
  at com.mapbox.mapboxsdk.maps.MapboxMap.clear (MapboxMap.java:1441)
  at com.doordash.driverapp.ui.common.DasherMapFragment.redrawMap (DasherMapFragment.java:180)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment.redrawMap (DashboardMapFragment.java:162)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment.lambda$observeAvailableTimeSlots$0$DashboardMapFragment (DashboardMapFragment.java:107)
  at com.doordash.driverapp.ui.dashboard.DashboardMapFragment$$Lambda$0.accept (DashboardMapFragment.java)
  at io.reactivex.internal.observers.LambdaObserver.onNext (LambdaObserver.java:63)
  at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal (ObservableObserveOn.java:200)
  at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run (ObservableObserveOn.java:252)
  at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run (HandlerScheduler.java:109)
  at android.os.Handler.handleCallback (Handler.java:751)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6349)
  at java.lang.reflect.Method.invoke! (Native method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:893)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:783)

@tobrun
Copy link
Member

tobrun commented Aug 31, 2018

@jsun-dd thanks for the detailed write up, been trying my best to reproduce with provided code,
ended up with testing with the following:

public class SimpleMapActivity extends AppCompatActivity {

  private MapView mapView;
  private final Handler handler = new Handler();
  private final Random random = new Random();

  private final Runnable runnable = new Runnable() {
    @Override
    public void run() {
      mapboxMap.clear();
      addRandomStuff();
      handler.postDelayed(this, 250);
    }
  };

  private MapboxMap mapboxMap;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map_simple);
    mapView = (MapView) findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(mapboxMap -> {
      this.mapboxMap = mapboxMap;
      loopRandomStuff();
    });
  }

  private void loopRandomStuff() {
    handler.post(runnable);
  }

  private void addRandomStuff() {
    for (int i = 0; i < random.nextInt() + 20; i++) {
      List<LatLng> latLngs = new ArrayList<>();
      for (int j = 0; j < random.nextInt() + 10; j++) {
        latLngs.add(createRandomLatLng());
      }
      addHeatmapRegion(latLngs, Color.argb(255, random.nextInt(255), random.nextInt(255), random.nextInt(255)));
    }
  }

  private void addHeatmapRegion(List<LatLng> decodedPolyline, @ColorInt int fillColor) {
    // Draw the polygon with fill color
    PolygonOptions polygonOptions = new PolygonOptions();
    polygonOptions.addAll(decodedPolyline);
    polygonOptions.fillColor(fillColor);
    mapboxMap.addPolygon(polygonOptions);

    // Work around for Mapbox polygon stroke width bug:
    // https://github.com/mapbox/mapbox-gl-native/issues/324, and
    // https://github.com/mapbox/react-native-mapbox-gl/issues/435
    // Draw the border polyline with the same points on top of the polygon.
    PolylineOptions polylineOptions = new PolylineOptions()
      .addAll(decodedPolyline)
      .color(Color.WHITE)
      .width(2f);
    mapboxMap.addPolyline(polylineOptions);
  }


  private LatLng createRandomLatLng() {
    return new LatLng((random.nextDouble() * -180.0) + 90.0,
      (random.nextDouble() * -360.0) + 180.0);
  }
... // other lifecycle methods

As seen in gif below this is not resulting in any ANR:

ezgif com-video-to-gif 80

I'm not able to fully replicate your setup, would you be able to do the following tests? or provide a minimal reproducible example?

  • print out the hashcode of the mapboxMap your are calling addPolyline/Polygon and clear methods on. It could be that you are retaining an old instance of this object. Please check if this hashcode at point of an ANR matches the hashcode of the mapboxmap received through OnMapReady.
  • validate that all your mapboxMap invocations are happening on the UiThread? We have some checks in place to validate this already but we might have missed some in the API. This could lead to ANR issues as you are running into.

re. #11440 (comment), we are tracking this issue in #11877.

@jsun-dd
Copy link

jsun-dd commented Sep 3, 2018

@tobrun thanks a lot for the update. I can get you a setup that more closely reproduces our code. I'll try first your tips, and also upgrading to Mapbox 6+, as that might be a much better use of time for simply getting us to a better state. Will update again soon.

@tobrun
Copy link
Member

tobrun commented Jan 4, 2019

Annotations are deprecated and are being replaced by the annotations plugin.

@tobrun tobrun closed this as completed Jan 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android needs information
Projects
None yet
Development

No branches or pull requests

9 participants