diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index de1bcc34db..9ff647526d 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -177,12 +177,16 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI FolderIcon icon = inflateIcon(resId, activityContext, group, folderInfo); folder.setFolderIcon(icon); folder.bind(folderInfo); + icon.setFolder(folder); + folderInfo.addListener(icon); return icon; } /** - * Builds a FolderIcon to be added to the Launcher + * Builds a FolderIcon to be added to the activity. + * This method doesn't add any listeners to the FolderInfo, and hence any changes to the info + * will not be reflected in the folder. */ public static FolderIcon inflateIcon(int resId, ActivityContext activity, @Nullable ViewGroup group, FolderInfo folderInfo) { @@ -228,8 +232,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI icon.mPreviewVerifier.setFolderInfo(folderInfo); icon.updatePreviewItems(false); - folderInfo.addListener(icon); - return icon; } diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java index 7367f2e998..836ae98bcf 100644 --- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java +++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java @@ -51,11 +51,12 @@ import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.RunnableList; import com.android.systemui.shared.Flags; +import java.lang.ref.WeakReference; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; /** @@ -121,7 +122,7 @@ public class GridCustomizationsProvider extends ContentProvider { // Set of all active previews used to track duplicate memory allocations private final Set mActivePreviews = - Collections.newSetFromMap(new WeakHashMap<>()); + Collections.newSetFromMap(new ConcurrentHashMap<>()); @Override public boolean onCreate() { @@ -317,8 +318,15 @@ public class GridCustomizationsProvider extends ContentProvider { Bundle result = new Bundle(); result.putParcelable(KEY_SURFACE_PACKAGE, renderer.getSurfacePackage()); - Messenger messenger = - new Messenger(new Handler(UI_HELPER_EXECUTOR.getLooper(), observer)); + mActivePreviews.add(observer); + lifeCycleTracker.add(() -> mActivePreviews.remove(observer)); + + // Wrap the callback in a weak reference. This ensures that the callback is not kept + // alive due to the Messenger's IBinder + Messenger messenger = new Messenger(new Handler( + UI_HELPER_EXECUTOR.getLooper(), + new WeakCallbackWrapper(observer))); + Message msg = Message.obtain(); msg.replyTo = messenger; result.putParcelable(KEY_CALLBACK, msg); @@ -400,4 +408,34 @@ public class GridCustomizationsProvider extends ContentProvider { && plo.renderer.getDisplayId() == renderer.getDisplayId(); } } + + /** + * A WeakReference wrapper around Handler.Callback to avoid passing hard-reference over IPC + * when using a Messenger + */ + private static class WeakCallbackWrapper implements Handler.Callback { + + private final WeakReference mActual; + private final Message mCleanupMessage; + + WeakCallbackWrapper(Handler.Callback actual) { + mActual = new WeakReference<>(actual); + mCleanupMessage = new Message(); + } + + @Override + public boolean handleMessage(Message message) { + Handler.Callback actual = mActual.get(); + return actual != null && actual.handleMessage(message); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Handler.Callback actual = mActual.get(); + if (actual != null) { + actual.handleMessage(mCleanupMessage); + } + } + } } diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index 3000b252d4..a7cf1a7876 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -105,7 +105,6 @@ public class PreviewSurfaceRenderer { private final SurfaceControlViewHost mSurfaceControlViewHost; private boolean mDestroyed = false; - private LauncherPreviewRenderer mRenderer; private boolean mHideQsb; @Nullable private FrameLayout mViewRoot = null; @@ -224,9 +223,8 @@ public class PreviewSurfaceRenderer { * @param hide True to hide and false to show. */ public void hideBottomRow(boolean hide) { - if (mRenderer != null) { - mRenderer.hideBottomRow(hide); - } + mHideQsb = hide; + loadAsync(); } /** @@ -368,15 +366,16 @@ public class PreviewSurfaceRenderer { if (mDestroyed) { return; } + LauncherPreviewRenderer renderer; if (Flags.newCustomizationPickerUi()) { - mRenderer = new LauncherPreviewRenderer(inflationContext, idp, mPreviewColorOverride, + renderer = new LauncherPreviewRenderer(inflationContext, idp, mPreviewColorOverride, mWallpaperColors, launcherWidgetSpanInfo); } else { - mRenderer = new LauncherPreviewRenderer(inflationContext, idp, + renderer = new LauncherPreviewRenderer(inflationContext, idp, mWallpaperColors, launcherWidgetSpanInfo); } - mRenderer.hideBottomRow(mHideQsb); - View view = mRenderer.getRenderedView(dataModel, widgetProviderInfoMap); + renderer.hideBottomRow(mHideQsb); + View view = renderer.getRenderedView(dataModel, widgetProviderInfoMap); // This aspect scales the view to fit in the surface and centers it final float scale = Math.min(mWidth / (float) view.getMeasuredWidth(), mHeight / (float) view.getMeasuredHeight());