1 /*
2  * Copyright (C) 2021 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.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
20 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
21 
22 import static com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController.DEFAULT_TRANSPARENCY;
23 import static com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController.MAXIMUM_TRANSPARENCY;
24 import static com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController.PRECISION;
25 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
26 import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
27 
28 import static com.google.common.truth.Truth.assertThat;
29 
30 import static org.mockito.Mockito.doReturn;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 
34 import android.content.ContentResolver;
35 import android.content.Context;
36 import android.provider.Settings;
37 
38 import androidx.preference.PreferenceScreen;
39 import androidx.test.core.app.ApplicationProvider;
40 
41 import com.android.settings.testutils.shadow.ShadowInteractionJankMonitor;
42 import com.android.settings.widget.SeekBarPreference;
43 
44 import org.junit.Before;
45 import org.junit.Rule;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.Mock;
49 import org.mockito.Spy;
50 import org.mockito.junit.MockitoJUnit;
51 import org.mockito.junit.MockitoRule;
52 import org.robolectric.RobolectricTestRunner;
53 import org.robolectric.annotation.Config;
54 
55 /** Tests for {@link FloatingMenuTransparencyPreferenceController}. */
56 @RunWith(RobolectricTestRunner.class)
57 @Config(shadows = {ShadowInteractionJankMonitor.class})
58 public class FloatingMenuTransparencyPreferenceControllerTest {
59 
60     @Rule
61     public MockitoRule mocks = MockitoJUnit.rule();
62 
63     @Spy
64     private final Context mContext = ApplicationProvider.getApplicationContext();
65     @Mock
66     private ContentResolver mContentResolver;
67     private FloatingMenuTransparencyPreferenceController mController;
68     private SeekBarPreference mSeekBarPreference;
69 
70     @Mock
71     private PreferenceScreen mScreen;
72 
73     @Before
setUp()74     public void setUp() {
75         when(mContext.getContentResolver()).thenReturn(mContentResolver);
76         mController = new FloatingMenuTransparencyPreferenceController(mContext, "test_key");
77 
78         mSeekBarPreference = new SeekBarPreference(mContext);
79         doReturn(mSeekBarPreference).when(mScreen).findPreference("test_key");
80     }
81 
82     @Test
getAvailabilityStatus_a11yBtnModeFloatingMenu_returnAvailable()83     public void getAvailabilityStatus_a11yBtnModeFloatingMenu_returnAvailable() {
84         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
85                 ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
86 
87         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
88     }
89 
90     @Test
getAvailabilityStatus_a11yBtnModeNavigationBar_returnDisabledDependentSetting()91     public void getAvailabilityStatus_a11yBtnModeNavigationBar_returnDisabledDependentSetting() {
92         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
93                 ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
94 
95         assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
96     }
97 
98     @Test
displayPreference_floatingMenuMode_fadeEnabled_preferenceEnabled()99     public void displayPreference_floatingMenuMode_fadeEnabled_preferenceEnabled() {
100         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
101                 ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
102         Settings.Secure.putInt(mContentResolver,
103                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* ON */ 1);
104 
105         mController.displayPreference(mScreen);
106 
107         assertThat(mSeekBarPreference.isEnabled()).isTrue();
108     }
109 
110     @Test
displayPreference_floatingMenuMode_fadeDisabled_preferenceDisabled()111     public void displayPreference_floatingMenuMode_fadeDisabled_preferenceDisabled() {
112         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
113                 ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
114         Settings.Secure.putInt(mContentResolver,
115                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* OFF */ 0);
116 
117         mController.displayPreference(mScreen);
118 
119         assertThat(mSeekBarPreference.isEnabled()).isFalse();
120     }
121 
122     @Test
displayPreference_navigationBarMode_preferenceDisabled()123     public void displayPreference_navigationBarMode_preferenceDisabled() {
124         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
125                 ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
126 
127         mController.displayPreference(mScreen);
128 
129         assertThat(mSeekBarPreference.isEnabled()).isFalse();
130     }
131 
132     @Test
onChange_floatingMenuModeChangeToNavigationBar_preferenceDisabled()133     public void onChange_floatingMenuModeChangeToNavigationBar_preferenceDisabled() {
134         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
135                 ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
136         Settings.Secure.putInt(mContentResolver,
137                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* ON */ 1);
138         mController.displayPreference(mScreen);
139 
140         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
141                 ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
142         mController.mContentObserver.onChange(false);
143 
144         assertThat(mSeekBarPreference.isEnabled()).isFalse();
145     }
146 
147     @Test
onChange_navigationBarModeChangeToFloatingMenu_preferenceDisabled()148     public void onChange_navigationBarModeChangeToFloatingMenu_preferenceDisabled() {
149         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
150                 ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
151         Settings.Secure.putInt(mContentResolver,
152                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* ON */ 1);
153         mController.displayPreference(mScreen);
154 
155         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
156                 ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
157         mController.mContentObserver.onChange(false);
158 
159         assertThat(mSeekBarPreference.isEnabled()).isTrue();
160     }
161 
162     @Test
getSliderPosition_putNormalOpacityValue_expectedValue()163     public void getSliderPosition_putNormalOpacityValue_expectedValue() {
164         final float transparencyValue = 0.65f;
165         Settings.Secure.putFloat(mContext.getContentResolver(),
166                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
167                 (MAXIMUM_TRANSPARENCY - transparencyValue));
168 
169         assertThat(mController.getSliderPosition()).isEqualTo((int) (transparencyValue * 100));
170     }
171 
172     @Test
getSliderPosition_putOutOfBoundOpacityValue_defaultValue()173     public void getSliderPosition_putOutOfBoundOpacityValue_defaultValue() {
174         Settings.Secure.putFloat(mContext.getContentResolver(),
175                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.01f);
176 
177         final int defaultValue = Math.round(DEFAULT_TRANSPARENCY * PRECISION);
178         assertThat(mController.getSliderPosition()).isEqualTo(defaultValue);
179     }
180 
181     @Test
setSliderPosition_expectedValue()182     public void setSliderPosition_expectedValue() {
183         final float transparencyValue = 0.27f;
184         mController.setSliderPosition((int) (transparencyValue * 100));
185 
186         final float value = Settings.Secure.getFloat(mContext.getContentResolver(),
187                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, -1);
188         assertThat(value).isEqualTo((MAXIMUM_TRANSPARENCY - transparencyValue));
189     }
190 
191     @Test
onResume_registerSpecificContentObserver()192     public void onResume_registerSpecificContentObserver() {
193         mController.onResume();
194 
195         verify(mContentResolver).registerContentObserver(
196                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_MODE), false,
197                 mController.mContentObserver);
198         verify(mContentResolver).registerContentObserver(
199                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED),
200                 false,
201                 mController.mContentObserver);
202     }
203 
204     @Test
onPause_unregisterContentObserver()205     public void onPause_unregisterContentObserver() {
206         mController.onPause();
207 
208         verify(mContentResolver).unregisterContentObserver(mController.mContentObserver);
209     }
210 }
211