1 /*
2  * Copyright (C) 2024 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.impl.sensorprivacy.ui
18 
19 import android.graphics.drawable.TestStubDrawable
20 import android.hardware.SensorPrivacyManager.Sensors.CAMERA
21 import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
22 import android.widget.Switch
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import androidx.test.filters.SmallTest
25 import com.android.systemui.SysuiTestCase
26 import com.android.systemui.common.shared.model.Icon
27 import com.android.systemui.kosmos.Kosmos
28 import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
29 import com.android.systemui.qs.tiles.impl.sensorprivacy.domain.model.SensorPrivacyToggleTileModel
30 import com.android.systemui.qs.tiles.impl.sensorprivacy.qsCameraSensorPrivacyToggleTileConfig
31 import com.android.systemui.qs.tiles.impl.sensorprivacy.qsMicrophoneSensorPrivacyToggleTileConfig
32 import com.android.systemui.qs.tiles.impl.sensorprivacy.ui.SensorPrivacyTileResources.CameraPrivacyTileResources
33 import com.android.systemui.qs.tiles.impl.sensorprivacy.ui.SensorPrivacyTileResources.MicrophonePrivacyTileResources
34 import com.android.systemui.qs.tiles.viewmodel.QSTileState
35 import com.android.systemui.res.R
36 import org.junit.Test
37 import org.junit.runner.RunWith
38 
39 @SmallTest
40 @RunWith(AndroidJUnit4::class)
41 class SensorPrivacyToggleTileMapperTest : SysuiTestCase() {
42     private val kosmos = Kosmos()
43     private val cameraConfig = kosmos.qsCameraSensorPrivacyToggleTileConfig
44     private val micConfig = kosmos.qsMicrophoneSensorPrivacyToggleTileConfig
45 
46     @Test
mapCamera_notBlockednull47     fun mapCamera_notBlocked() {
48         val mapper = createMapper(CameraPrivacyTileResources)
49         val inputModel = SensorPrivacyToggleTileModel(false)
50 
51         val outputState = mapper.map(cameraConfig, inputModel)
52 
53         val expectedState =
54             createSensorPrivacyToggleTileState(
55                 QSTileState.ActivationState.ACTIVE,
56                 context.getString(R.string.quick_settings_camera_mic_available),
57                 R.drawable.qs_camera_access_icon_on,
58                 null,
59                 CAMERA,
60             )
61         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
62     }
63 
64     @Test
mapCamera_blockednull65     fun mapCamera_blocked() {
66         val mapper = createMapper(CameraPrivacyTileResources)
67         val inputModel = SensorPrivacyToggleTileModel(true)
68 
69         val outputState = mapper.map(cameraConfig, inputModel)
70 
71         val expectedState =
72             createSensorPrivacyToggleTileState(
73                 QSTileState.ActivationState.INACTIVE,
74                 context.getString(R.string.quick_settings_camera_mic_blocked),
75                 R.drawable.qs_camera_access_icon_off,
76                 null,
77                 CAMERA,
78             )
79         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
80     }
81 
82     @Test
mapMic_notBlockednull83     fun mapMic_notBlocked() {
84         val mapper = createMapper(MicrophonePrivacyTileResources)
85         val inputModel = SensorPrivacyToggleTileModel(false)
86 
87         val outputState = mapper.map(micConfig, inputModel)
88 
89         val expectedState =
90             createSensorPrivacyToggleTileState(
91                 QSTileState.ActivationState.ACTIVE,
92                 context.getString(R.string.quick_settings_camera_mic_available),
93                 R.drawable.qs_mic_access_on,
94                 null,
95                 MICROPHONE,
96             )
97         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
98     }
99 
100     @Test
mapMic_blockednull101     fun mapMic_blocked() {
102         val mapper = createMapper(MicrophonePrivacyTileResources)
103         val inputModel = SensorPrivacyToggleTileModel(true)
104 
105         val outputState = mapper.map(micConfig, inputModel)
106 
107         val expectedState =
108             createSensorPrivacyToggleTileState(
109                 QSTileState.ActivationState.INACTIVE,
110                 context.getString(R.string.quick_settings_camera_mic_blocked),
111                 R.drawable.qs_mic_access_off,
112                 null,
113                 MICROPHONE,
114             )
115         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
116     }
117 
createMappernull118     private fun createMapper(
119         sensorResources: SensorPrivacyTileResources
120     ): SensorPrivacyToggleTileMapper {
121         val mapper =
122             SensorPrivacyToggleTileMapper(
123                 context.orCreateTestableResources
124                     .apply {
125                         addOverride(R.drawable.qs_camera_access_icon_off, TestStubDrawable())
126                         addOverride(R.drawable.qs_camera_access_icon_on, TestStubDrawable())
127                         addOverride(R.drawable.qs_mic_access_off, TestStubDrawable())
128                         addOverride(R.drawable.qs_mic_access_on, TestStubDrawable())
129                     }
130                     .resources,
131                 context.theme,
132                 sensorResources,
133             )
134         return mapper
135     }
136 
createSensorPrivacyToggleTileStatenull137     private fun createSensorPrivacyToggleTileState(
138         activationState: QSTileState.ActivationState,
139         secondaryLabel: String,
140         iconRes: Int,
141         stateDescription: CharSequence?,
142         sensorId: Int,
143     ): QSTileState {
144         val label =
145             if (sensorId == CAMERA) context.getString(R.string.quick_settings_camera_label)
146             else context.getString(R.string.quick_settings_mic_label)
147 
148         return QSTileState(
149             Icon.Loaded(context.getDrawable(iconRes)!!, null),
150             iconRes,
151             label,
152             activationState,
153             secondaryLabel,
154             setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK),
155             label,
156             stateDescription,
157             QSTileState.SideViewIcon.None,
158             QSTileState.EnabledState.ENABLED,
159             Switch::class.qualifiedName,
160         )
161     }
162 }
163