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

Commit 2cbab801 authored by Ivan Tkachenko's avatar Ivan Tkachenko Committed by Automerger Merge Worker
Browse files

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

Merge "Show Bubble OOBE on the first conversation bubble only" into udc-dev am: ac5394a4 am: ae5a8d64

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22076642



Change-Id: Ic9a787b13679d79cbc5ea90b984e989e829005fc
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 58153d8d ae5a8d64
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -655,6 +655,13 @@ public class Bubble implements BubbleViewProvider {
        return mIsImportantConversation;
        return mIsImportantConversation;
    }
    }


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

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


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


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


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


                    if (!isStackEduShowing() && mRelativeStackPositionBeforeRotation != null) {
                    if (!isStackEduVisible() && mRelativeStackPositionBeforeRotation != null) {
                        mStackAnimationController.setStackPosition(
                        mStackAnimationController.setStackPosition(
                                mRelativeStackPositionBeforeRotation);
                                mRelativeStackPositionBeforeRotation);
                        mRelativeStackPositionBeforeRotation = null;
                        mRelativeStackPositionBeforeRotation = null;
@@ -1046,9 +1044,9 @@ public class BubbleStackView extends FrameLayout
        setOnClickListener(view -> {
        setOnClickListener(view -> {
            if (mShowingManage) {
            if (mShowingManage) {
                showManageMenu(false /* show */);
                showManageMenu(false /* show */);
            } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
            } else if (isManageEduVisible()) {
                mManageEduView.hide();
                mManageEduView.hide();
            } else if (isStackEduShowing()) {
            } else if (isStackEduVisible()) {
                mStackEduView.hide(false /* isExpanding */);
                mStackEduView.hide(false /* isExpanding */);
            } else if (mBubbleData.isExpanded()) {
            } else if (mBubbleData.isExpanded()) {
                mBubbleData.setExpanded(false);
                mBubbleData.setExpanded(false);
@@ -1246,11 +1244,20 @@ public class BubbleStackView extends FrameLayout
        updateManageButtonListener();
        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.
     * Whether the educational view should show for the expanded view "manage" menu.
     */
     */
    private boolean shouldShowManageEdu() {
    private boolean shouldShowManageEdu() {
        if (ActivityManager.isRunningInTestHarness()) {
        if (!isConversationBubble()) {
            // We only show user education for conversation bubbles right now
            return false;
            return false;
        }
        }
        final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION);
        final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION);
@@ -1273,11 +1280,17 @@ public class BubbleStackView extends FrameLayout
        mManageEduView.show(mExpandedBubble.getExpandedView());
        mManageEduView.show(mExpandedBubble.getExpandedView());
    }
    }


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

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


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


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


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


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


        verify(mBubbleMetadataFlagListener, never()).onBubbleMetadataFlagChanged(any());
        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 Original line Diff line number Diff line
@@ -57,6 +57,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
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.ShadeExpansionStateManager;
import com.android.systemui.shade.ShadeWindowLogger;
import com.android.systemui.shade.ShadeWindowLogger;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.NotificationEntryHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
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.BubbleStackView;
import com.android.wm.shell.bubbles.BubbleViewInfoTask;
import com.android.wm.shell.bubbles.BubbleViewInfoTask;
import com.android.wm.shell.bubbles.Bubbles;
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.DisplayController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
@@ -1668,6 +1671,60 @@ public class BubblesTest extends SysuiTestCase {
                any(Bubble.class), anyBoolean(), anyBoolean());
                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
    @Test
    public void testShowOrHideAppBubble_addsAndExpand() {
    public void testShowOrHideAppBubble_addsAndExpand() {
        assertThat(mBubbleController.isStackExpanded()).isFalse();
        assertThat(mBubbleController.isStackExpanded()).isFalse();
@@ -1816,6 +1873,20 @@ public class BubblesTest extends SysuiTestCase {
                mock(Bubbles.PendingIntentCanceledListener.class), new SyncExecutor());
                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. */
    /** Creates a context that will return a PackageManager with specific AppInfo. */
    private Context setUpContextWithPackageManager(String pkg, ApplicationInfo info)
    private Context setUpContextWithPackageManager(String pkg, ApplicationInfo info)
            throws Exception {
            throws Exception {
@@ -1852,6 +1923,15 @@ public class BubblesTest extends SysuiTestCase {
        bubbleMetadata.setFlags(flags);
        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() {
    private Notification.BubbleMetadata getMetadata() {
        Intent target = new Intent(mContext, BubblesTestActivity.class);
        Intent target = new Intent(mContext, BubblesTestActivity.class);
        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, FLAG_MUTABLE);
        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, FLAG_MUTABLE);