Open shankari opened 9 months ago
I dug into the airplane mode a bit and wanted to get my findings out before we get swept away in the GSA project. I did not have enough time (nor a Samsung/OnePlus) to do tests with physical phones, so I did all of my work in a pixel emulator. I also didn't see an internal issue for this, I'm not sure where it is exactly, so I didn't get the chance to look at any logs.
I did 3 types of tests to see how airplane mode would affect the FSM. All of these tests involved me broadcasting a custom intent that would allow me to view the state of the FSM at any given time.
Control
For this test, I did a fresh install of the app, and got myself to the home screen. From there I retrieved the state, in which it was local.state.waiting_for_trip_start
. I then went to the Android home screen to put the app in the background, and turned on airplane mode. I then pinged for the state and I got local.state.waiting_for_trip_start
. I then turn off airplane mode, and went back into the app, and checked the state once again, being local.state.waiting_for_trip_start
.
Simulate trip trying to start
This test I wanted to focus on seeing what would happen if we tried to exit our geofence while in airplane mode. I've read conflicting things online about how some manufacturers may or may not allow geofence services to still work in airplane mode, hence why I tried it. The experiment followed the same suit as above until I got into airplane mode, which is when I broadcasted local.transition.exited_geofence
. After the app spins its wheels, we end up being stuck in the local.state.start
state, as a result of the error below. Turning off airplane mode and entering the app again does not seem to fix our state by itself.
02-01 13:25:04.532 13981 13981 I SensorControlBackgroundChecker: location settings are invalid, generating tracking
error and visible notification
Simulate performPeriodicActivity()
I also thought I'd try to see what happens if performPeriodicActivity
was called and the foreground service tries to restart itself. I did the exact same thing as I did in step 2, except I broadcasted for performPeriodicActivity
to be called instead of local.transition.exited_geofence
. We end up getting the same results, being that we get stuck in local.state.start
.
I know it was mentioned above that we could register for that airplane mode callback and restart the FSM, and I think thats a great idea. I have not been able to test it, however, as I am having trouble editing the AndroidManifest
, so in turn I can't register any BroadcastReceiver
to that event. Each time I try to run the app using npx cordova emulate android
the AndroidManifest
gets rebuilt. I definitely would appreciate some help on figuring out how I can write to AndroidManifest
without it getting overwritten so I can try this out.
Another alternative method that we can do instead is to check in TripDiaryStateMachineService.handleAction
if airplane mode is turned on. If it is turned on, then we can ignore any action request or automatically change the action request to something like local.state.waiting_for_trip_start
to prevent the state from being stuck in limbo.
Please let me know what you think @shankari, I would appreciate any feedback you may have.
@louisg1337 You can edit the AndroidManifest.xml
by changing the plugin.xml
.
AndroidManifest.xml
is updated) and then change the codeAndroidManifest.xml
while working on the code with a visual studio plugin https://marketplace.visualstudio.com/items?itemName=adelphes.android-dev-ext (note that you will need to open the build.gradle
file in platforms/android
gradelew build
manually from platforms/android
to build the apk.Let us know which works best!
Thank you for helping me figure out the AndroidManfiest
issue, I appreciate it! I managed to get together a draft PR with both the airplane mode and foreground service disappearance fixes. I decided to combine the two into one PR to 1) get these changes out faster and 2) because I had to edit the same file for both issues.
For the airplane mode change, I implemented the registering for the airplane mode receiver idea. I did run into an issue however, which is that apparently, with the new background execution limits, an app cannot register for implicit intents in the AndroidManifest
, besides for these exceptions. The docs on this specific issue can be found here. In that case, I had to instead register the the intent via Context.registerReceiver()
as specified by the docs. I did this in DataCollectionPlugin.pluginInitialize()
as I figured that would be a good spot to put it, although let me know if theres a better place.
The rest of the change is straight forward with the app listening for the airplane intent in TripDiaryStateMachineReceiver
, and then restarting the FSM.
To test this I did 3 separate tests which were as follows.
local.state.waiting_for_trip_start
to something different)local.start.state
to local.state.waiting_for_trip_start
.All tests were successful and nothing seemed too weird.
One concern I did have though was that in TripDiaryStateMachineReceiver
when restarting the state all I did was broadcast a transition_initialize
to the FSM. I was wondering if maybe it would be better to use this function as it only restarts the FSM if the state is local.start.state
. I wanted some input to determine if it was better to just always restart the FSM, or only when we are in that weird state.
Please let me know what you think @shankari, thank you!
@louisg1337 thank you for doing this; hopefully it will make the app a lot more stable, at least for people who travel by plane.
Two comments:
initialize
essentially functions (or is intended to function) as a NOP. https://github.com/e-mission/e-mission-data-collection/blob/103b787db3347254488083714d178624ec76092a/src/android/location/TripDiaryStateMachineService.java#L167Once you make that change, I am happy to merge the PR
Sounds great, thank you for the feedback! I just made both changes and they are now pushed to the PR. To also address the first bullet point, yes that is what I observed. Right when you switch to airplane mode the state is still in local.state.waiting_for_trip_start
, but the second the app does anything it switches over to local.start.state
.
Anecdotally, I seem to remember that when I got out of airplane mode, I would frequently miss trips. I do not remember whether the foreground service was missing at the time.
The goals for this issue are to go int and out of airplane mode on both a stock android phone and a custom (Samsung/OnePlus phone) and see what happens under the hood. We can also look at my logs (in the internal issue) and see the FSM state when exiting from airplane mode.
A potential change might be to register for the "leave airplane mode" callback and reset the FSM if needed. As a preliminary step, we can register for the "leave airplane mode" callback and log the state of the FSM and the foreground service at the time.