1 /*
2  * Copyright (C) 2022 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.mediaprojection.permission
18 
19 import android.app.AlertDialog
20 import android.media.projection.MediaProjectionConfig
21 import android.testing.TestableLooper
22 import android.view.WindowManager
23 import android.widget.Spinner
24 import android.widget.TextView
25 import androidx.test.ext.junit.runners.AndroidJUnit4
26 import androidx.test.filters.SmallTest
27 import com.android.systemui.SysuiTestCase
28 import com.android.systemui.flags.FeatureFlagsClassic
29 import com.android.systemui.flags.Flags
30 import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
31 import com.android.systemui.res.R
32 import com.android.systemui.statusbar.phone.AlertDialogWithDelegate
33 import com.android.systemui.statusbar.phone.SystemUIDialog
34 import com.android.systemui.util.mockito.mock
35 import junit.framework.Assert.assertEquals
36 import org.junit.After
37 import org.junit.Before
38 import org.junit.Test
39 import org.junit.runner.RunWith
40 import org.mockito.Mockito.`when` as whenever
41 
42 @SmallTest
43 @RunWith(AndroidJUnit4::class)
44 @TestableLooper.RunWithLooper(setAsMainLooper = true)
45 class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
46 
47     private lateinit var dialog: AlertDialog
48 
49     private val flags = mock<FeatureFlagsClassic>()
50     private val onStartRecordingClicked = mock<Runnable>()
51     private val mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>()
52 
53     private val mediaProjectionConfig: MediaProjectionConfig =
54         MediaProjectionConfig.createConfigForDefaultDisplay()
55     private val appName: String = "testApp"
56     private val hostUid: Int = 12345
57 
58     private val resIdSingleApp = R.string.screen_share_permission_dialog_option_single_app
59     private val resIdFullScreen = R.string.screen_share_permission_dialog_option_entire_screen
60     private val resIdSingleAppDisabled =
61         R.string.media_projection_entry_app_permission_dialog_single_app_disabled
62 
63     @Before
setUpnull64     fun setUp() {
65         whenever(flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)).thenReturn(true)
66     }
67 
68     @After
teardownnull69     fun teardown() {
70         if (::dialog.isInitialized) {
71             dialog.dismiss()
72         }
73     }
74 
75     @Test
showDialog_forceShowPartialScreenShareFalsenull76     fun showDialog_forceShowPartialScreenShareFalse() {
77         // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and
78         // overrideDisableSingleAppOption = false
79         val overrideDisableSingleAppOption = false
80         setUpAndShowDialog(overrideDisableSingleAppOption)
81 
82         val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner)
83         val secondOptionText =
84             spinner.adapter
85                 .getDropDownView(1, null, spinner)
86                 .findViewById<TextView>(android.R.id.text2)
87                 ?.text
88 
89         // check that the first option is full screen and enabled
90         assertEquals(context.getString(resIdFullScreen), spinner.selectedItem)
91 
92         // check that the second option is single app and disabled
93         assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionText)
94     }
95 
96     @Test
showDialog_forceShowPartialScreenShareTruenull97     fun showDialog_forceShowPartialScreenShareTrue() {
98         // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and
99         // overrideDisableSingleAppOption = true
100         val overrideDisableSingleAppOption = true
101         setUpAndShowDialog(overrideDisableSingleAppOption)
102 
103         val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner)
104         val secondOptionText =
105             spinner.adapter
106                 .getDropDownView(1, null, spinner)
107                 .findViewById<TextView>(android.R.id.text1)
108                 ?.text
109 
110         // check that the first option is single app and enabled
111         assertEquals(context.getString(resIdSingleApp), spinner.selectedItem)
112 
113         // check that the second option is full screen and enabled
114         assertEquals(context.getString(resIdFullScreen), secondOptionText)
115     }
116 
setUpAndShowDialognull117     private fun setUpAndShowDialog(overrideDisableSingleAppOption: Boolean) {
118         val delegate =
119             MediaProjectionPermissionDialogDelegate(
120                 context,
121                 mediaProjectionConfig,
122                 {},
123                 onStartRecordingClicked,
124                 appName,
125                 overrideDisableSingleAppOption,
126                 hostUid,
127                 mediaProjectionMetricsLogger
128             )
129 
130         dialog = AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate)
131         SystemUIDialog.applyFlags(dialog)
132         SystemUIDialog.setDialogSize(dialog)
133 
134         dialog.window?.addSystemFlags(
135             WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS
136         )
137 
138         delegate.onCreate(dialog, savedInstanceState = null)
139         dialog.show()
140     }
141 }
142