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.settings.accessibility;
18 
19 import static android.hardware.camera2.CameraCharacteristics.FLASH_INFO_AVAILABLE;
20 import static android.hardware.camera2.CameraCharacteristics.LENS_FACING;
21 import static android.hardware.camera2.CameraCharacteristics.LENS_FACING_BACK;
22 import static android.hardware.camera2.CameraMetadata.LENS_FACING_FRONT;
23 
24 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
25 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
26 import static com.android.settings.accessibility.FlashNotificationsUtil.getColorDescriptionText;
27 import static com.android.settings.accessibility.FlashNotificationsUtil.getFlashNotificationsState;
28 import static com.android.settings.accessibility.FlashNotificationsUtil.getScreenColor;
29 import static com.android.settings.accessibility.FlashNotificationsUtil.isTorchAvailable;
30 
31 import static com.google.common.truth.Truth.assertThat;
32 
33 import static org.junit.Assert.assertThrows;
34 import static org.mockito.Mockito.when;
35 import static org.robolectric.shadow.api.Shadow.extract;
36 import static org.robolectric.shadows.ShadowCameraCharacteristics.newCameraCharacteristics;
37 
38 import android.content.ContentResolver;
39 import android.content.Context;
40 import android.hardware.camera2.CameraAccessException;
41 import android.hardware.camera2.CameraCharacteristics;
42 import android.hardware.camera2.CameraManager;
43 import android.provider.Settings;
44 
45 import androidx.test.core.app.ApplicationProvider;
46 
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.MockitoAnnotations;
52 import org.mockito.Spy;
53 import org.mockito.junit.MockitoJUnit;
54 import org.mockito.junit.MockitoRule;
55 import org.robolectric.RobolectricTestRunner;
56 import org.robolectric.Shadows;
57 import org.robolectric.shadows.ShadowCameraCharacteristics;
58 import org.robolectric.shadows.ShadowCameraManager;
59 
60 @RunWith(RobolectricTestRunner.class)
61 public class FlashNotificationsUtilTest {
62 
63     @Rule
64     public MockitoRule mMockitoRule = MockitoJUnit.rule();
65     @Spy
66     private Context mContext = ApplicationProvider.getApplicationContext();
67     @Spy
68     private CameraManager mCameraManager = mContext.getSystemService(CameraManager.class);
69 
70     private ShadowCameraManager mShadowCameraManager;
71     private ContentResolver mContentResolver;
72 
73     @Before
setUp()74     public void setUp() {
75         MockitoAnnotations.initMocks(this);
76         mShadowCameraManager = Shadows.shadowOf(mCameraManager);
77         mContentResolver = mContext.getContentResolver();
78     }
79 
80     @Test
isTorchAvailable_nullCameraManager_assertFalse()81     public void isTorchAvailable_nullCameraManager_assertFalse() {
82         when(mContext.getSystemService(CameraManager.class)).thenReturn(null);
83         assertThat(isTorchAvailable(mContext)).isFalse();
84     }
85 
86     @Test
isTorchAvailable_noCamera_assertFalse()87     public void isTorchAvailable_noCamera_assertFalse() {
88         assertThat(isTorchAvailable(mContext)).isFalse();
89     }
90 
91     @Test
isTorchAvailable_getCameraIdListThrowException_assertFalse()92     public void isTorchAvailable_getCameraIdListThrowException_assertFalse()
93             throws CameraAccessException {
94         when(mCameraManager.getCameraIdList()).thenThrow(CameraAccessException.class);
95         assertThat(isTorchAvailable(mContext)).isFalse();
96     }
97 
98     @Test
isTorchAvailable_getCameraCharacteristicsThrowException_assertFalse()99     public void isTorchAvailable_getCameraCharacteristicsThrowException_assertFalse()
100             throws CameraAccessException {
101         CameraCharacteristics cameraCharacteristics = newCameraCharacteristics();
102         mShadowCameraManager.addCamera("0", cameraCharacteristics);
103 
104         when(mCameraManager.getCameraCharacteristics("0")).thenThrow(CameraAccessException.class);
105 
106         assertThat(isTorchAvailable(mContext)).isFalse();
107     }
108 
109     @Test
isTorchAvailable_torchNotPresent_assertFalse()110     public void isTorchAvailable_torchNotPresent_assertFalse() {
111         setTorchNotPresent();
112 
113         assertThat(isTorchAvailable(mContext)).isFalse();
114     }
115 
116     @Test
isTorchAvailable_torchPresent_assertTrue()117     public void isTorchAvailable_torchPresent_assertTrue() {
118         setTorchPresent();
119 
120         assertThat(isTorchAvailable(mContext)).isTrue();
121     }
122 
123     @Test
isTorchAvailable_lensFacingFront_assertFalse()124     public void isTorchAvailable_lensFacingFront_assertFalse() {
125         CameraCharacteristics cameraCharacteristics = newCameraCharacteristics();
126         ShadowCameraCharacteristics shadowCameraCharacteristics = extract(cameraCharacteristics);
127         shadowCameraCharacteristics.set(FLASH_INFO_AVAILABLE, true);
128         shadowCameraCharacteristics.set(LENS_FACING, LENS_FACING_FRONT);
129         mShadowCameraManager.addCamera("0", cameraCharacteristics);
130 
131         assertThat(isTorchAvailable(mContext)).isFalse();
132     }
133 
134     @Test
getScreenColor_undefinedColor_throwException()135     public void getScreenColor_undefinedColor_throwException() {
136         assertThrows(FlashNotificationsUtil.ScreenColorNotFoundException.class, () ->
137                 getScreenColor(0x4D0000FF));
138     }
139 
140     @Test
getScreenColor_azureColor_returnAzure()141     public void getScreenColor_azureColor_returnAzure() throws Exception {
142         assertThat(getScreenColor(0x660080FF)).isEqualTo(ScreenFlashNotificationColor.AZURE);
143     }
144 
145     @Test
getColorDescriptionText_undefinedColor_returnEmpty()146     public void getColorDescriptionText_undefinedColor_returnEmpty() {
147         assertThat(getColorDescriptionText(mContext, 0x4D0000FF)).isEqualTo("");
148     }
149 
150     @Test
getColorDescriptionText_azureColor_returnAzureName()151     public void getColorDescriptionText_azureColor_returnAzureName() {
152         assertThat(getColorDescriptionText(mContext, ScreenFlashNotificationColor.AZURE.mColorInt))
153                 .isEqualTo(mContext.getString(ScreenFlashNotificationColor.AZURE.mStringRes));
154     }
155 
156     @Test
getFlashNotificationsState_torchPresent_cameraOff_screenOff_assertOff()157     public void getFlashNotificationsState_torchPresent_cameraOff_screenOff_assertOff() {
158         setTorchPresent();
159         Settings.System.putInt(mContentResolver, Settings.System.CAMERA_FLASH_NOTIFICATION, OFF);
160         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, OFF);
161 
162         assertThat(getFlashNotificationsState(mContext))
163                 .isEqualTo(FlashNotificationsUtil.State.OFF);
164     }
165 
166     @Test
getFlashNotificationsState_torchNotPresent_cameraOn_screenOff_assertOff()167     public void getFlashNotificationsState_torchNotPresent_cameraOn_screenOff_assertOff() {
168         setTorchNotPresent();
169         Settings.System.putInt(mContentResolver, Settings.System.CAMERA_FLASH_NOTIFICATION, ON);
170         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, OFF);
171 
172         assertThat(getFlashNotificationsState(mContext))
173                 .isEqualTo(FlashNotificationsUtil.State.OFF);
174     }
175 
176     @Test
getFlashNotificationsState_torchPresent_cameraOn_screenOff_assertCamera()177     public void getFlashNotificationsState_torchPresent_cameraOn_screenOff_assertCamera() {
178         setTorchPresent();
179         Settings.System.putInt(mContentResolver, Settings.System.CAMERA_FLASH_NOTIFICATION, ON);
180         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, OFF);
181 
182         assertThat(getFlashNotificationsState(mContext))
183                 .isEqualTo(FlashNotificationsUtil.State.CAMERA);
184     }
185 
186     @Test
getFlashNotificationsState_torchPresent_cameraOff_screenOn_assertScreen()187     public void getFlashNotificationsState_torchPresent_cameraOff_screenOn_assertScreen() {
188         setTorchPresent();
189         Settings.System.putInt(mContentResolver, Settings.System.CAMERA_FLASH_NOTIFICATION, OFF);
190         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, ON);
191 
192         assertThat(getFlashNotificationsState(mContext))
193                 .isEqualTo(FlashNotificationsUtil.State.SCREEN);
194     }
195 
196     @Test
testGetFlashNotificationsState_torchPresent_cameraOn_screenOn_assertCameraScreen()197     public void testGetFlashNotificationsState_torchPresent_cameraOn_screenOn_assertCameraScreen() {
198         setTorchPresent();
199         Settings.System.putInt(mContentResolver, Settings.System.CAMERA_FLASH_NOTIFICATION, ON);
200         Settings.System.putInt(mContentResolver, Settings.System.SCREEN_FLASH_NOTIFICATION, ON);
201 
202         assertThat(getFlashNotificationsState(mContext))
203                 .isEqualTo(FlashNotificationsUtil.State.CAMERA_SCREEN);
204     }
205 
setTorchPresent()206     private void setTorchPresent() {
207         CameraCharacteristics cameraCharacteristics = newCameraCharacteristics();
208         ShadowCameraCharacteristics shadowCameraCharacteristics = extract(cameraCharacteristics);
209         shadowCameraCharacteristics.set(FLASH_INFO_AVAILABLE, true);
210         shadowCameraCharacteristics.set(LENS_FACING, LENS_FACING_BACK);
211         mShadowCameraManager.addCamera("0", cameraCharacteristics);
212     }
213 
setTorchNotPresent()214     private void setTorchNotPresent() {
215         CameraCharacteristics cameraCharacteristics = newCameraCharacteristics();
216         ShadowCameraCharacteristics shadowCameraCharacteristics = extract(cameraCharacteristics);
217         shadowCameraCharacteristics.set(FLASH_INFO_AVAILABLE, false);
218         mShadowCameraManager.addCamera("0", cameraCharacteristics);
219     }
220 }
221