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

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

Merge "Clean up the converted kotlin in NotificationRowContentBinderImplTest" into main

parents e84fdcef 6084821a
Loading
Loading
Loading
Loading
+106 −171
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.CancellationSignal
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import android.util.TypedValue
import android.util.TypedValue.COMPLEX_UNIT_SP
import android.view.View
import android.view.ViewGroup
import android.widget.RemoteViews
@@ -34,6 +35,10 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag
import com.android.systemui.statusbar.notification.row.shared.HeadsUpStatusBarModel
@@ -43,7 +48,6 @@ import com.android.systemui.statusbar.notification.row.shared.NotificationRowCon
import com.android.systemui.statusbar.policy.InflatedSmartReplyState
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder
import com.android.systemui.statusbar.policy.SmartReplyStateInflater
import com.android.systemui.util.concurrency.mockExecutorHandler
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
@@ -65,20 +69,24 @@ import org.mockito.kotlin.whenever
@RunWithLooper
@EnableFlags(NotificationRowContentBinderRefactor.FLAG_NAME)
class NotificationRowContentBinderImplTest : SysuiTestCase() {
    private lateinit var mNotificationInflater: NotificationRowContentBinderImpl
    private lateinit var mBuilder: Notification.Builder
    private lateinit var mRow: ExpandableNotificationRow
    private lateinit var mHelper: NotificationTestHelper

    private var mCache: NotifRemoteViewCache = mock()
    private var mConversationNotificationProcessor: ConversationNotificationProcessor = mock()
    private var mInflatedSmartReplyState: InflatedSmartReplyState = mock()
    private var mInflatedSmartReplies: InflatedSmartReplyViewHolder = mock()
    private var mNotifLayoutInflaterFactoryProvider: NotifLayoutInflaterFactory.Provider = mock()
    private var mHeadsUpStyleProvider: HeadsUpStyleProvider = mock()
    private var mNotifLayoutInflaterFactory: NotifLayoutInflaterFactory = mock()
    private val mSmartReplyStateInflater: SmartReplyStateInflater =
    private lateinit var notificationInflater: NotificationRowContentBinderImpl
    private lateinit var builder: Notification.Builder
    private lateinit var row: ExpandableNotificationRow
    private lateinit var testHelper: NotificationTestHelper

    private val cache: NotifRemoteViewCache = mock()
    private val layoutInflaterFactoryProvider =
        object : NotifLayoutInflaterFactory.Provider {
            override fun provide(
                row: ExpandableNotificationRow,
                layoutType: Int
            ): NotifLayoutInflaterFactory = mock()
        }
    private val smartReplyStateInflater: SmartReplyStateInflater =
        object : SmartReplyStateInflater {
            private val inflatedSmartReplyState: InflatedSmartReplyState = mock()
            private val inflatedSmartReplies: InflatedSmartReplyViewHolder = mock()

            override fun inflateSmartReplyViewHolder(
                sysuiContext: Context,
                notifPackageContext: Context,
@@ -86,37 +94,34 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
                existingSmartReplyState: InflatedSmartReplyState?,
                newSmartReplyState: InflatedSmartReplyState
            ): InflatedSmartReplyViewHolder {
                return mInflatedSmartReplies
                return inflatedSmartReplies
            }

            override fun inflateSmartReplyState(entry: NotificationEntry): InflatedSmartReplyState {
                return mInflatedSmartReplyState
                return inflatedSmartReplyState
            }
        }

    @Before
    fun setUp() {
        allowTestableLooperAsMainThread()
        mBuilder =
        builder =
            Notification.Builder(mContext, "no-id")
                .setSmallIcon(R.drawable.ic_person)
                .setContentTitle("Title")
                .setContentText("Text")
                .setStyle(Notification.BigTextStyle().bigText("big text"))
        mHelper = NotificationTestHelper(mContext, mDependency)
        val row = mHelper.createRow(mBuilder.build())
        mRow = spy(row)
        whenever(mNotifLayoutInflaterFactoryProvider.provide(any(), any()))
            .thenReturn(mNotifLayoutInflaterFactory)
        mNotificationInflater =
        testHelper = NotificationTestHelper(mContext, mDependency)
        row = spy(testHelper.createRow(builder.build()))
        notificationInflater =
            NotificationRowContentBinderImpl(
                mCache,
                cache,
                mock(),
                mConversationNotificationProcessor,
                mock<ConversationNotificationProcessor>(),
                mock(),
                mSmartReplyStateInflater,
                mNotifLayoutInflaterFactoryProvider,
                mHeadsUpStyleProvider,
                smartReplyStateInflater,
                layoutInflaterFactoryProvider,
                mock<HeadsUpStyleProvider>(),
                mock()
            )
    }
@@ -125,16 +130,16 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
    fun testIncreasedHeadsUpBeingUsed() {
        val params = BindParams()
        params.usesIncreasedHeadsUpHeight = true
        val builder = spy(mBuilder)
        mNotificationInflater.inflateNotificationViews(
            mRow.entry,
            mRow,
        val builder = spy(builder)
        notificationInflater.inflateNotificationViews(
            row.entry,
            row,
            params,
            true /* inflateSynchronously */,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
            FLAG_CONTENT_VIEW_ALL,
            builder,
            mContext,
            mSmartReplyStateInflater
            smartReplyStateInflater
        )
        verify(builder).createHeadsUpContentView(true)
    }
@@ -143,80 +148,68 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
    fun testIncreasedHeightBeingUsed() {
        val params = BindParams()
        params.usesIncreasedHeight = true
        val builder = spy(mBuilder)
        mNotificationInflater.inflateNotificationViews(
            mRow.entry,
            mRow,
        val builder = spy(builder)
        notificationInflater.inflateNotificationViews(
            row.entry,
            row,
            params,
            true /* inflateSynchronously */,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
            FLAG_CONTENT_VIEW_ALL,
            builder,
            mContext,
            mSmartReplyStateInflater
            smartReplyStateInflater
        )
        verify(builder).createContentView(true)
    }

    @Test
    fun testInflationCallsUpdated() {
        inflateAndWait(
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
            mRow
        )
        verify(mRow).onNotificationUpdated()
        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
        verify(row).onNotificationUpdated()
    }

    @Test
    fun testInflationOnlyInflatesSetFlags() {
        inflateAndWait(
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP,
            mRow
        )
        Assert.assertNotNull(mRow.privateLayout.headsUpChild)
        verify(mRow).onNotificationUpdated()
        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, row)
        Assert.assertNotNull(row.privateLayout.headsUpChild)
        verify(row).onNotificationUpdated()
    }

    @Test
    fun testInflationThrowsErrorDoesntCallUpdated() {
        mRow.privateLayout.removeAllViews()
        mRow.entry.sbn.notification.contentView =
        row.privateLayout.removeAllViews()
        row.entry.sbn.notification.contentView =
            RemoteViews(mContext.packageName, R.layout.status_bar)
        inflateAndWait(
            true /* expectingException */,
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
            mRow
            notificationInflater,
            FLAG_CONTENT_VIEW_ALL,
            row
        )
        Assert.assertTrue(mRow.privateLayout.childCount == 0)
        verify(mRow, times(0)).onNotificationUpdated()
        Assert.assertTrue(row.privateLayout.childCount == 0)
        verify(row, times(0)).onNotificationUpdated()
    }

    @Test
    fun testAsyncTaskRemoved() {
        mRow.entry.abortTask()
        inflateAndWait(
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
            mRow
        )
        verify(mRow).onNotificationUpdated()
        row.entry.abortTask()
        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
        verify(row).onNotificationUpdated()
    }

    @Test
    fun testRemovedNotInflated() {
        mRow.setRemoved()
        mNotificationInflater.setInflateSynchronously(true)
        mNotificationInflater.bindContent(
            mRow.entry,
            mRow,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
        row.setRemoved()
        notificationInflater.setInflateSynchronously(true)
        notificationInflater.bindContent(
            row.entry,
            row,
            FLAG_CONTENT_VIEW_ALL,
            BindParams(),
            false /* forceInflate */,
            null /* callback */
        )
        Assert.assertNull(mRow.entry.runningTask)
        Assert.assertNull(row.entry.runningTask)
    }

    @Test
@@ -235,11 +228,11 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
            inflateSynchronously = false,
            isMinimized = false,
            result = result,
            reInflateFlags = NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED,
            reInflateFlags = FLAG_CONTENT_VIEW_EXPANDED,
            inflationId = 0,
            remoteViewCache = mock(),
            entry = mRow.entry,
            row = mRow,
            entry = row.entry,
            row = row,
            isNewView = true, /* isNewView */
            remoteViewClickHandler = { _, _, _ -> true },
            callback =
@@ -253,7 +246,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
                        countDownLatch.countDown()
                    }
                },
            parentLayout = mRow.privateLayout,
            parentLayout = row.privateLayout,
            existingView = null,
            existingWrapper = null,
            runningInflations = HashMap(),
@@ -275,13 +268,13 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {

    @Test
    fun doesntReapplyDisallowedRemoteView() {
        mBuilder.setStyle(Notification.MediaStyle())
        val mediaView = mBuilder.createContentView()
        mBuilder.setStyle(Notification.DecoratedCustomViewStyle())
        mBuilder.setCustomContentView(
        builder.setStyle(Notification.MediaStyle())
        val mediaView = builder.createContentView()
        builder.setStyle(Notification.DecoratedCustomViewStyle())
        builder.setCustomContentView(
            RemoteViews(context.packageName, com.android.systemui.tests.R.layout.custom_view_dark)
        )
        val decoratedMediaView = mBuilder.createContentView()
        val decoratedMediaView = builder.createContentView()
        Assert.assertFalse(
            "The decorated media style doesn't allow a view to be reapplied!",
            NotificationRowContentBinderImpl.canReapplyRemoteView(mediaView, decoratedMediaView)
@@ -292,112 +285,65 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
    @Ignore("b/345418902")
    fun testUsesSameViewWhenCachedPossibleToReuse() {
        // GIVEN a cached view.
        val contractedRemoteView = mBuilder.createContentView()
        whenever(
                mCache.hasCachedView(
                    mRow.entry,
                    NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
                )
            )
            .thenReturn(true)
        whenever(
                mCache.getCachedView(
                    mRow.entry,
                    NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
                )
            )
        val contractedRemoteView = builder.createContentView()
        whenever(cache.hasCachedView(row.entry, FLAG_CONTENT_VIEW_CONTRACTED)).thenReturn(true)
        whenever(cache.getCachedView(row.entry, FLAG_CONTENT_VIEW_CONTRACTED))
            .thenReturn(contractedRemoteView)

        // GIVEN existing bound view with same layout id.
        val view = contractedRemoteView.apply(mContext, null /* parent */)
        mRow.privateLayout.setContractedChild(view)
        row.privateLayout.setContractedChild(view)

        // WHEN inflater inflates
        inflateAndWait(
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED,
            mRow
        )
        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row)

        // THEN the view should be re-used
        Assert.assertEquals(
            "Binder inflated a new view even though the old one was cached and usable.",
            view,
            mRow.privateLayout.contractedChild
            row.privateLayout.contractedChild
        )
    }

    @Test
    fun testInflatesNewViewWhenCachedNotPossibleToReuse() {
        // GIVEN a cached remote view.
        val contractedRemoteView = mBuilder.createHeadsUpContentView()
        whenever(
                mCache.hasCachedView(
                    mRow.entry,
                    NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
                )
            )
            .thenReturn(true)
        whenever(
                mCache.getCachedView(
                    mRow.entry,
                    NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
                )
            )
        val contractedRemoteView = builder.createHeadsUpContentView()
        whenever(cache.hasCachedView(row.entry, FLAG_CONTENT_VIEW_CONTRACTED)).thenReturn(true)
        whenever(cache.getCachedView(row.entry, FLAG_CONTENT_VIEW_CONTRACTED))
            .thenReturn(contractedRemoteView)

        // GIVEN existing bound view with different layout id.
        val view: View = TextView(mContext)
        mRow.privateLayout.setContractedChild(view)
        row.privateLayout.setContractedChild(view)

        // WHEN inflater inflates
        inflateAndWait(
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED,
            mRow
        )
        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row)

        // THEN the view should be a new view
        Assert.assertNotEquals(
            "Binder (somehow) used the same view when inflating.",
            view,
            mRow.privateLayout.contractedChild
            row.privateLayout.contractedChild
        )
    }

    @Test
    fun testInflationCachesCreatedRemoteView() {
        // WHEN inflater inflates
        inflateAndWait(
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED,
            mRow
        )
        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row)

        // THEN inflater informs cache of the new remote view
        verify(mCache)
            .putCachedView(
                eq(mRow.entry),
                eq(NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED),
                any()
            )
        verify(cache).putCachedView(eq(row.entry), eq(FLAG_CONTENT_VIEW_CONTRACTED), any())
    }

    @Test
    fun testUnbindRemovesCachedRemoteView() {
        // WHEN inflated unbinds content
        mNotificationInflater.unbindContent(
            mRow.entry,
            mRow,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
        )
        notificationInflater.unbindContent(row.entry, row, FLAG_CONTENT_VIEW_HEADS_UP)

        // THEN inflated informs cache to remove remote view
        verify(mCache)
            .removeCachedView(
                eq(mRow.entry),
                eq(NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP)
            )
        verify(cache).removeCachedView(eq(row.entry), eq(FLAG_CONTENT_VIEW_HEADS_UP))
    }

    @Test
@@ -453,46 +399,36 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
        whenever(view.measuredHeight)
            .thenReturn(
                TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_SP,
                        COMPLEX_UNIT_SP,
                        measuredHeightDp,
                        mContext.resources.displayMetrics
                    )
                    .toInt()
            )
        mRow.entry.targetSdk = targetSdk
        mRow.entry.sbn.notification.contentView = contentView
        return NotificationRowContentBinderImpl.isValidView(view, mRow.entry, mContext.resources)
        row.entry.targetSdk = targetSdk
        row.entry.sbn.notification.contentView = contentView
        return NotificationRowContentBinderImpl.isValidView(view, row.entry, mContext.resources)
    }

    @Test
    fun testInvalidNotificationDoesNotInvokeCallback() {
        mRow.privateLayout.removeAllViews()
        mRow.entry.sbn.notification.contentView =
        row.privateLayout.removeAllViews()
        row.entry.sbn.notification.contentView =
            RemoteViews(
                mContext.packageName,
                com.android.systemui.tests.R.layout.invalid_notification_height
            )
        inflateAndWait(
            true,
            mNotificationInflater,
            NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL,
            mRow
        )
        Assert.assertEquals(0, mRow.privateLayout.childCount.toLong())
        verify(mRow, times(0)).onNotificationUpdated()
        inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
        Assert.assertEquals(0, row.privateLayout.childCount.toLong())
        verify(row, times(0)).onNotificationUpdated()
    }

    private class ExceptionHolder {
        var mException: Exception? = null

        fun setException(exception: Exception?) {
            mException = exception
        }
        var exception: Exception? = null
    }

    private class AsyncFailRemoteView(packageName: String?, layoutId: Int) :
        RemoteViews(packageName, layoutId) {
        var mHandler = mockExecutorHandler { p0 -> p0.run() }

        override fun apply(context: Context, parent: ViewGroup): View {
            return super.apply(context, parent)
@@ -505,7 +441,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
            listener: OnViewAppliedListener,
            handler: InteractionHandler?
        ): CancellationSignal {
            mHandler.post { listener.onError(RuntimeException("Failed to inflate async")) }
            executor.execute { listener.onError(RuntimeException("Failed to inflate async")) }
            return CancellationSignal()
        }

@@ -541,18 +477,17 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
                object : InflationCallback {
                    override fun handleInflationException(entry: NotificationEntry, e: Exception) {
                        if (!expectingException) {
                            exceptionHolder.setException(e)
                            exceptionHolder.exception = e
                        }
                        countDownLatch.countDown()
                    }

                    override fun onAsyncInflationFinished(entry: NotificationEntry) {
                        if (expectingException) {
                            exceptionHolder.setException(
                            exceptionHolder.exception =
                                RuntimeException(
                                    "Inflation finished even though there should be an error"
                                )
                            )
                        }
                        countDownLatch.countDown()
                    }
@@ -566,7 +501,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
                callback /* callback */
            )
            Assert.assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS))
            exceptionHolder.mException?.let { throw it }
            exceptionHolder.exception?.let { throw it }
        }
    }
}