Potential fix for receiver leak problem
The background thread is not stopping listening fast enough and is resulting in first a receiver leak message followed by a crash when trying to finally unregister the receiver. Fix this by adding a registerReceiver to SummaryLoader that will automatically unregister the receiver on the main thread to ensure it happens in time. Change-Id: I0104e929d5505eb53993f6765e4c90120df35cf6 Fixes: 28211606
This commit is contained in:
@@ -16,8 +16,14 @@
|
|||||||
package com.android.settings.dashboard;
|
package com.android.settings.dashboard;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.os.*;
|
import android.content.IntentFilter;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -45,6 +51,7 @@ public class SummaryLoader {
|
|||||||
|
|
||||||
private DashboardAdapter mAdapter;
|
private DashboardAdapter mAdapter;
|
||||||
private boolean mListening;
|
private boolean mListening;
|
||||||
|
private ArrayList<BroadcastReceiver> mReceivers = new ArrayList<>();
|
||||||
|
|
||||||
public SummaryLoader(Activity activity, List<DashboardCategory> categories) {
|
public SummaryLoader(Activity activity, List<DashboardCategory> categories) {
|
||||||
mHandler = new Handler();
|
mHandler = new Handler();
|
||||||
@@ -88,6 +95,14 @@ public class SummaryLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setListening(boolean listening) {
|
public void setListening(boolean listening) {
|
||||||
|
synchronized (mReceivers) {
|
||||||
|
// Unregister listeners immediately.
|
||||||
|
mListening = false;
|
||||||
|
for (int i = 0; i < mReceivers.size(); i++) {
|
||||||
|
mActivity.unregisterReceiver(mReceivers.get(i));
|
||||||
|
}
|
||||||
|
mReceivers.clear();
|
||||||
|
}
|
||||||
mWorker.obtainMessage(Worker.MSG_SET_LISTENING, listening ? 1 : 0, 0).sendToTarget();
|
mWorker.obtainMessage(Worker.MSG_SET_LISTENING, listening ? 1 : 0, 0).sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +143,28 @@ public class SummaryLoader {
|
|||||||
return tile.metaData;
|
return tile.metaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a receiver and automatically unregisters it when the activity is stopping.
|
||||||
|
* This ensures that the receivers are unregistered immediately, since most summary loader
|
||||||
|
* operations are asynchronous.
|
||||||
|
*/
|
||||||
|
public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
|
||||||
|
synchronized (mReceivers) {
|
||||||
|
if (!mListening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mReceivers.add(receiver);
|
||||||
|
mActivity.registerReceiver(receiver, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void setListeningW(boolean listening) {
|
private synchronized void setListeningW(boolean listening) {
|
||||||
if (mListening == listening) return;
|
if (mListening == listening) return;
|
||||||
if (DEBUG) Log.d(TAG, "Listening " + listening);
|
if (DEBUG) Log.d(TAG, "Listening " + listening);
|
||||||
|
mListening = listening;
|
||||||
for (SummaryProvider p : mSummaryMap.keySet()) {
|
for (SummaryProvider p : mSummaryMap.keySet()) {
|
||||||
p.setListening(listening);
|
p.setListening(listening);
|
||||||
}
|
}
|
||||||
mListening = listening;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void makeProviderW(Tile tile) {
|
private synchronized void makeProviderW(Tile tile) {
|
||||||
|
@@ -28,7 +28,6 @@ import android.content.IntentFilter;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.NetworkInfo.State;
|
import android.net.NetworkInfo.State;
|
||||||
@@ -39,15 +38,12 @@ import android.nfc.NfcAdapter;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.PreferenceViewHolder;
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.style.TextAppearanceSpan;
|
import android.text.style.TextAppearanceSpan;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.ContextMenu.ContextMenuInfo;
|
import android.view.ContextMenu.ContextMenuInfo;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -58,7 +54,6 @@ import android.widget.ProgressBar;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TextView.BufferType;
|
import android.widget.TextView.BufferType;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.LinkifyUtils;
|
import com.android.settings.LinkifyUtils;
|
||||||
@@ -999,9 +994,7 @@ public class WifiSettings extends RestrictedSettingsFragment
|
|||||||
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||||
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
||||||
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
|
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
|
||||||
mContext.registerReceiver(this, filter);
|
mSummaryLoader.registerReceiver(this, filter);
|
||||||
} else {
|
|
||||||
mContext.unregisterReceiver(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user