New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Fix starting Foreground services from the background #2658
base: master
Are you sure you want to change the base?
Conversation
…-fix Fix Zip path traversal vulnerability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code itself looks great on it. Though I have a couple points worth mentioning here -
-
This looks like a fine soultion for the purpose of this hotfix but I think we want to have a more long term strategy here for the next release (2.54). We possibly want to move away from the model of always having a foreground service running with the notification with these new Android restrictions in place. @ctsims I believe this will be a substantial product change for users as they might be accustomed to see the CC logged-in notification. Do you have thoughts on making this change. The trade off here is asking for a new permission to all users (exact alarm) vs retaining the foreground session notification.
-
Have you been able to replicate this bug and verify that this PR actually fixes it ? Since it looks a bit tricky to repro this bug, it would be nice to have the repro steps mentioned in the description of this PR.
@@ -28,7 +28,7 @@ | |||
<uses-permission android:name="android.permission.RECORD_AUDIO" /> | |||
<uses-permission android:name="android.permission.CAMERA" /> | |||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> | |||
|
|||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This permission can be revoked by the user or system at any time and we need to check if the permission is granted before using it otherwise direct user to grant this permission. reference
this.startForeground(NOTIFICATION, notificationBuilder.build()); | ||
} | ||
|
||
private boolean isAppInTheBackground() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ununsed.
@shubham1g5 Yes, it's not that difficult to reproduce, especially when the user is logging in for the first time. So, clearing user data, logging in and immediately sending the app to the background is one way to make it happen. Let me add those steps to the description. |
Hey @shubham1g5
Can you start a spec doc outlining this transition, including the motivations and underlying changes to Android's permissions framework that are making it necessary? It's definitely a very big transition to move to a model where we don't have a persistent service, because the persistent service is the mechanism we use to maintain a persistent in-memory-only footprint for the decrypted database keys without Android killing the process. Without the service, many things could happen which would require the user to re-enter their password constantly, which is something we'd like to actively avoid since most of our users are provided CommCare as the main or sole function of the phone. It's plausible there are new mechanisms we can take advantage of for that purpose, though. We already have it on the docket to explore other ways to manage other sensitive tokens outside of process memory, so we should possibly explore these concepts together. |
Ahh I didn't realise that's the primary reason for the session service. I will see if I can find alternatives here and list them out in another doc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good to me overall except a few comments and I do think this solution will work out for this issue in short term atleast. And I am happy for this to go out as a hotfix but would like QA to test this workflow in detail before we do so.
Although I do think that the better approach here would be to get rid of foreground service altogether instead of adding another permission that user needs to grant with this special request framing.
* running in the background. This method leverages AlarmManager to initiate the Service | ||
*/ | ||
@RequiresApi(api = Build.VERSION_CODES.O) | ||
private void startForegroundServiceWithAlarmManager() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should check for the alarm permission is granted ( canScheduleExactAlarms()
) before scheduling the alarm.
} | ||
} | ||
|
||
// TODO: In addition to scrolling to where CommCare app is, we should highlight the item |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the page this intent send us to not CC specific and user need to locate CC from a list of apps ?
} | ||
|
||
private static boolean shouldRequestSpecialPermission(AppCompatActivity activity, String specialPerm) { | ||
if (!requestingSpecialAppPermission) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what would cause requestingSpecialAppPermission
to be true
here ?
//Send the notification. | ||
this.startForeground(NOTIFICATION, notificationBuilder.build()); | ||
//Send the notification | ||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && CommCareApplication.isAppInBackground()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you been able to repro the crash with the foreground notification here ? I would think that since the foreground service has already started the app will always be in the foreground.
PendingIntent.FLAG_IMMUTABLE); | ||
|
||
AlarmManager alarmmanager = (AlarmManager) getSystemService(ALARM_SERVICE); | ||
alarmmanager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), pendingIntent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should check for canScheduleExactAlarms()
before scheduling this.
Is it also possible to link the firebase crash in the PR description so that we can see how frequent it is to decide whether it should be hotfixed or not ? |
Pausing this for now until we release version 2.54. Changing the base of this PR to |
Summary
This PR resolves a restriction on Android 12+ with starting foreground services while the application is in the background, which is causing ForegroundServiceStartNotAllowedException errors. This is particularly relevant to the CommCare Session, as it needs to remain alive even when the app goes to the background for some time. There are 2 places where this happens:
Steps to reproduce the error
Stacktrace
Product Description
Safety Assurance
Automated test coverage
Safety story