Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b72ff9c6 authored by wilsonshih's avatar wilsonshih
Browse files

Fix WallpaperEngine object leaked during stress test.

The wallpaper engine object may not have released due to someone continuously
change wallpaper with the same component, such as image wallpaper.
In this case, server side may receive attached engine to a connection, however,
it could already detached.

Example sequence:
bind wallpaper (A) connection (C1)
  detachWallpaperLocked(lastwallpaper)
  lastwallpaper = A + C1
bind wallpaper (A) connection (C2)
  detachWallpaperLocked(lastwallpaper = A + C1)
  last = A + C2
  attachEngine to C1
Then the connection C1 will never be released because it was be detached.

We can fix this by notify that WallpaperService is detached.
When it was detached, it shall destroy its engine if there is, and doesn't attach
back to WallpaperManagerService anymore.

Bug: 128974839
Test: run atest WallpaperManagerTest, then dump
adb shell dumpsys activity service com.android.systemui/com.android.systemui.ImageWallpaper
to make sure there is only one WallpaperEngine object.

Change-Id: Ifea201fe8860af11376717d344fee77182b38e54
parent a50d69cc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,4 +26,5 @@ oneway interface IWallpaperService {
    void attach(IWallpaperConnection connection,
            IBinder windowToken, int windowType, boolean isPreview,
            int reqWidth, int reqHeight, in Rect padding, int displayId);
    void detach();
}
+25 −3
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.internal.view.BaseSurfaceHolder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;

/**
@@ -1309,6 +1310,7 @@ public abstract class WallpaperService extends Service {
        final int mDisplayId;
        final DisplayManager mDisplayManager;
        final Display mDisplay;
        private final AtomicBoolean mDetached = new AtomicBoolean();

        Engine mEngine;

@@ -1399,8 +1401,23 @@ public abstract class WallpaperService extends Service {
            mCaller.sendMessage(msg);
        }

        public void detach() {
            mDetached.set(true);
        }

        private void doDetachEngine() {
            mActiveEngines.remove(mEngine);
            mEngine.detach();
        }

        @Override
        public void executeMessage(Message message) {
            if (mDetached.get()) {
                if (mActiveEngines.contains(mEngine)) {
                    doDetachEngine();
                }
                return;
            }
            switch (message.what) {
                case DO_ATTACH: {
                    try {
@@ -1416,8 +1433,7 @@ public abstract class WallpaperService extends Service {
                    return;
                }
                case DO_DETACH: {
                    mActiveEngines.remove(mEngine);
                    mEngine.detach();
                    doDetachEngine();
                    return;
                }
                case DO_SET_DESIRED_SIZE: {
@@ -1497,6 +1513,7 @@ public abstract class WallpaperService extends Service {
     */
    class IWallpaperServiceWrapper extends IWallpaperService.Stub {
        private final WallpaperService mTarget;
        private IWallpaperEngineWrapper mEngineWrapper;

        public IWallpaperServiceWrapper(WallpaperService context) {
            mTarget = context;
@@ -1506,9 +1523,14 @@ public abstract class WallpaperService extends Service {
        public void attach(IWallpaperConnection conn, IBinder windowToken,
                int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
                int displayId) {
            new IWallpaperEngineWrapper(mTarget, conn, windowToken,
            mEngineWrapper = new IWallpaperEngineWrapper(mTarget, conn, windowToken,
                    windowType, isPreview, reqWidth, reqHeight, padding, displayId);
        }

        @Override
        public void detach() {
            mEngineWrapper.detach();
        }
    }

    @Override
+5 −0
Original line number Diff line number Diff line
@@ -2682,6 +2682,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                }
                wallpaper.connection.mReply = null;
            }
            try {
                wallpaper.connection.mService.detach();
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed detaching wallpaper service ", e);
            }
            mContext.unbindService(wallpaper.connection);
            wallpaper.connection.forEachDisplayConnector(
                    WallpaperConnection.DisplayConnector::disconnectLocked);