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

Commit 6084821a authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Clean up the converted kotlin in NotificationRowContentBinderImplTest

Bug: 343942780
Flag: com.android.systemui.notification_row_content_binder_refactor
Test: atest NotificationRowContentBinderImplTest
Change-Id: Ibeeaa0d18254fe1165b8596332ea719f97cd4530
parent 531ef6d8
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 }
        }
    }
}