1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.qs.tiles 18 19 import android.os.Handler 20 import android.os.Looper 21 import android.service.quicksettings.Tile 22 import android.testing.TestableLooper 23 import androidx.test.ext.junit.runners.AndroidJUnit4 24 import androidx.test.filters.SmallTest 25 import com.android.internal.logging.MetricsLogger 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.animation.DialogTransitionAnimator 28 import com.android.systemui.classifier.FalsingManagerFake 29 import com.android.systemui.plugins.ActivityStarter 30 import com.android.systemui.plugins.statusbar.StatusBarStateController 31 import com.android.systemui.qs.QSHost 32 import com.android.systemui.qs.QsEventLogger 33 import com.android.systemui.qs.logging.QSLogger 34 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor 35 import com.android.systemui.recordissue.IssueRecordingServiceConnection 36 import com.android.systemui.recordissue.IssueRecordingState 37 import com.android.systemui.recordissue.RecordIssueDialogDelegate 38 import com.android.systemui.recordissue.TraceurConnection 39 import com.android.systemui.res.R 40 import com.android.systemui.screenrecord.RecordingController 41 import com.android.systemui.settings.UserContextProvider 42 import com.android.systemui.statusbar.phone.KeyguardDismissUtil 43 import com.android.systemui.statusbar.phone.SystemUIDialog 44 import com.android.systemui.statusbar.policy.KeyguardStateController 45 import com.android.systemui.util.mockito.any 46 import com.android.systemui.util.mockito.whenever 47 import com.google.common.truth.Truth.assertThat 48 import java.util.concurrent.Executors 49 import org.junit.After 50 import org.junit.Before 51 import org.junit.Test 52 import org.junit.runner.RunWith 53 import org.mockito.ArgumentMatchers.eq 54 import org.mockito.ArgumentMatchers.isA 55 import org.mockito.Mock 56 import org.mockito.Mockito.verify 57 import org.mockito.MockitoAnnotations 58 59 /** 60 * This class tests the functionality of the RecordIssueTile. The initial state of the tile is 61 * always be inactive at the start of these tests. 62 */ 63 @RunWith(AndroidJUnit4::class) 64 @TestableLooper.RunWithLooper(setAsMainLooper = true) 65 @SmallTest 66 class RecordIssueTileTest : SysuiTestCase() { 67 68 @Mock private lateinit var host: QSHost 69 @Mock private lateinit var qsEventLogger: QsEventLogger 70 @Mock private lateinit var metricsLogger: MetricsLogger 71 @Mock private lateinit var statusBarStateController: StatusBarStateController 72 @Mock private lateinit var recordingController: RecordingController 73 @Mock private lateinit var activityStarter: ActivityStarter 74 @Mock private lateinit var qsLogger: QSLogger 75 @Mock private lateinit var keyguardDismissUtil: KeyguardDismissUtil 76 @Mock private lateinit var keyguardStateController: KeyguardStateController 77 @Mock private lateinit var dialogLauncherAnimator: DialogTransitionAnimator 78 @Mock private lateinit var panelInteractor: PanelInteractor 79 @Mock private lateinit var userContextProvider: UserContextProvider 80 @Mock private lateinit var issueRecordingState: IssueRecordingState 81 @Mock private lateinit var delegateFactory: RecordIssueDialogDelegate.Factory 82 @Mock private lateinit var dialogDelegate: RecordIssueDialogDelegate 83 @Mock private lateinit var dialog: SystemUIDialog 84 85 private lateinit var testableLooper: TestableLooper 86 private lateinit var tile: RecordIssueTile 87 private lateinit var irsConnProvider: IssueRecordingServiceConnection.Provider 88 private lateinit var traceurConnProvider: TraceurConnection.Provider 89 90 @Before setUpnull91 fun setUp() { 92 MockitoAnnotations.initMocks(this) 93 whenever(host.context).thenReturn(mContext) 94 whenever(delegateFactory.create(any())).thenReturn(dialogDelegate) 95 whenever(dialogDelegate.createDialog()).thenReturn(dialog) 96 97 irsConnProvider = IssueRecordingServiceConnection.Provider(userContextProvider) 98 traceurConnProvider = 99 TraceurConnection.Provider(userContextProvider, Looper.getMainLooper()) 100 101 testableLooper = TestableLooper.get(this) 102 tile = 103 RecordIssueTile( 104 host, 105 qsEventLogger, 106 testableLooper.looper, 107 Handler(testableLooper.looper), 108 FalsingManagerFake(), 109 metricsLogger, 110 statusBarStateController, 111 activityStarter, 112 qsLogger, 113 keyguardDismissUtil, 114 keyguardStateController, 115 dialogLauncherAnimator, 116 panelInteractor, 117 userContextProvider, 118 irsConnProvider, 119 traceurConnProvider, 120 Executors.newSingleThreadExecutor(), 121 issueRecordingState, 122 delegateFactory, 123 recordingController, 124 ) 125 } 126 127 @After teardownnull128 fun teardown() { 129 tile.destroy() 130 testableLooper.processAllMessages() 131 } 132 133 @Test qsTileUi_shouldLookCorrect_whenInactivenull134 fun qsTileUi_shouldLookCorrect_whenInactive() { 135 whenever(issueRecordingState.isRecording).thenReturn(false) 136 137 val testState = tile.newTileState() 138 tile.handleUpdateState(testState, null) 139 140 assertThat(testState.state).isEqualTo(Tile.STATE_INACTIVE) 141 assertThat(testState.secondaryLabel.toString()) 142 .isEqualTo(mContext.getString(R.string.qs_record_issue_start)) 143 } 144 145 @Test qsTileUi_shouldLookCorrect_whenRecordingnull146 fun qsTileUi_shouldLookCorrect_whenRecording() { 147 whenever(issueRecordingState.isRecording).thenReturn(true) 148 val testState = tile.newTileState() 149 tile.handleUpdateState(testState, null) 150 151 assertThat(testState.state).isEqualTo(Tile.STATE_ACTIVE) 152 assertThat(testState.secondaryLabel.toString()) 153 .isEqualTo(mContext.getString(R.string.qs_record_issue_stop)) 154 } 155 156 @Test inActiveQsTile_switchesToActive_whenClickednull157 fun inActiveQsTile_switchesToActive_whenClicked() { 158 whenever(issueRecordingState.isRecording).thenReturn(false) 159 160 val testState = tile.newTileState() 161 tile.handleUpdateState(testState, null) 162 163 assertThat(testState.state).isEqualTo(Tile.STATE_INACTIVE) 164 } 165 166 @Test activeQsTile_switchesToInActive_whenClickednull167 fun activeQsTile_switchesToInActive_whenClicked() { 168 whenever(issueRecordingState.isRecording).thenReturn(true) 169 170 val testState = tile.newTileState() 171 tile.handleUpdateState(testState, null) 172 173 assertThat(testState.state).isEqualTo(Tile.STATE_ACTIVE) 174 } 175 176 @Test showPrompt_shouldUseKeyguardDismissUtil_ToShowDialognull177 fun showPrompt_shouldUseKeyguardDismissUtil_ToShowDialog() { 178 whenever(issueRecordingState.isRecording).thenReturn(false) 179 180 tile.handleClick(null) 181 testableLooper.processAllMessages() 182 183 verify(keyguardDismissUtil) 184 .executeWhenUnlocked( 185 isA(ActivityStarter.OnDismissAction::class.java), 186 eq(false), 187 eq(true), 188 ) 189 } 190 } 191