summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Bryce Lee <brycelee@google.com> 2024-08-26 03:05:19 +0000
committer Bryce Lee <brycelee@google.com> 2024-08-27 00:03:43 +0000
commit8ac907f2a219f06d34aebe2bc2dbba9f8e98b560 (patch)
tree813ee013de0fd4f9599ce90bcd07ed898fad13b2
parent7477c179b16fc5a27d371fd85f8a392fa1c20a95 (diff)
Use a WeakReferences in DreamServiceWrapper and DreamActivityCallbacks.
The DreamServiceWrapper and DreamActivityCallbacks are handed across process during onBind. As a result, it should not reference the parent class as this will lead to a memory leak. This changelist wraps the parent in a WeakReference to resolve this. Test: manual. monitored heap usage and verified no leak Bug: 360088321 Flag: EXEMPT bugfix Change-Id: I99bde447a8844b9d15c1908139b987d097e233d3
-rw-r--r--core/java/android/service/dreams/DreamService.java97
1 files changed, 68 insertions, 29 deletions
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 0242de0b972c..c3585e3c5288 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -81,6 +81,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
import java.util.function.Consumer;
/**
@@ -1261,7 +1262,7 @@ public class DreamService extends Service implements Window.Callback {
@Override
public final IBinder onBind(Intent intent) {
if (mDebug) Slog.v(mTag, "onBind() intent = " + intent);
- mDreamServiceWrapper = new DreamServiceWrapper();
+ mDreamServiceWrapper = new DreamServiceWrapper(new WeakReference<>(this));
final ComponentName overlayComponent = intent.getParcelableExtra(
EXTRA_DREAM_OVERLAY_COMPONENT, ComponentName.class);
@@ -1631,7 +1632,8 @@ public class DreamService extends Service implements Window.Callback {
i.setComponent(mInjector.getDreamActivityComponent());
i.setPackage(mInjector.getDreamPackageName());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- DreamActivity.setCallback(i, new DreamActivityCallbacks(mDreamToken));
+ DreamActivity.setCallback(i,
+ new DreamActivityCallbacks(mDreamToken, new WeakReference<>(this)));
final ServiceInfo serviceInfo = mInjector.getServiceInfo();
final CharSequence title = fetchDreamLabel(mInjector.getPackageManager(),
mInjector.getResources(), serviceInfo, isPreviewMode);
@@ -1845,22 +1847,37 @@ public class DreamService extends Service implements Window.Callback {
* uses it to control the DreamService. It is also used to receive callbacks from the
* DreamActivity.
*/
- final class DreamServiceWrapper extends IDreamService.Stub {
+ static final class DreamServiceWrapper extends IDreamService.Stub {
+ final WeakReference<DreamService> mService;
+
+ DreamServiceWrapper(WeakReference<DreamService> service) {
+ mService = service;
+ }
+
+ private void post(Consumer<DreamService> consumer) {
+ final DreamService service = mService.get();
+
+ if (service == null) {
+ return;
+ }
+
+ service.mHandler.post(() -> consumer.accept(service));
+ }
+
@Override
public void attach(final IBinder dreamToken, final boolean canDoze,
final boolean isPreviewMode, IRemoteCallback started) {
- mHandler.post(
- () -> DreamService.this.attach(dreamToken, canDoze, isPreviewMode, started));
+ post(dreamService -> dreamService.attach(dreamToken, canDoze, isPreviewMode, started));
}
@Override
public void detach() {
- mHandler.post(DreamService.this::detach);
+ post(DreamService::detach);
}
@Override
public void wakeUp() {
- mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
+ post(dreamService -> dreamService.wakeUp(true /*fromSystem*/));
}
@Override
@@ -1868,48 +1885,70 @@ public class DreamService extends Service implements Window.Callback {
if (!dreamHandlesBeingObscured()) {
return;
}
+ post(DreamService::comeToFront);
+ }
+ }
- mHandler.post(DreamService.this::comeToFront);
+ private void onActivityCreated(DreamActivity activity, IBinder dreamToken) {
+ if (dreamToken != mDreamToken || mFinished) {
+ Slog.d(TAG, "DreamActivity was created after the dream was finished or "
+ + "a new dream started, finishing DreamActivity");
+ if (!activity.isFinishing()) {
+ activity.finishAndRemoveTask();
+ }
+ return;
+ }
+ if (mActivity != null) {
+ Slog.w(TAG, "A DreamActivity has already been started, "
+ + "finishing latest DreamActivity");
+ if (!activity.isFinishing()) {
+ activity.finishAndRemoveTask();
+ }
+ return;
}
+
+ mActivity = activity;
+ onWindowCreated(activity.getWindow());
+ }
+
+ private void onActivityDestroyed() {
+ mActivity = null;
+ mWindow = null;
+ detach();
}
/** @hide */
@VisibleForTesting
- public final class DreamActivityCallbacks extends Binder {
+ public static final class DreamActivityCallbacks extends Binder {
private final IBinder mActivityDreamToken;
+ private WeakReference<DreamService> mService;
- DreamActivityCallbacks(IBinder token) {
+ DreamActivityCallbacks(IBinder token, WeakReference<DreamService> service) {
mActivityDreamToken = token;
+ mService = service;
}
/** Callback when the {@link DreamActivity} has been created */
public void onActivityCreated(DreamActivity activity) {
- if (mActivityDreamToken != mDreamToken || mFinished) {
- Slog.d(TAG, "DreamActivity was created after the dream was finished or "
- + "a new dream started, finishing DreamActivity");
- if (!activity.isFinishing()) {
- activity.finishAndRemoveTask();
- }
- return;
- }
- if (mActivity != null) {
- Slog.w(TAG, "A DreamActivity has already been started, "
- + "finishing latest DreamActivity");
- if (!activity.isFinishing()) {
- activity.finishAndRemoveTask();
- }
+ final DreamService service = mService.get();
+
+ if (service == null) {
return;
}
- mActivity = activity;
- onWindowCreated(activity.getWindow());
+ service.onActivityCreated(activity, mActivityDreamToken);
}
/** Callback when the {@link DreamActivity} has been destroyed */
public void onActivityDestroyed() {
- mActivity = null;
- mWindow = null;
- detach();
+ final DreamService service = mService.get();
+
+ if (service == null) {
+ return;
+ }
+
+ service.onActivityDestroyed();
+ mService = null;
}
}