package com.android.systemui.controls.management import android.content.ComponentName import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.ServiceInfo import android.graphics.drawable.Drawable import android.os.Bundle import android.testing.TestableLooper import android.view.View import android.widget.Button import android.window.OnBackInvokedCallback import android.window.OnBackInvokedDispatcher import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.rule.ActivityTestRule import com.android.systemui.SysuiTestCase import com.android.systemui.activity.SingleActivityFactory import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.CustomIconCache import com.android.systemui.controls.controller.ControlsControllerImpl import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.utils.SafeIconLoader import com.google.common.truth.Truth.assertThat import java.util.concurrent.CountDownLatch import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.eq import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class ControlsEditingActivityTest : SysuiTestCase() { private companion object { val TEST_COMPONENT = ComponentName("TestPackageName", "TestClassName") val TEST_STRUCTURE: CharSequence = "TestStructure" val TEST_APP: CharSequence = "TestApp" val TEST_UID = 12345 } private val uiExecutor = FakeExecutor(FakeSystemClock()) @Mock lateinit var controller: ControlsControllerImpl @Mock lateinit var userTracker: UserTracker @Mock lateinit var customIconCache: CustomIconCache @Mock lateinit var controlsListingController: ControlsListingController @Mock(answer = Answers.RETURNS_MOCKS) lateinit var safeIconLoaderFactory: SafeIconLoader.Factory private var latch: CountDownLatch = CountDownLatch(1) @Mock private lateinit var mockDispatcher: OnBackInvokedDispatcher @Captor private lateinit var captureCallback: ArgumentCaptor @Rule @JvmField var activityRule = ActivityTestRule( /* activityFactory= */ SingleActivityFactory { TestableControlsEditingActivity( uiExecutor, controller, userTracker, customIconCache, controlsListingController, safeIconLoaderFactory, mockDispatcher, latch, ) }, /* initialTouchMode= */ false, /* launchActivity= */ false, ) @Before fun setUp() { MockitoAnnotations.initMocks(this) val serviceInfo = ControlsServiceInfo(TEST_COMPONENT, "", TEST_UID) `when`(controlsListingController.getCurrentServices()).thenReturn(listOf(serviceInfo)) } @Test fun testBackCallbackRegistrationAndUnregistration() { launchActivity() // 1. ensure that launching the activity results in it registering a callback verify(mockDispatcher) .registerOnBackInvokedCallback( eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), captureCallback.capture(), ) activityRule.finishActivity() latch.await() // ensure activity is finished // 2. ensure that when the activity is finished, it unregisters the same callback verify(mockDispatcher).unregisterOnBackInvokedCallback(captureCallback.value) } @Test fun testAddControlsButton_visible() { with(launchActivity()) { val addControlsButton = requireViewById