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

Commit a687a41a authored by Ats Jenk's avatar Ats Jenk
Browse files

Add background executor to Bubble class

Adds background executor to Bubble class to prepare moving
BubbleViewInfoTask from using deprecated AsyncTask for bubble view
inflation. Use the shell background executor instead.
We are experiencing some bugs with bubbles showing up and the cause is a
race condition in view inflation.
Using an executor instead of the AsyncTask is the first step to fix
this.
Executor will be used for inflation in a follow-up cl.

Bug: 353894869
Test: atest WMShellUnitTests
Test: atest BubblesTest
Test: atest BubbleEducationControllerTest
Test: atest BubblePositionerTest
Test: atest BubbleStackViewTest
Flag: EXEMPT refactor

Change-Id: Ibb936cd649701ed5f16d5d8a3e340c8aeb11b52c
parent 8c89b822
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -268,7 +268,8 @@ class BubblePositionerTest {
            )
        positioner.update(deviceConfig)
        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        assertThat(positioner.getExpandedViewHeight(bubble)).isEqualTo(MAX_HEIGHT)
    }
@@ -294,6 +295,7 @@ class BubblePositionerTest {
                0 /* taskId */,
                null /* locus */,
                true /* isDismissable */,
                directExecutor(),
                directExecutor()
            ) {}

@@ -322,6 +324,7 @@ class BubblePositionerTest {
                0 /* taskId */,
                null /* locus */,
                true /* isDismissable */,
                directExecutor(),
                directExecutor()
            ) {}

@@ -416,7 +419,8 @@ class BubblePositionerTest {
        positioner.update(deviceConfig)

        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        // This bubble will have max height so it'll always be top aligned
        assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -433,7 +437,8 @@ class BubblePositionerTest {
        positioner.update(deviceConfig)

        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        // Always top aligned in phone portrait
        assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -452,7 +457,8 @@ class BubblePositionerTest {
        positioner.update(deviceConfig)

        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        // This bubble will have max height which is always top aligned on small tablets
        assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -470,7 +476,8 @@ class BubblePositionerTest {
        positioner.update(deviceConfig)

        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        // This bubble will have max height which is always top aligned on small tablets
        assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -489,7 +496,8 @@ class BubblePositionerTest {
        positioner.update(deviceConfig)

        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        // This bubble will have max height which is always top aligned on landscape, large tablet
        assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -507,7 +515,8 @@ class BubblePositionerTest {
        positioner.update(deviceConfig)

        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())

        val manageButtonHeight =
            context.resources.getDimensionPixelSize(R.dimen.bubble_manage_button_height)
+4 −1
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ class BubbleStackViewTest {
                BubbleLogger(UiEventLoggerFake()),
                positioner,
                BubbleEducationController(context),
                shellExecutor,
                shellExecutor
            )
        bubbleStackViewManager = FakeBubbleStackViewManager()
@@ -364,6 +365,7 @@ class BubbleStackViewTest {
                /* taskId= */ 0,
                "locus",
                /* isDismissable= */ true,
                directExecutor(),
                directExecutor()
            ) {}
        inflateBubble(bubble)
@@ -373,7 +375,8 @@ class BubbleStackViewTest {
    private fun createAndInflateBubble(): Bubble {
        val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
        val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button)
        val bubble = Bubble.createAppBubble(intent, UserHandle(1), icon, directExecutor())
        val bubble =
            Bubble.createAppBubble(intent, UserHandle(1), icon, directExecutor(), directExecutor())
        inflateBubble(bubble)
        return bubble
    }
+20 −12
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ import com.android.wm.shell.Flags;
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
import com.android.wm.shell.common.bubbles.BubbleInfo;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;

import java.io.PrintWriter;
import java.util.List;
@@ -79,6 +81,7 @@ public class Bubble implements BubbleViewProvider {
    private final LocusId mLocusId;

    private final Executor mMainExecutor;
    private final Executor mBgExecutor;

    private long mLastUpdated;
    private long mLastAccessed;
@@ -206,7 +209,9 @@ public class Bubble implements BubbleViewProvider {
    @VisibleForTesting(visibility = PRIVATE)
    public Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
            final int desiredHeight, final int desiredHeightResId, @Nullable final String title,
            int taskId, @Nullable final String locus, boolean isDismissable, Executor mainExecutor,
            int taskId, @Nullable final String locus, boolean isDismissable,
            @ShellMainThread Executor mainExecutor,
            @ShellBackgroundThread Executor bgExecutor,
            final Bubbles.BubbleMetadataFlagListener listener) {
        Objects.requireNonNull(key);
        Objects.requireNonNull(shortcutInfo);
@@ -225,6 +230,7 @@ public class Bubble implements BubbleViewProvider {
        mTitle = title;
        mShowBubbleUpdateDot = false;
        mMainExecutor = mainExecutor;
        mBgExecutor = bgExecutor;
        mTaskId = taskId;
        mBubbleMetadataFlagListener = listener;
        mIsAppBubble = false;
@@ -236,7 +242,8 @@ public class Bubble implements BubbleViewProvider {
            @Nullable Icon icon,
            boolean isAppBubble,
            String key,
            Executor mainExecutor) {
            @ShellMainThread Executor mainExecutor,
            @ShellBackgroundThread Executor bgExecutor) {
        mGroupKey = null;
        mLocusId = null;
        mFlags = 0;
@@ -246,13 +253,15 @@ public class Bubble implements BubbleViewProvider {
        mKey = key;
        mShowBubbleUpdateDot = false;
        mMainExecutor = mainExecutor;
        mBgExecutor = bgExecutor;
        mTaskId = INVALID_TASK_ID;
        mAppIntent = intent;
        mDesiredHeight = Integer.MAX_VALUE;
        mPackageName = intent.getPackage();
    }

    private Bubble(ShortcutInfo info, Executor mainExecutor) {
    private Bubble(ShortcutInfo info, @ShellMainThread Executor mainExecutor,
            @ShellBackgroundThread Executor bgExecutor) {
        mGroupKey = null;
        mLocusId = null;
        mFlags = 0;
@@ -262,6 +271,7 @@ public class Bubble implements BubbleViewProvider {
        mKey = getBubbleKeyForShortcut(info);
        mShowBubbleUpdateDot = false;
        mMainExecutor = mainExecutor;
        mBgExecutor = bgExecutor;
        mTaskId = INVALID_TASK_ID;
        mAppIntent = null;
        mDesiredHeight = Integer.MAX_VALUE;
@@ -270,24 +280,21 @@ public class Bubble implements BubbleViewProvider {
    }

    /** Creates an app bubble. */
    public static Bubble createAppBubble(
            Intent intent,
            UserHandle user,
            @Nullable Icon icon,
            Executor mainExecutor) {
    public static Bubble createAppBubble(Intent intent, UserHandle user, @Nullable Icon icon,
            @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
        return new Bubble(intent,
                user,
                icon,
                /* isAppBubble= */ true,
                /* key= */ getAppBubbleKeyForApp(intent.getPackage(), user),
                mainExecutor);
                mainExecutor, bgExecutor);
    }

    /** Creates a shortcut bubble. */
    public static Bubble createShortcutBubble(
            ShortcutInfo info,
            Executor mainExecutor) {
        return new Bubble(info, mainExecutor);
            @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
        return new Bubble(info, mainExecutor, bgExecutor);
    }

    /**
@@ -312,7 +319,7 @@ public class Bubble implements BubbleViewProvider {
    public Bubble(@NonNull final BubbleEntry entry,
            final Bubbles.BubbleMetadataFlagListener listener,
            final Bubbles.PendingIntentCanceledListener intentCancelListener,
            Executor mainExecutor) {
            @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
        mIsAppBubble = false;
        mKey = entry.getKey();
        mGroupKey = entry.getGroupKey();
@@ -327,6 +334,7 @@ public class Bubble implements BubbleViewProvider {
            });
        };
        mMainExecutor = mainExecutor;
        mBgExecutor = bgExecutor;
        mTaskId = INVALID_TASK_ID;
        setEntry(entry);
    }
+1 −1
Original line number Diff line number Diff line
@@ -1495,7 +1495,7 @@ public class BubbleController implements ConfigurationChangeListener,
                b.setAppBubbleIntent(intent);
            } else {
                // App bubble does not exist, lets add and expand it
                b = Bubble.createAppBubble(intent, user, icon, mMainExecutor);
                b = Bubble.createAppBubble(intent, user, icon, mMainExecutor, mBackgroundExecutor);
            }
            ProtoLog.d(WM_SHELL_BUBBLES, "inflateAndAdd %s", appBubbleKey);
            b.setShouldAutoExpand(true);
+10 −4
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.Bubbles.DismissReason;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.common.bubbles.RemovedBubble;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -201,6 +203,7 @@ public class BubbleData {
    private final BubblePositioner mPositioner;
    private final BubbleEducationController mEducationController;
    private final Executor mMainExecutor;
    private final Executor mBgExecutor;
    /** Bubbles that are actively in the stack. */
    private final List<Bubble> mBubbles;
    /** Bubbles that aged out to overflow. */
@@ -246,12 +249,14 @@ public class BubbleData {
    private HashMap<String, String> mSuppressedGroupKeys = new HashMap<>();

    public BubbleData(Context context, BubbleLogger bubbleLogger, BubblePositioner positioner,
            BubbleEducationController educationController, Executor mainExecutor) {
            BubbleEducationController educationController, @ShellMainThread Executor mainExecutor,
            @ShellBackgroundThread Executor bgExecutor) {
        mContext = context;
        mLogger = bubbleLogger;
        mPositioner = positioner;
        mEducationController = educationController;
        mMainExecutor = mainExecutor;
        mBgExecutor = bgExecutor;
        mOverflow = new BubbleOverflow(context, positioner);
        mBubbles = new ArrayList<>();
        mOverflowBubbles = new ArrayList<>();
@@ -431,7 +436,8 @@ public class BubbleData {
                    bubbleToReturn = new Bubble(entry,
                            mBubbleMetadataFlagListener,
                            mCancelledListener,
                            mMainExecutor);
                            mMainExecutor,
                            mBgExecutor);
                } else {
                    // If there's no entry it must be a persisted bubble
                    bubbleToReturn = persistedBubble;
@@ -450,7 +456,7 @@ public class BubbleData {
        String bubbleKey = Bubble.getBubbleKeyForShortcut(info);
        Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey);
        if (bubbleToReturn == null) {
            bubbleToReturn = Bubble.createShortcutBubble(info, mMainExecutor);
            bubbleToReturn = Bubble.createShortcutBubble(info, mMainExecutor, mBgExecutor);
        }
        return bubbleToReturn;
    }
@@ -461,7 +467,7 @@ public class BubbleData {
                user);
        Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey);
        if (bubbleToReturn == null) {
            bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor);
            bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor, mBgExecutor);
        }
        return bubbleToReturn;
    }
Loading