Skip to content

Commit

Permalink
Don't assume sync()/unsync() method calls are paired.
Browse files Browse the repository at this point in the history
It's possible for them to be called like this:

 .sync()
 .sync()
 .unsync()
 .unsync()

The old code ended up leaking objects because they were registered as
handlers in the first sync() call, the variable containing a reference
to them was overwritten in the second sync() call, and they were never
unregistered. This caused problems.
  • Loading branch information
argosphil committed Sep 9, 2023
1 parent f7ac061 commit 3d577ca
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,32 +156,37 @@ public MediaService(Context ctx, IAsteroidDevice device) {

@Override
public void sync() {
mCtx.getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mVolumeChangeObserver);
try {
mMediaSessionManager = (MediaSessionManager) mCtx.getSystemService(Context.MEDIA_SESSION_SERVICE);
List<MediaController> controllers = mMediaSessionManager.getActiveSessions(new ComponentName(mCtx, NLService.class));
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> {
onActiveSessionsChanged(controllers);
mMediaSessionManager.addOnActiveSessionsChangedListener(this, new ComponentName(mCtx, NLService.class));
});
} catch (SecurityException e) {
Log.w(TAG, "No Notification Access");
if (mMediaSessionManager == null) {
mCtx.getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mVolumeChangeObserver);
try {
mMediaSessionManager = (MediaSessionManager) mCtx.getSystemService(Context.MEDIA_SESSION_SERVICE);
List<MediaController> controllers = mMediaSessionManager.getActiveSessions(new ComponentName(mCtx, NLService.class));
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> {
onActiveSessionsChanged(controllers);
mMediaSessionManager.addOnActiveSessionsChangedListener(this, new ComponentName(mCtx, NLService.class));
});
} catch (SecurityException e) {
Log.w(TAG, "No Notification Access");
}
}
}

@Override
public final void unsync() {
mCtx.getContentResolver().unregisterContentObserver(mVolumeChangeObserver);
if (mMediaSessionManager != null) {
mCtx.getContentResolver().unregisterContentObserver(mVolumeChangeObserver);

if(mMediaSessionManager != null)
mMediaSessionManager.removeOnActiveSessionsChangedListener(this);
mMediaSessionManager = null;
}
if (mMediaController != null) {
try {
mMediaController.unregisterCallback(mMediaCallback);
} catch(IllegalArgumentException ignored) {}
} catch (IllegalArgumentException ignored) {
}
mMediaController = null;
}
mMediaController = null;
}

private void sendVolume(int volume) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,36 @@ public class NotificationService implements IConnectivityService {
public static final String TAG = NotificationService.class.toString();
private final Context mCtx;
private final IAsteroidDevice mDevice;
private final NotificationReceiver mNReceiver;
private NotificationReceiver mNReceiver;

public NotificationService(Context ctx, IAsteroidDevice device) {
this.mDevice = device;
this.mCtx = ctx;
mNReceiver = new NotificationReceiver();
}

@Override
public void sync() {
IntentFilter filter = new IntentFilter();
filter.addAction("org.asteroidos.sync.NOTIFICATION_LISTENER");
mCtx.registerReceiver(mNReceiver, filter);

Intent i = new Intent("org.asteroidos.sync.NOTIFICATION_LISTENER_SERVICE");
i.putExtra("command", "refresh");
mCtx.sendBroadcast(i);
if (mNReceiver == null) {
IntentFilter filter = new IntentFilter();
filter.addAction("org.asteroidos.sync.NOTIFICATION_LISTENER");
mNReceiver = new NotificationReceiver();
mCtx.registerReceiver(mNReceiver, filter);

Intent i = new Intent("org.asteroidos.sync.NOTIFICATION_LISTENER_SERVICE");
i.putExtra("command", "refresh");
mCtx.sendBroadcast(i);
}
}

@Override
public void unsync() {
try {
mCtx.unregisterReceiver(mNReceiver);
} catch (IllegalArgumentException ignored) {}
if (mNReceiver != null) {
try {
mCtx.unregisterReceiver(mNReceiver);
} catch (IllegalArgumentException ignored) {
}
mNReceiver = null;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,25 @@ public ScreenshotService(Context ctx, IAsteroidDevice device) {

@Override
public void sync() {
mSReceiver = new ScreenshotReqReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("org.asteroidos.sync.SCREENSHOT_REQUEST_LISTENER");
mCtx.registerReceiver(mSReceiver, filter);
if (mSReceiver == null) {
mSReceiver = new ScreenshotReqReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("org.asteroidos.sync.SCREENSHOT_REQUEST_LISTENER");
mCtx.registerReceiver(mSReceiver, filter);

mDownloading = false;
mDownloading = false;
}
}

@Override
public void unsync() {
try {
mCtx.unregisterReceiver(mSReceiver);
} catch (IllegalArgumentException ignored) {}
if (mSReceiver != null) {
try {
mCtx.unregisterReceiver(mSReceiver);
} catch (IllegalArgumentException ignored) {
}
mSReceiver = null;
}
}

private static int bytesToInt(byte[] b) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,27 @@ public SilentModeService(Context con) {

@Override
public final void sync() {
notificationPref = prefs.getBoolean(PREF_RINGER, false);
if (notificationPref == null) {
notificationPref = prefs.getBoolean(PREF_RINGER, false);

if (notificationPref){
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(PREF_ORIG_RINGER, am.getRingerMode());
editor.apply();
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
if (notificationPref) {
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(PREF_ORIG_RINGER, am.getRingerMode());
editor.apply();
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}
}
}

@Override
public final void unsync() {
notificationPref = prefs.getBoolean(PREF_RINGER, false);
if (notificationPref) {
int origRingerMode = prefs.getInt(PREF_ORIG_RINGER, AudioManager.RINGER_MODE_NORMAL);
am.setRingerMode(origRingerMode);
if (notificationPref != null) {
notificationPref = prefs.getBoolean(PREF_RINGER, false);
if (notificationPref) {
int origRingerMode = prefs.getInt(PREF_ORIG_RINGER, AudioManager.RINGER_MODE_NORMAL);
am.setRingerMode(origRingerMode);
}
notificationPref = null;
}
}

Expand Down
54 changes: 30 additions & 24 deletions app/src/main/java/org/asteroidos/sync/connectivity/TimeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,27 @@ public TimeService(Context ctx, IAsteroidDevice device) {

@Override
public final void sync() {
Handler handler = new Handler();
handler.postDelayed(this::updateTime, 500);

// Register a broadcast handler to use for the alarm Intent
// Also listen for TIME_CHANGED and TIMEZONE_CHANGED events
mSReceiver = new TimeSyncReqReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(TIME_SYNC_INTENT);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
mCtx.registerReceiver(mSReceiver, filter);

// register an alarm to sync the time once a day
Intent alarmIntent = new Intent(TIME_SYNC_INTENT);
alarmPendingIntent = PendingIntent.getBroadcast(mCtx, 0, alarmIntent, PendingIntent.FLAG_IMMUTABLE);
alarmMgr = (AlarmManager) mCtx.getSystemService(Context.ALARM_SERVICE);
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
AlarmManager.INTERVAL_DAY, alarmPendingIntent);
if (mSReceiver == null) {
Handler handler = new Handler();
handler.postDelayed(this::updateTime, 500);

// Register a broadcast handler to use for the alarm Intent
// Also listen for TIME_CHANGED and TIMEZONE_CHANGED events
mSReceiver = new TimeSyncReqReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(TIME_SYNC_INTENT);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
mCtx.registerReceiver(mSReceiver, filter);

// register an alarm to sync the time once a day
Intent alarmIntent = new Intent(TIME_SYNC_INTENT);
alarmPendingIntent = PendingIntent.getBroadcast(mCtx, 0, alarmIntent, PendingIntent.FLAG_IMMUTABLE);
alarmMgr = (AlarmManager) mCtx.getSystemService(Context.ALARM_SERVICE);
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
AlarmManager.INTERVAL_DAY, alarmPendingIntent);
}
}

@Override
Expand All @@ -102,11 +104,15 @@ private void updateTime() {
}

public final void unsync() {
try {
mCtx.unregisterReceiver(mSReceiver);
} catch (IllegalArgumentException ignored) {}
if (alarmMgr!= null) {
alarmMgr.cancel(alarmPendingIntent);
if (mSReceiver != null) {
try {
mCtx.unregisterReceiver(mSReceiver);
mSReceiver = null;
} catch (IllegalArgumentException ignored) {
}
if (alarmMgr != null) {
alarmMgr.cancel(alarmPendingIntent);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,32 +90,40 @@ public WeatherService(Context ctx, IAsteroidDevice device) {

@Override
public void sync() {
updateWeather();

// Register a broadcast handler to use for the alarm Intent
mSReceiver = new WeatherSyncReqReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WEATHER_SYNC_INTENT);
mCtx.registerReceiver(mSReceiver, filter);

// Fire update intent every 30 Minutes to update Weather
Intent alarmIntent = new Intent(WEATHER_SYNC_INTENT);
mAlarmPendingIntent = PendingIntent.getBroadcast(mCtx, 0, alarmIntent, PendingIntent.FLAG_IMMUTABLE);
mAlarmMgr = (AlarmManager) mCtx.getSystemService(Context.ALARM_SERVICE);
mAlarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
AlarmManager.INTERVAL_HALF_HOUR, mAlarmPendingIntent);
if (mSReceiver == null) {
updateWeather();

// Register a broadcast handler to use for the alarm Intent
mSReceiver = new WeatherSyncReqReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WEATHER_SYNC_INTENT);

mCtx.registerReceiver(mSReceiver, filter);
// Fire update intent every 30 Minutes to update Weather
Intent alarmIntent = new Intent(WEATHER_SYNC_INTENT);
mAlarmPendingIntent = PendingIntent.getBroadcast(mCtx, 0, alarmIntent, PendingIntent.FLAG_IMMUTABLE);
mAlarmMgr = (AlarmManager) mCtx.getSystemService(Context.ALARM_SERVICE);
mAlarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
AlarmManager.INTERVAL_HALF_HOUR, mAlarmPendingIntent);
}
}

@Override
public void unsync() {
try {
mCtx.unregisterReceiver(mSReceiver);
} catch (IllegalArgumentException ignored) {}
if (mSReceiver != null) {
try {
mCtx.unregisterReceiver(mSReceiver);
mSReceiver = null;
} catch (IllegalArgumentException ignored) {
}

if (mAlarmMgr != null) {
mAlarmMgr.cancel(mAlarmPendingIntent);
if (mAlarmMgr != null) {
mAlarmMgr.cancel(mAlarmPendingIntent);
}
mSReceiver = null;
}

}

private void updateWeather() {
Expand Down

0 comments on commit 3d577ca

Please sign in to comment.