Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#1297 closed defect/bug (fixed)

Navit process does not exit cleanly on Android, causing issues on relaunch

Reported by: mvglasow (2) Owned by: cp15
Priority: major Milestone:
Component: port/android Version: git master
Severity: normal Keywords:
Cc: http://wiki.navit-project.org/index.php/user:mvglasow, (2)

Description

It appears that under certain circumstances Navit does not exit cleanly on Android. When launching Navit again, the old process is re-used and the screen does not update correctly. Input is, however, processed correctly.

To reproduce (tested with r6087 as well with several highfive builds):

  1. Make sure you are using the default navit.xml (not a customized one).
  2. Launch Navit and tap the screen to go to the menu.
    1. Select Actions > Town. The Town dialog should appear.
    2. Select Back to map (globe icon). Navit should return to the map.
    3. Return to the menu and select Quit.
  3. Launch Navit again.
    1. Select Actions > Town. The screen will appear frozen, with the Town entry highlighted.
    2. Select Back to map (globe icon). You will now see the Town dialog.
    3. Tap anywhere near the middle of the screen. You will see the main menu.
  4. Kill Navit (by long-pressing Back, if enabled in Developer options, or through App settings).
  5. Relaunch Navit and repeat everything underneath step 2. You will see correct behavior again.

A logcat clearly shows that between tapping Quit and relaunching Navit, the same process ID is used across both instances.

This might be the explanation for #974.

On highfive, I have noticed that the following lines in my navit.xml will prevent this issue from occurring:

		<osd name="profile" enabled="yes" type="button" x="192" y="-222" w="144" h="144" command='
		vehicle.profilename=(
		vehicle.profilename=="car"?"bike":
		(vehicle.profilename=="bike"?"pedestrian":
		"car"));
		osd[@name=="profile"].src=
		(vehicle.profilename=="car" || vehicle.profilename=="bike" || vehicle.profilename=="pedestrian")?"/sdcard/navit/osd/profile_"+vehicle.profilename+"_xxhdpi.png":"/sdcard/navit/osd/profile_unknown_xxhdpi.png"
		' src="/sdcard/navit/osd/profile_unknown_xxhdpi.png"/>
		
		<osd name="my_osd_cmdif_2" h="1" w="1"  update_period="2"  enabled="yes" type="cmd_interface" x="22"  y="832" background_color="#00000000" command='
		osd[@name=="profile"].src=
		(vehicle.profilename=="car" || vehicle.profilename=="car_avoid_tolls" || vehicle.profilename=="bike" || vehicle.profilename=="pedestrian" || vehicle.profilename=="horse" || vehicle.profilename=="Truck")?"/sdcard/navit/osd/profile_"+vehicle.profilename+"_xxhdpi.png":"/sdcard/navit/osd/profile_unknown_xxhdpi.png"
		'/>

(My intention was to have an OSD button to switch vehicle profiles, though that never worked as intended.)

With these lines in place, Navit exits correctly and behaves correctly on relaunch – at least in current highfive builds (which are based upon SVN builds around New Year's). r6087 crashes with my navit.xml, need to investigate why.

On highfive, messing with the cmd_interface OSD brings the issue back. Tests I carrie out:

  • Setting the button to enabled="no" has no effect.
  • If I set the update_period="60" for the OSD, the issues appear only when I relaunch Navit within 60 seconds of quitting it. If I wait longer than 60 seconds before I relaunch Navit, it behaves correctly.
  • If I set command='' (empty command) for the cmd_interface, the issue is back.
  • Other changes to the command have also caused the issue to return, namely command='osd[@name=="profile"].src="/sdcard/navit/osd/profile_unknown_xxhdpi.png"'.

Apparently running a certain type of OSD command causes Navit to exit cleanly. That seems to depend on the command (as empty commands or certain types of commands don't work), though I have no clear idea of what it is (reading a parameter? reading a certain parameter).

Attachments (1)

navit-r6087-crash.txt (22.0 KB) - added by mvglasow (2) 4 years ago.
Logcat of crash on r6087

Download all attachments as: .zip

Change History (9)

comment:1 Changed 4 years ago by mvglasow (2)

  • Component changed from core to port/android
  • Owner changed from KaZeR to cp15

Changed 4 years ago by mvglasow (2)

Logcat of crash on r6087

comment:2 Changed 4 years ago by mvglasow (2)

The different behavior between HighFive? and r6087 is probably explained by the changes in r6033, which disables catching SIGSEGV on Android. The log shows that Navit crashes with error 11, which is SIGSEGV. Builds prior to r6033 would just terminate silently, which explains the different behavior.

So the whole cmd_interface thing is just a red herring (although quitting Navit should also prevent cmd_interfaces from firing, but that's a separate issue). A case of two bugs seemingly canceling each other out...

So the question is: why is Navit not exiting properly?

comment:3 Changed 4 years ago by tryagain

What Android version do you have on your device? I seem to be unable to reproduce it with r6061 on my Android 4.1.1 tablet. But have seen similar behaviour during development.

Actually, having Quit button on Android is a bad practice.

For discussion and examples of Quit button implementation, look here http://stackoverflow.com/questions/2033914/quitting-an-application-is-that-frowned-upon

We actually seem need the quit button for the following reasons:

1) we expect our application to consume much resources and want to release them by the user's request, not waiting for OS to kill us.

2) we want to do something while the app is in background. Examples are navigation announcement and track recording.

3) we need explicit restart of our app to simplify "select map directory" and configuration backup/restore functions.

First reason probably should be left to OS discretion. At least, other resource consuming apps, games, tend to have no "quit" buttons.

For the second one, we better should give to user some controls to stop these processes manually and separately.

Looks like the best way to fix quit button on Android would be to make it completely unnecessary there...

comment:4 Changed 4 years ago by mvglasow (2)

I'm using Android 4.4.4 (Cyanogenmod 11 M11) on a Nexus S and a OnePlus? One.

I agree with you on the general philosophy of a Quit button – on the long run, we want to get rid of it on Android. However, in order to get that to work cleanly, a few other things would need to happen:

  • First, we need to preserve state information (basically anything that can be set through the UI, such as vehicle profiles, 2D/3D, selected layout, speech on/off etc.) between instances rather than falling back to the defaults in navit.xml. A persistent cache of the route graph would also help.
  • Then we'd need to identify the cases which need an explicit restart, come up with a solution that's in line with Android design principles and implement that.
  • When these things are in place, we can change the way the Navit service runs: by default, we'd start it as a background service and make it a foreground service only when we start routing (destination set). Once the destination is reached and thus cleared, the service would become a background service again. This would tell Android that it's OK to kill Navit when it's not routing but that it should be kept alive when routing is in progress (so that we'd get speech instructions and continue to receive GPS updates). Same goes for other things we want to continue in the background, such as track recording.
  • Finally, we might want to do some cleanup, such as releasing the GPS when Navit is not running as a foreground service and no Navit activity is in the foreground, and re-registering when these conditions change again.

With all these things properly implemented, we could eliminate the Quit button on Android – the OS would take care of this so the user wouldn't have to. And I totally agree that this is the way things should work on Android, since every other app works that way and users are used to that. Requiring users to explicitly quit Navit isn't exactly great user experience.

But... that's a project roughly comparable to HighFive?, which we started some six months ago and which is getting close to a release candidate only now – I'd expect a similar timeframe on this one (since I'm pretty sure something unexpected will happen somewhere and cost us a lot of time).

Until then, I believe we need a clean Quit implementation. I'll look into it – though that doesn't mean we should abandon the idea of a more Android-like way of handling Quit.

comment:5 Changed 4 years ago by mvglasow (2)

Fixed in r6088.

Turns out the fix was a one-liner: instead of calling Activity.finish() in Navit.java simply call Navit.NavitDestroy(). This is a native method which does a simple exit(0), which is the correct way to terminate a native Android app from within.

I'll leave this open until we've decided how to go on about the "big" plan to do things the Android way and get rid of Quit altogether on Android. That should go into a new ticket, maybe even more than one.

comment:6 Changed 4 years ago by kazer

  • Resolution set to fixed
  • Status changed from new to closed

r6132 is currently available in the play store, in the beta channel ( https://play.google.com/apps/testing/org.navitproject.navit ) please reopen if the issue happens again.

comment:7 Changed 4 years ago by tobias schlemmer

I still have the problem on Android 2.3.7 (Cyanogenmod-7.2.0-hero) using 0.5.0+git:44b6fe5

comment:8 Changed 4 years ago by mvglasow (2)

  • Cc http://wiki.navit-project.org/index.php/user:mvglasow (2) added
Note: See TracTickets for help on using tickets.