Let LockManager only lock current, not future process

This fixes a bug on Android 8
where the AlarmManager would re-start a killed BriarService.
Then the LockManager lingers around locked and causes an ANR on Android 8.x when the user comes back to it.
This commit is contained in:
Torsten Grote
2021-02-19 10:42:43 -03:00
parent a04b512497
commit a546fecc01
4 changed files with 22 additions and 10 deletions

View File

@@ -46,6 +46,7 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.os.Process.myPid;
import static androidx.core.app.NotificationCompat.VISIBILITY_SECRET; import static androidx.core.app.NotificationCompat.VISIBILITY_SECRET;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
@@ -58,6 +59,7 @@ import static org.briarproject.briar.api.android.AndroidNotificationManager.FAIL
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_NOTIFICATION_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_NOTIFICATION_ID;
import static org.briarproject.briar.api.android.LockManager.ACTION_LOCK; import static org.briarproject.briar.api.android.LockManager.ACTION_LOCK;
import static org.briarproject.briar.api.android.LockManager.EXTRA_PID;
public class BriarService extends Service { public class BriarService extends Service {
@@ -202,7 +204,12 @@ public class BriarService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_LOCK.equals(intent.getAction())) { if (ACTION_LOCK.equals(intent.getAction())) {
lockManager.setLocked(true); int pid = intent.getIntExtra(EXTRA_PID, -1);
if (pid == myPid()) lockManager.setLocked(true);
else if (LOG.isLoggable(WARNING)) {
LOG.warning("Tried to lock process " + pid + " but this is " +
myPid());
}
} }
return START_NOT_STICKY; // Don't restart automatically if killed return START_NOT_STICKY; // Don't restart automatically if killed
} }

View File

@@ -32,8 +32,10 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.app.PendingIntent.getService; import static android.app.PendingIntent.getService;
import static android.content.Context.ALARM_SERVICE; import static android.content.Context.ALARM_SERVICE;
import static android.os.Process.myPid;
import static android.os.SystemClock.elapsedRealtime; import static android.os.SystemClock.elapsedRealtime;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
@@ -75,23 +77,25 @@ public class LockManagerImpl implements LockManager, Service, EventListener {
LockManagerImpl(Application app, SettingsManager settingsManager, LockManagerImpl(Application app, SettingsManager settingsManager,
AndroidNotificationManager notificationManager, AndroidNotificationManager notificationManager,
@DatabaseExecutor Executor dbExecutor) { @DatabaseExecutor Executor dbExecutor) {
this.appContext = app.getApplicationContext(); appContext = app.getApplicationContext();
this.settingsManager = settingsManager; this.settingsManager = settingsManager;
this.notificationManager = notificationManager; this.notificationManager = notificationManager;
this.dbExecutor = dbExecutor; this.dbExecutor = dbExecutor;
this.alarmManager = alarmManager =
(AlarmManager) appContext.getSystemService(ALARM_SERVICE); (AlarmManager) appContext.getSystemService(ALARM_SERVICE);
Intent i = Intent i =
new Intent(ACTION_LOCK, null, appContext, BriarService.class); new Intent(ACTION_LOCK, null, appContext, BriarService.class);
this.lockIntent = getService(appContext, 0, i, 0); i.putExtra(EXTRA_PID, myPid());
this.timeoutNever = Integer.valueOf( // When not using FLAG_UPDATE_CURRENT, the intent might have no extras
lockIntent = getService(appContext, 0, i, FLAG_UPDATE_CURRENT);
timeoutNever = Integer.parseInt(
appContext.getString(R.string.pref_lock_timeout_value_never)); appContext.getString(R.string.pref_lock_timeout_value_never));
this.timeoutDefault = Integer.valueOf( timeoutDefault = Integer.parseInt(
appContext.getString(R.string.pref_lock_timeout_value_default)); appContext.getString(R.string.pref_lock_timeout_value_default));
this.timeoutMinutes = timeoutNever; timeoutMinutes = timeoutNever;
// setting this in the constructor makes #getValue() @NonNull // setting this in the constructor makes #getValue() @NonNull
this.lockable.setValue(false); lockable.setValue(false);
} }
@Override @Override
@@ -148,7 +152,7 @@ public class LockManagerImpl implements LockManager, Service, EventListener {
boolean oldValue = lockable.getValue(); boolean oldValue = lockable.getValue();
boolean newValue = hasScreenLock(appContext) && lockableSetting; boolean newValue = hasScreenLock(appContext) && lockableSetting;
if (oldValue != newValue) { if (oldValue != newValue) {
this.lockable.setValue(newValue); lockable.setValue(newValue);
} }
} }

View File

@@ -77,7 +77,7 @@ public class UnlockActivity extends BaseActivity {
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, protected void onActivityResult(int requestCode, int resultCode,
Intent data) { @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_KEYGUARD_UNLOCK) { if (requestCode == REQUEST_KEYGUARD_UNLOCK) {
if (resultCode == RESULT_OK) unlock(); if (resultCode == RESULT_OK) unlock();

View File

@@ -8,6 +8,7 @@ import androidx.lifecycle.LiveData;
public interface LockManager { public interface LockManager {
String ACTION_LOCK = "lock"; String ACTION_LOCK = "lock";
String EXTRA_PID = "PID";
/** /**
* Stops the inactivity timer when the user interacts with the app. * Stops the inactivity timer when the user interacts with the app.