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

Commit ac5394a4 authored by Ivan Tkachenko's avatar Ivan Tkachenko Committed by Android (Google) Code Review
Browse files

Merge "Show Bubble OOBE on the first conversation bubble only" into udc-dev

parents 342bac9d bd680873
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -655,6 +655,13 @@ public class Bubble implements BubbleViewProvider {
        return mIsImportantConversation;
    }

    /**
     * Whether this bubble is conversation
     */
    public boolean isConversation() {
        return null != mShortcutInfo;
    }

    /**
     * Sets whether this notification should be suppressed in the shade.
     */
+33 −19
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -575,7 +574,7 @@ public class BubbleStackView extends FrameLayout
            if (maybeShowStackEdu()) {
                mShowedUserEducationInTouchListenerActive = true;
                return true;
            } else if (isStackEduShowing()) {
            } else if (isStackEduVisible()) {
                mStackEduView.hide(false /* fromExpansion */);
            }

@@ -651,7 +650,7 @@ public class BubbleStackView extends FrameLayout
                    mExpandedAnimationController.dragBubbleOut(
                            v, viewInitialX + dx, viewInitialY + dy);
                } else {
                    if (isStackEduShowing()) {
                    if (isStackEduVisible()) {
                        mStackEduView.hide(false /* fromExpansion */);
                    }
                    mStackAnimationController.moveStackFromTouch(
@@ -733,8 +732,7 @@ public class BubbleStackView extends FrameLayout

        @Override
        public void onMove(float dx, float dy) {
            if ((mManageEduView != null && mManageEduView.getVisibility() == VISIBLE)
                    || isStackEduShowing()) {
            if (isManageEduVisible() || isStackEduVisible()) {
                return;
            }

@@ -996,7 +994,7 @@ public class BubbleStackView extends FrameLayout
                    mStackAnimationController.updateResources();
                    mBubbleOverflow.updateResources();

                    if (!isStackEduShowing() && mRelativeStackPositionBeforeRotation != null) {
                    if (!isStackEduVisible() && mRelativeStackPositionBeforeRotation != null) {
                        mStackAnimationController.setStackPosition(
                                mRelativeStackPositionBeforeRotation);
                        mRelativeStackPositionBeforeRotation = null;
@@ -1046,9 +1044,9 @@ public class BubbleStackView extends FrameLayout
        setOnClickListener(view -> {
            if (mShowingManage) {
                showManageMenu(false /* show */);
            } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
            } else if (isManageEduVisible()) {
                mManageEduView.hide();
            } else if (isStackEduShowing()) {
            } else if (isStackEduVisible()) {
                mStackEduView.hide(false /* isExpanding */);
            } else if (mBubbleData.isExpanded()) {
                mBubbleData.setExpanded(false);
@@ -1246,11 +1244,20 @@ public class BubbleStackView extends FrameLayout
        updateManageButtonListener();
    }

    /**
     * Whether the selected bubble is conversation bubble
     */
    private boolean isConversationBubble() {
        BubbleViewProvider bubble = mBubbleData.getSelectedBubble();
        return bubble instanceof Bubble && ((Bubble) bubble).isConversation();
    }

    /**
     * Whether the educational view should show for the expanded view "manage" menu.
     */
    private boolean shouldShowManageEdu() {
        if (ActivityManager.isRunningInTestHarness()) {
        if (!isConversationBubble()) {
            // We only show user education for conversation bubbles right now
            return false;
        }
        final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION);
@@ -1273,11 +1280,17 @@ public class BubbleStackView extends FrameLayout
        mManageEduView.show(mExpandedBubble.getExpandedView());
    }

    @VisibleForTesting
    public boolean isManageEduVisible() {
        return mManageEduView != null && mManageEduView.getVisibility() == VISIBLE;
    }

    /**
     * Whether education view should show for the collapsed stack.
     */
    private boolean shouldShowStackEdu() {
        if (ActivityManager.isRunningInTestHarness()) {
        if (!isConversationBubble()) {
            // We only show user education for conversation bubbles right now
            return false;
        }
        final boolean seen = getPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION);
@@ -1310,13 +1323,14 @@ public class BubbleStackView extends FrameLayout
        return mStackEduView.show(mPositioner.getDefaultStartPosition());
    }

    private boolean isStackEduShowing() {
    @VisibleForTesting
    public boolean isStackEduVisible() {
        return mStackEduView != null && mStackEduView.getVisibility() == VISIBLE;
    }

    // Recreates & shows the education views. Call when a theme/config change happens.
    private void updateUserEdu() {
        if (isStackEduShowing()) {
        if (isStackEduVisible()) {
            removeView(mStackEduView);
            mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController);
            addView(mStackEduView);
@@ -1325,7 +1339,7 @@ public class BubbleStackView extends FrameLayout
            mStackAnimationController.setStackPosition(mPositioner.getDefaultStartPosition());
            mStackEduView.show(mPositioner.getDefaultStartPosition());
        }
        if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
        if (isManageEduVisible()) {
            removeView(mManageEduView);
            mManageEduView = new ManageEducationView(mContext, mPositioner);
            addView(mManageEduView);
@@ -1429,7 +1443,7 @@ public class BubbleStackView extends FrameLayout
        mStackAnimationController.updateResources();
        mDismissView.updateResources();
        mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2);
        if (!isStackEduShowing()) {
        if (!isStackEduVisible()) {
            mStackAnimationController.setStackPosition(
                    new RelativeStackPosition(
                            mPositioner.getRestingPosition(),
@@ -2013,7 +2027,7 @@ public class BubbleStackView extends FrameLayout
        if (mIsExpanded) {
            if (mShowingManage) {
                showManageMenu(false);
            } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
            } else if (isManageEduVisible()) {
                mManageEduView.hide();
            } else {
                mBubbleData.setExpanded(false);
@@ -2158,7 +2172,7 @@ public class BubbleStackView extends FrameLayout
        cancelDelayedExpandCollapseSwitchAnimations();
        final boolean showVertically = mPositioner.showBubblesVertically();
        mIsExpanded = true;
        if (isStackEduShowing()) {
        if (isStackEduVisible()) {
            mStackEduView.hide(true /* fromExpansion */);
        }
        beforeExpandedViewAnimation();
@@ -2280,7 +2294,7 @@ public class BubbleStackView extends FrameLayout
    private void animateCollapse() {
        cancelDelayedExpandCollapseSwitchAnimations();

        if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
        if (isManageEduVisible()) {
            mManageEduView.hide();
        }

@@ -2677,7 +2691,7 @@ public class BubbleStackView extends FrameLayout
        if (flyoutMessage == null
                || flyoutMessage.message == null
                || !bubble.showFlyout()
                || isStackEduShowing()
                || isStackEduVisible()
                || isExpanded()
                || mIsExpansionAnimating
                || mIsGestureInProgress
@@ -2800,7 +2814,7 @@ public class BubbleStackView extends FrameLayout
     * them.
     */
    public void getTouchableRegion(Rect outRect) {
        if (isStackEduShowing()) {
        if (isStackEduVisible()) {
            // When user education shows then capture all touches
            outRect.set(0, 0, getWidth(), getHeight());
            return;
+25 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
@@ -162,4 +164,27 @@ public class BubbleTest extends ShellTestCase {

        verify(mBubbleMetadataFlagListener, never()).onBubbleMetadataFlagChanged(any());
    }

    @Test
    public void testBubbleIsConversation_hasConversationShortcut() {
        Bubble bubble = createBubbleWithShortcut();
        assertThat(bubble.getShortcutInfo()).isNotNull();
        assertThat(bubble.isConversation()).isTrue();
    }

    @Test
    public void testBubbleIsConversation_hasNoShortcut() {
        Bubble bubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor);
        assertThat(bubble.getShortcutInfo()).isNull();
        assertThat(bubble.isConversation()).isFalse();
    }

    private Bubble createBubbleWithShortcut() {
        ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext)
                .setId("mockShortcutId")
                .build();
        return new Bubble("mockKey", shortcutInfo, 10, Resources.ID_NULL,
                "mockTitle", 0 /* taskId */, "mockLocus", true /* isDismissible */,
                mMainExecutor, mBubbleMetadataFlagListener);
    }
}
+80 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -100,6 +101,7 @@ import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.shade.ShadeWindowLogger;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.NotificationEntryHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -135,6 +137,7 @@ import com.android.wm.shell.bubbles.BubbleLogger;
import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.bubbles.BubbleViewInfoTask;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.bubbles.StackEducationViewKt;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
@@ -1668,6 +1671,60 @@ public class BubblesTest extends SysuiTestCase {
                any(Bubble.class), anyBoolean(), anyBoolean());
    }

    @Test
    public void testShowStackEdu_isNotConversationBubble() {
        // Setup
        setPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION, false);
        BubbleEntry bubbleEntry = createBubbleEntry(false /* isConversation */);
        mBubbleController.updateBubble(bubbleEntry);
        assertTrue(mBubbleController.hasBubbles());

        // Click on bubble
        Bubble bubble = mBubbleData.getBubbleInStackWithKey(bubbleEntry.getKey());
        assertFalse(bubble.isConversation());
        bubble.getIconView().callOnClick();

        // Check education is not shown
        BubbleStackView stackView = mBubbleController.getStackView();
        assertFalse(stackView.isStackEduVisible());
    }

    @Test
    public void testShowStackEdu_isConversationBubble() {
        // Setup
        setPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION, false);
        BubbleEntry bubbleEntry = createBubbleEntry(true /* isConversation */);
        mBubbleController.updateBubble(bubbleEntry);
        assertTrue(mBubbleController.hasBubbles());

        // Click on bubble
        Bubble bubble = mBubbleData.getBubbleInStackWithKey(bubbleEntry.getKey());
        assertTrue(bubble.isConversation());
        bubble.getIconView().callOnClick();

        // Check education is shown
        BubbleStackView stackView = mBubbleController.getStackView();
        assertTrue(stackView.isStackEduVisible());
    }

    @Test
    public void testShowStackEdu_isSeenConversationBubble() {
        // Setup
        setPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION, true);
        BubbleEntry bubbleEntry = createBubbleEntry(true /* isConversation */);
        mBubbleController.updateBubble(bubbleEntry);
        assertTrue(mBubbleController.hasBubbles());

        // Click on bubble
        Bubble bubble = mBubbleData.getBubbleInStackWithKey(bubbleEntry.getKey());
        assertTrue(bubble.isConversation());
        bubble.getIconView().callOnClick();

        // Check education is not shown
        BubbleStackView stackView = mBubbleController.getStackView();
        assertFalse(stackView.isStackEduVisible());
    }

    @Test
    public void testShowOrHideAppBubble_addsAndExpand() {
        assertThat(mBubbleController.isStackExpanded()).isFalse();
@@ -1816,6 +1873,20 @@ public class BubblesTest extends SysuiTestCase {
                mock(Bubbles.PendingIntentCanceledListener.class), new SyncExecutor());
    }

    private BubbleEntry createBubbleEntry(boolean isConversation) {
        NotificationEntry notificationEntry = mNotificationTestHelper.createBubble(mDeleteIntent);
        if (isConversation) {
            ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext)
                    .setId("shortcutId")
                    .build();
            NotificationEntryHelper.modifyRanking(notificationEntry)
                    .setIsConversation(true)
                    .setShortcutInfo(shortcutInfo)
                    .build();
        }
        return mBubblesManager.notifToBubbleEntry(notificationEntry);
    }

    /** Creates a context that will return a PackageManager with specific AppInfo. */
    private Context setUpContextWithPackageManager(String pkg, ApplicationInfo info)
            throws Exception {
@@ -1852,6 +1923,15 @@ public class BubblesTest extends SysuiTestCase {
        bubbleMetadata.setFlags(flags);
    }

    /**
     * Set preferences boolean value for key
     * Used to setup global state for stack view education tests
     */
    private void setPrefBoolean(String key, boolean enabled) {
        mContext.getSharedPreferences(mContext.getPackageName(), Context.MODE_PRIVATE)
                .edit().putBoolean(key, enabled).apply();
    }

    private Notification.BubbleMetadata getMetadata() {
        Intent target = new Intent(mContext, BubblesTestActivity.class);
        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, FLAG_MUTABLE);