Fix memory leak in ApplicationStates
- Use app context in dreambackend - Use WeakReference in LocalBluetoothManager to track foreground activity - Use WeakReference in ApplicationsState to track active sessions Bug: 109894607 Test: hprof Change-Id: I0e868182a364efbd110eb77ebd6cdbd83f164669
This commit is contained in:
@@ -22,9 +22,6 @@ import android.app.AppGlobals;
|
||||
import android.app.Application;
|
||||
import android.app.usage.StorageStats;
|
||||
import android.app.usage.StorageStatsManager;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -49,7 +46,6 @@ import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import android.text.format.Formatter;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Log;
|
||||
@@ -62,6 +58,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.Collator;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
@@ -74,6 +71,11 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
|
||||
/**
|
||||
* Keeps track of information about all installed applications, lazy-loading
|
||||
* as needed.
|
||||
@@ -132,7 +134,7 @@ public class ApplicationsState {
|
||||
boolean mSessionsChanged;
|
||||
|
||||
// Temporary for dispatching session callbacks. Only touched by main thread.
|
||||
final ArrayList<Session> mActiveSessions = new ArrayList<Session>();
|
||||
final ArrayList<WeakReference<Session>> mActiveSessions = new ArrayList<>();
|
||||
|
||||
final HandlerThread mThread;
|
||||
final BackgroundHandler mBackgroundHandler;
|
||||
@@ -618,7 +620,7 @@ public class ApplicationsState {
|
||||
for (int i=0; i<mSessions.size(); i++) {
|
||||
Session s = mSessions.get(i);
|
||||
if (s.mResumed) {
|
||||
mActiveSessions.add(s);
|
||||
mActiveSessions.add(new WeakReference<>(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -830,46 +832,70 @@ public class ApplicationsState {
|
||||
rebuildActiveSessions();
|
||||
switch (msg.what) {
|
||||
case MSG_REBUILD_COMPLETE: {
|
||||
Session s = (Session)msg.obj;
|
||||
if (mActiveSessions.contains(s)) {
|
||||
s.mCallbacks.onRebuildComplete(s.mLastAppList);
|
||||
Session s = (Session) msg.obj;
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null && session == s) {
|
||||
s.mCallbacks.onRebuildComplete(s.mLastAppList);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_PACKAGE_LIST_CHANGED: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onPackageListChanged();
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onPackageListChanged();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_PACKAGE_ICON_CHANGED: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onPackageIconChanged();
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onPackageIconChanged();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_PACKAGE_SIZE_CHANGED: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onPackageSizeChanged(
|
||||
(String)msg.obj);
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onPackageSizeChanged(
|
||||
(String) msg.obj);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_ALL_SIZES_COMPUTED: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onAllSizesComputed();
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onAllSizesComputed();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_RUNNING_STATE_CHANGED: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onRunningStateChanged(
|
||||
msg.arg1 != 0);
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onRunningStateChanged(
|
||||
msg.arg1 != 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_LAUNCHER_INFO_CHANGED: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onLauncherInfoChanged();
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onLauncherInfoChanged();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_LOAD_ENTRIES_COMPLETE: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onLoadEntriesCompleted();
|
||||
for (WeakReference<Session> sessionRef : mActiveSessions) {
|
||||
final Session session = sessionRef.get();
|
||||
if (session != null) {
|
||||
session.mCallbacks.onLoadEntriesCompleted();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.settingslib.bluetooth;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* LocalBluetoothManager provides a simplified interface on top of a subset of
|
||||
* the Bluetooth API. Note that {@link #getInstance} will return null
|
||||
@@ -34,7 +36,7 @@ public class LocalBluetoothManager {
|
||||
private final Context mContext;
|
||||
|
||||
/** If a BT-related activity is in the foreground, this will be it. */
|
||||
private Context mForegroundActivity;
|
||||
private WeakReference<Context> mForegroundActivity;
|
||||
|
||||
private final LocalBluetoothAdapter mLocalAdapter;
|
||||
|
||||
@@ -85,17 +87,19 @@ public class LocalBluetoothManager {
|
||||
}
|
||||
|
||||
public Context getForegroundActivity() {
|
||||
return mForegroundActivity;
|
||||
return mForegroundActivity == null
|
||||
? null
|
||||
: mForegroundActivity.get();
|
||||
}
|
||||
|
||||
public boolean isForegroundActivity() {
|
||||
return mForegroundActivity != null;
|
||||
return mForegroundActivity != null && mForegroundActivity.get() != null;
|
||||
}
|
||||
|
||||
public synchronized void setForegroundActivity(Context context) {
|
||||
if (context != null) {
|
||||
Log.d(TAG, "setting foreground activity to non-null context");
|
||||
mForegroundActivity = context;
|
||||
mForegroundActivity = new WeakReference<>(context);
|
||||
} else {
|
||||
if (mForegroundActivity != null) {
|
||||
Log.d(TAG, "setting foreground activity to null");
|
||||
|
||||
@@ -36,12 +36,12 @@ import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -97,15 +97,15 @@ public class DreamBackend {
|
||||
}
|
||||
|
||||
public DreamBackend(Context context) {
|
||||
mContext = context;
|
||||
mContext = context.getApplicationContext();
|
||||
mDreamManager = IDreamManager.Stub.asInterface(
|
||||
ServiceManager.getService(DreamService.DREAM_SERVICE));
|
||||
mComparator = new DreamInfoComparator(getDefaultDream());
|
||||
mDreamsEnabledByDefault = context.getResources()
|
||||
mDreamsEnabledByDefault = mContext.getResources()
|
||||
.getBoolean(com.android.internal.R.bool.config_dreamsEnabledByDefault);
|
||||
mDreamsActivatedOnSleepByDefault = context.getResources()
|
||||
mDreamsActivatedOnSleepByDefault = mContext.getResources()
|
||||
.getBoolean(com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
|
||||
mDreamsActivatedOnDockByDefault = context.getResources()
|
||||
mDreamsActivatedOnDockByDefault = mContext.getResources()
|
||||
.getBoolean(com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user