Skip to content
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

Prevent crash on alarms going off with a different user active #886

Merged
merged 1 commit into from
May 29, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.annotation.AnyThread;
import android.support.annotation.MainThread;
Expand Down Expand Up @@ -52,6 +55,7 @@ public abstract class CycledLeScanner {
// avoid doing too many scans in a limited time on Android 7.0 or because we are capable of
// multiple detections. If true, it indicates scanning needs to be stopped when we finish.
private boolean mScanningLeftOn = false;
private BroadcastReceiver mCancelAlarmOnUserSwitchBroadcastReceiver = null;

protected long mBetweenScanPeriod;

Expand Down Expand Up @@ -260,7 +264,6 @@ public void destroy() {

// Remove any postDelayed Runnables queued for the next scan cycle
mHandler.removeCallbacksAndMessages(null);

// We cannot quit the thread used by the handler until queued Runnables have been processed,
// because the handler is what stops scanning, and we do not want scanning left on.
// So we stop the thread using the handler, so we make sure it happens after all other
Expand All @@ -273,6 +276,7 @@ public void run() {
mScanThread.quit();
}
});
cleanupCancelAlarmOnUserSwitch();
}

protected abstract void stopScan();
Expand Down Expand Up @@ -484,12 +488,37 @@ protected void setWakeUpAlarm() {
if (milliseconds < mScanPeriod) {
milliseconds = mScanPeriod;
}

AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + milliseconds, getWakeUpOperation());
LogManager.d(TAG, "Set a wakeup alarm to go off in %s ms: %s", milliseconds, getWakeUpOperation());
cancelAlarmOnUserSwitch();
}

// Added to prevent crash on switching users. See #876
protected void cancelAlarmOnUserSwitch() {
if (mCancelAlarmOnUserSwitchBroadcastReceiver == null) {
IntentFilter filter = new IntentFilter();
filter.addAction( Intent.ACTION_USER_BACKGROUND );
filter.addAction( Intent.ACTION_USER_FOREGROUND );

mCancelAlarmOnUserSwitchBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
LogManager.w(TAG, "User switch detected. Cancelling alarm to prevent potential crash.");
cancelWakeUpAlarm();
}
};
mContext.registerReceiver(mCancelAlarmOnUserSwitchBroadcastReceiver, filter);
}
}
protected void cleanupCancelAlarmOnUserSwitch() {
if (mCancelAlarmOnUserSwitchBroadcastReceiver != null) {
mContext.unregisterReceiver(mCancelAlarmOnUserSwitchBroadcastReceiver);
mCancelAlarmOnUserSwitchBroadcastReceiver = null;
}
}


protected PendingIntent getWakeUpOperation() {
if (mWakeUpOperation == null) {
Intent wakeupIntent = new Intent(mContext, StartupBroadcastReceiver.class);
Expand Down