From 712a8bf0041dde1ee1611d2c107db1ce9fb11a47 Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Thu, 1 Apr 2021 11:19:20 +0100 Subject: [PATCH] Prevent launcher crash when an App Widget is removed. If an App Widget with a scrollable element is removed, we may end up in a situation where we try to draw the view directly on a canvas while the it has already been detached from the workspace. This can crash as some of the drawing the scroll indicators require the view to be attached. In general, we should never draw a view by calling the draw method directly, even more so when the view is detached: the behavior is undefined as the method expects the canvas to be properly set up, and it is not. A crash can therefore be expected. This patch should avoid crashing the launcher until we stop doing that altogether. Fix: 183386115 Test: Manally add a view with a preview layout Test: Manually remove an app widget with a list view Change-Id: I8e1aa581700a08d6747eab085199c2b293e0e3fb --- .../dragndrop/AppWidgetHostViewDrawable.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java index 5cd95dc413..7b32bbf02e 100644 --- a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java +++ b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java @@ -27,15 +27,21 @@ import android.graphics.drawable.Drawable; import com.android.launcher3.widget.LauncherAppWidgetHostView; -/** A drawable which renders {@link LauncherAppWidgetHostView} to a canvas. */ +/** + * A drawable which renders {@link LauncherAppWidgetHostView} to a canvas. + * + * TODO(b/183609936) Stop using that class and remove it. + */ public final class AppWidgetHostViewDrawable extends Drawable { private final LauncherAppWidgetHostView mAppWidgetHostView; private Paint mPaint = new Paint(); private final Path mClipPath; + private final boolean mWasAttached; public AppWidgetHostViewDrawable(LauncherAppWidgetHostView appWidgetHostView) { mAppWidgetHostView = appWidgetHostView; + mWasAttached = appWidgetHostView.isAttachedToWindow(); Path clipPath = null; if (appWidgetHostView.getClipToOutline()) { Outline outline = new Outline(); @@ -56,7 +62,12 @@ public final class AppWidgetHostViewDrawable extends Drawable { if (mClipPath != null) { canvas.clipPath(mClipPath); } - mAppWidgetHostView.draw(canvas); + // If the view was never attached, or is current attached, then draw. Otherwise do not try + // to draw, or we might trigger bugs with items that get drawn while requiring the view to + // be attached. + if (!mWasAttached || mAppWidgetHostView.isAttachedToWindow()) { + mAppWidgetHostView.draw(canvas); + } canvas.restoreToCount(saveCount); }