Skip to content

Commit

Permalink
RemotePreferenceManager: Fix receiver registration issues.
Browse files Browse the repository at this point in the history
- We might get see attach() calls from multiple prefs, so stop assuming
  there's only one per key. Namely, a new activity might be created and
  attached before the previous one is destroyed
- The passed-in context is likely to be an activity one. As the manager
  instance is static, this can cause leaks and the receiver might be
  attached to a destroyed activity. Just hold onto the application
  context instead, which is a singleton anyway.

Change-Id: Ica17c19ab6e1cdfd402968ce2594d3ed362e23ee
JIRA:LINN-3
  • Loading branch information
maniac103 committed Feb 12, 2017
1 parent 77b94bc commit 6669674
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 14 deletions.
2 changes: 1 addition & 1 deletion sdk/src/java/cyanogenmod/preference/RemotePreference.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void onAttached() {
@Override
public void onDetached() {
super.onDetached();
RemotePreferenceManager.get(mContext).detach(getKey());
RemotePreferenceManager.get(mContext).detach(getKey(), this);
}

protected String getRemoteKey(Bundle metaData) {
Expand Down
42 changes: 29 additions & 13 deletions sdk/src/java/cyanogenmod/preference/RemotePreferenceManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
import android.util.ArrayMap;
import android.util.Log;

import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import cyanogenmod.platform.Manifest;

Expand All @@ -54,7 +56,7 @@ public class RemotePreferenceManager {

private final Context mContext;
private final Map<String, Intent> mCache = new ArrayMap<>();
private final Map<String, OnRemoteUpdateListener> mCallbacks = new ArrayMap<>();
private final Map<String, Set<OnRemoteUpdateListener>> mCallbacks = new ArrayMap<>();

private final Handler mMainHandler = new Handler(Looper.getMainLooper());

Expand All @@ -73,7 +75,7 @@ private RemotePreferenceManager(Context context) {

public synchronized static RemotePreferenceManager get(Context context) {
if (sInstance == null) {
sInstance = new RemotePreferenceManager(context);
sInstance = new RemotePreferenceManager(context.getApplicationContext());
}
return sInstance;
}
Expand All @@ -89,27 +91,36 @@ public void attach(String key, OnRemoteUpdateListener pref) {
}
synchronized (mCallbacks) {
if (i != null) {
mCallbacks.put(key, pref);
if (mCallbacks.size() == 1) {
mThread = new HandlerThread("RemotePreference");
mThread.start();
mHandler = new Handler(mThread.getLooper());
mContext.registerReceiver(mListener,
new IntentFilter(ACTION_REFRESH_PREFERENCE),
Manifest.permission.MANAGE_REMOTE_PREFERENCES, mHandler);
Set<OnRemoteUpdateListener> cbs = mCallbacks.get(key);
if (cbs == null) {
cbs = new HashSet<>();
mCallbacks.put(key, cbs);
if (mCallbacks.size() == 1) {
mThread = new HandlerThread("RemotePreference");
mThread.start();
mHandler = new Handler(mThread.getLooper());
mContext.registerReceiver(mListener,
new IntentFilter(ACTION_REFRESH_PREFERENCE),
Manifest.permission.MANAGE_REMOTE_PREFERENCES, mHandler);
}
}
cbs.add(pref);
requestUpdate(key);
}
}
}

public void detach(String key) {
public void detach(String key, OnRemoteUpdateListener pref) {
synchronized (mCallbacks) {
if (mCallbacks.remove(key) != null && mCallbacks.size() == 0) {
Set<OnRemoteUpdateListener> cbs = mCallbacks.get(key);
if (cbs != null && cbs.remove(pref) && cbs.isEmpty()
&& mCallbacks.remove(key) != null && mCallbacks.isEmpty()) {
mContext.unregisterReceiver(mListener);
if (mThread != null) {
mThread.quit();
mThread = null;
}
mHandler = null;
}
}
}
Expand Down Expand Up @@ -152,7 +163,12 @@ public void onReceive(Context context, Intent intent) {
public void run() {
synchronized (mCallbacks) {
if (mCallbacks.containsKey(key)) {
mCallbacks.get(key).onRemoteUpdated(bundle);
Set<OnRemoteUpdateListener> cbs = mCallbacks.get(key);
if (cbs != null) {
for (OnRemoteUpdateListener cb : cbs) {
cb.onRemoteUpdated(bundle);
}
}
}
}
}
Expand Down

0 comments on commit 6669674

Please sign in to comment.