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

Commit 83bdb759 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Migrate remoteinput to entryadapter" into main

parents e65271a8 c3e1eecf
Loading
Loading
Loading
Loading
+120 −4
Original line number Diff line number Diff line
@@ -20,16 +20,29 @@ import static com.android.systemui.log.LogBufferHelperKt.logcatLogBuffer;

import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.ActivityOptions;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.os.UserHandle;
import android.platform.test.flag.junit.FlagsParameterization;
import android.testing.TestableLooper;
import android.util.Pair;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RemoteViews;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
@@ -42,19 +55,37 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.util.kotlin.JavaAdapter;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWith(ParameterizedAndroidJunit4.class)
@TestableLooper.RunWithLooper
public class NotificationRemoteInputManagerTest extends SysuiTestCase {

    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return FlagsParameterization.allCombinationsOf(NotificationBundleUi.FLAG_NAME);
    }

    private static final String TEST_PACKAGE_NAME = "test";
    private static final int TEST_UID = 0;

@@ -69,14 +100,34 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
    @Mock private NotificationClickNotifier mClickNotifier;
    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
    @Mock private PowerInteractor mPowerInteractor;
    @Mock
    NotificationRemoteInputManager.RemoteInputListener mRemoteInputListener;
    private ActionClickLogger mActionClickLogger;
    @Captor
    ArgumentCaptor<NotificationRemoteInputManager.ClickHandler> mClickHandlerArgumentCaptor;
    private Context mSpyContext;

    private NotificationTestHelper mTestHelper;
    private TestableNotificationRemoteInputManager mRemoteInputManager;
    private NotificationEntry mEntry;

   public NotificationRemoteInputManagerTest(FlagsParameterization flags) {
       super();
       mSetFlagsRule.setFlagsParameterization(flags);
   }

    @Before
    public void setUp() {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mSpyContext = spy(mContext);
        doNothing().when(mSpyContext).startIntentSender(
                any(), any(), anyInt(), anyInt(), anyInt(), any());


        mTestHelper = new NotificationTestHelper(mSpyContext, mDependency);
        mActionClickLogger = spy(new ActionClickLogger(logcatLogBuffer()));

        mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext,
                mock(NotifPipelineFlags.class),
                mLockscreenUserManager,
@@ -87,9 +138,10 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
                mRemoteInputUriController,
                new RemoteInputControllerLogger(logcatLogBuffer()),
                mClickNotifier,
                new ActionClickLogger(logcatLogBuffer()),
                mActionClickLogger,
                mock(JavaAdapter.class),
                mock(ShadeInteractor.class));
        mRemoteInputManager.setRemoteInputListener(mRemoteInputListener);
        mEntry = new NotificationEntryBuilder()
                .setPkg(TEST_PACKAGE_NAME)
                .setOpPkg(TEST_PACKAGE_NAME)
@@ -133,6 +185,70 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
        assertTrue(mRemoteInputManager.shouldKeepForSmartReplyHistory(mEntry));
    }

    @Test
    public void testActionClick() throws Exception {
        RemoteViews.RemoteResponse response = mock(RemoteViews.RemoteResponse.class);
        when(response.getLaunchOptions(any())).thenReturn(
                Pair.create(mock(Intent.class), mock(ActivityOptions.class)));
        ExpandableNotificationRow row = getRowWithReplyAction();
        View actionView = ((LinearLayout) row.getPrivateLayout().getExpandedChild().findViewById(
                com.android.internal.R.id.actions)).getChildAt(0);
        Notification n = getNotification(row);
        CountDownLatch latch = new CountDownLatch(1);
        Consumer<NotificationEntry> consumer = notificationEntry -> latch.countDown();
        if (!NotificationBundleUi.isEnabled()) {
            mRemoteInputManager.addActionPressListener(consumer);
        }

        mRemoteInputManager.getRemoteViewsOnClickHandler().onInteraction(
                actionView,
                n.actions[0].actionIntent,
                response);

        verify(mActionClickLogger).logInitialClick(row.getKey(), 0, n.actions[0].actionIntent);
        verify(mClickNotifier).onNotificationActionClick(
                eq(row.getKey()), eq(0), eq(n.actions[0]), any(), eq(false));
        verify(mCallback).handleRemoteViewClick(eq(actionView), eq(n.actions[0].actionIntent),
                eq(false), eq(0), mClickHandlerArgumentCaptor.capture());

        mClickHandlerArgumentCaptor.getValue().handleClick();
        verify(mActionClickLogger).logStartingIntentWithDefaultHandler(
                row.getKey(), n.actions[0].actionIntent, 0);

        verify(mRemoteInputListener).releaseNotificationIfKeptForRemoteInputHistory(row.getKey());
        if (NotificationBundleUi.isEnabled()) {
            verify(row.getEntryAdapter()).onNotificationActionClicked();
        } else {
            latch.await(10, TimeUnit.MILLISECONDS);
        }
    }

    private Notification getNotification(ExpandableNotificationRow row) {
        if (NotificationBundleUi.isEnabled()) {
            return row.getEntryAdapter().getSbn().getNotification();
        } else {
            return row.getEntry().getSbn().getNotification();
        }
    }

    private ExpandableNotificationRow getRowWithReplyAction() throws Exception {
        PendingIntent pi = PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
                PendingIntent.FLAG_IMMUTABLE);
        Notification n = new Notification.Builder(mSpyContext, "")
                .setSmallIcon(com.android.systemui.res.R.drawable.ic_person)
                .addAction(new Notification.Action(com.android.systemui.res.R.drawable.ic_person,
                        "reply", pi))
                .build();
        ExpandableNotificationRow row = mTestHelper.createRow(n);
        row.onNotificationUpdated();
        row.getPrivateLayout().setExpandedChild(Notification.Builder.recoverBuilder(mSpyContext, n)
                .createBigContentView().apply(
                        mSpyContext,
                        row.getPrivateLayout(),
                        mRemoteInputManager.getRemoteViewsOnClickHandler()));
        return row;
    }

    private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {

        TestableNotificationRemoteInputManager(
+20 −7
Original line number Diff line number Diff line
@@ -29,8 +29,10 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.res.R
import com.android.systemui.statusbar.RankingBuilder
import com.android.systemui.statusbar.notification.mockNotificationActivityStarter
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.entryAdapterFactory
import com.android.systemui.statusbar.notification.row.mockNotificationActionClickManager
import com.android.systemui.statusbar.notification.shared.NotificationBundleUi
import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
import com.android.systemui.testKosmos
@@ -355,16 +357,27 @@ class NotificationEntryAdapterTest : SysuiTestCase() {
        val notification: Notification =
            Notification.Builder(mContext, "").setSmallIcon(R.drawable.ic_person).build()

        val entry =
            NotificationEntryBuilder()
                .setNotification(notification)
                .setImportance(NotificationManager.IMPORTANCE_MIN)
                .build()
        val entry = NotificationEntryBuilder().setNotification(notification).build()

        underTest = factory.create(entry) as NotificationEntryAdapter

        underTest.onNotificationBubbleIconClicked()
        verify((factory as? EntryAdapterFactoryImpl)?.getNotificationActivityStarter())
            ?.onNotificationBubbleIconClicked(entry)
        verify(kosmos.mockNotificationActivityStarter).onNotificationBubbleIconClicked(entry)
    }

    @Test
    @EnableFlags(NotificationBundleUi.FLAG_NAME)
    fun onNotificationActionClicked() {
        val notification: Notification =
            Notification.Builder(mContext, "")
                .setSmallIcon(R.drawable.ic_person)
                .addAction(Mockito.mock(Notification.Action::class.java))
                .build()

        val entry = NotificationEntryBuilder().setNotification(notification).build()

        underTest = factory.create(entry) as NotificationEntryAdapter
        underTest.onNotificationActionClicked()
        verify(kosmos.mockNotificationActionClickManager).onNotificationActionClicked(entry)
    }
}
+12 −3
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderWrapper.DecisionImpl
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderWrapper.FullScreenIntentDecisionImpl
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider
import com.android.systemui.statusbar.notification.row.mockNotificationActionClickManager
import com.android.systemui.statusbar.notification.shared.NotificationBundleUi
import com.android.systemui.statusbar.phone.NotificationGroupTestHelper
import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.FakeExecutor
@@ -138,6 +140,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
                headsUpViewBinder,
                visualInterruptionDecisionProvider,
                remoteInputManager,
                kosmos.mockNotificationActionClickManager,
                launchFullScreenIntentProvider,
                flags,
                statusBarNotificationChipsInteractor,
@@ -161,9 +164,15 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
            verify(notifPipeline).addOnBeforeFinalizeFilterListener(capture())
        }
        onHeadsUpChangedListener = withArgCaptor { verify(headsUpManager).addListener(capture()) }
        actionPressListener = withArgCaptor {
        actionPressListener = if (NotificationBundleUi.isEnabled) {
            withArgCaptor {
                verify(kosmos.mockNotificationActionClickManager).addActionClickListener(capture())
            }
        } else {
            withArgCaptor {
                verify(remoteInputManager).addActionPressListener(capture())
            }
        }
        given(headsUpManager.allEntries).willAnswer { huns.stream() }
        given(headsUpManager.isHeadsUpEntry(anyString())).willAnswer { invocation ->
            val key = invocation.getArgument<String>(0)
@@ -260,7 +269,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
        addHUN(entry)

        actionPressListener.accept(entry)
        verify(headsUpManager, times(1)).setUserActionMayIndirectlyRemove(entry)
        verify(headsUpManager, times(1)).setUserActionMayIndirectlyRemove(entry.key)

        whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(true)
        assertFalse(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
+1 −1
Original line number Diff line number Diff line
@@ -1071,7 +1071,7 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : SysuiTestCase() {

        assertThat(underTest.canRemoveImmediately(notifEntry.key)).isFalse()

        underTest.setUserActionMayIndirectlyRemove(notifEntry)
        underTest.setUserActionMayIndirectlyRemove(notifEntry.key)

        assertThat(underTest.canRemoveImmediately(notifEntry.key)).isTrue()
    }
+4 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -743,11 +744,12 @@ public class NotificationTestHelper {
                mock(MetricsLogger.class),
                mock(PeopleNotificationIdentifier.class),
                mock(NotificationIconStyleProvider.class),
                mock(VisualStabilityCoordinator.class)
                mock(VisualStabilityCoordinator.class),
                mock(NotificationActionClickManager.class)
        ).create(entry);

        row.initialize(
                entryAdapter,
                spy(entryAdapter),
                entry,
                mock(RemoteInputViewSubcomponent.Factory.class),
                APP_NAME,
Loading