1 /*
2  * Copyright (C) 2014 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.cts.verifier.sensors.helpers;
18 
19 import com.android.cts.verifier.R;
20 import com.android.cts.verifier.sensors.base.ISensorTestStateContainer;
21 
22 import android.content.ContentResolver;
23 import android.os.Build;
24 import android.provider.Settings;
25 
26 import java.lang.reflect.Field;
27 
28 /**
29  * A helper class that provides a mechanism to:
30  * - prompt users to activate/deactivate features that are known to register for sensor data.
31  * - turn on/off certain components of the device on behalf of the test (described as 'runtime
32  *   features')
33  * - keep track of the initial state for each sensor feature, so it can be restored at will
34  */
35 public class SensorFeaturesDeactivator {
36 
37     private final ISensorTestStateContainer mStateContainer;
38 
39     private final SensorSettingContainer mAirplaneMode = new AirplaneModeSettingContainer();
40     private final SensorSettingContainer mScreenBrightnessMode =
41             new ScreenBrightnessModeSettingContainer();
42     private final SensorSettingContainer mAmbientDisplayMode = new AmbientDisplaySettingContainer();
43     private final SensorSettingContainer mAutoRotateScreenMode =
44             new AutoRotateScreenModeSettingContainer();
45     private final SensorSettingContainer mKeepScreenOnMode = new KeepScreenOnModeSettingContainer();
46     private final SensorSettingContainer mLocationMode = new LocationModeSettingContainer();
47 
SensorFeaturesDeactivator(ISensorTestStateContainer stateContainer)48     public SensorFeaturesDeactivator(ISensorTestStateContainer stateContainer) {
49         mStateContainer = stateContainer;
50     }
51 
requestDeactivationOfFeatures()52     public synchronized void requestDeactivationOfFeatures() throws InterruptedException {
53         captureInitialState();
54 
55         mAirplaneMode.requestToSetMode(mStateContainer, true);
56         mScreenBrightnessMode.requestToSetMode(mStateContainer, false);
57         mAmbientDisplayMode.requestToSetMode(mStateContainer, false);
58         mAutoRotateScreenMode.requestToSetMode(mStateContainer, false);
59         mKeepScreenOnMode.requestToSetMode(mStateContainer, false);
60         mLocationMode.requestToSetMode(mStateContainer, false);
61 
62         // TODO: find a way to find out if there are clients still registered at this time
63         mStateContainer.getTestLogger()
64                 .logInstructions(R.string.snsr_sensor_feature_deactivation);
65         mStateContainer.waitForUserToContinue();
66     }
67 
requestToRestoreFeatures()68     public synchronized void requestToRestoreFeatures() throws InterruptedException {
69         if (Thread.currentThread().isInterrupted()) {
70             // TODO: in the future, if the thread is interrupted, we might need to serialize the
71             //       intermediate state we acquired so we can restore when we have a chance
72             return;
73         }
74 
75         mAirplaneMode.requestToResetMode(mStateContainer);
76         mScreenBrightnessMode.requestToResetMode(mStateContainer);
77         mAmbientDisplayMode.requestToResetMode(mStateContainer);
78         mAutoRotateScreenMode.requestToResetMode(mStateContainer);
79         mKeepScreenOnMode.requestToResetMode(mStateContainer);
80         mLocationMode.requestToResetMode(mStateContainer);
81     }
82 
captureInitialState()83     private void captureInitialState() {
84         mAirplaneMode.captureInitialState();
85         mScreenBrightnessMode.captureInitialState();
86         mAmbientDisplayMode.captureInitialState();
87         mAutoRotateScreenMode.captureInitialState();
88         mLocationMode.captureInitialState();
89         mKeepScreenOnMode.captureInitialState();
90     }
91 
92     private class AirplaneModeSettingContainer extends SensorSettingContainer {
AirplaneModeSettingContainer()93         public AirplaneModeSettingContainer() {
94             super(Settings.ACTION_WIRELESS_SETTINGS, R.string.snsr_setting_airplane_mode);
95         }
96 
97         @Override
getSettingMode(int defaultValue)98         protected int getSettingMode(int defaultValue) {
99             ContentResolver contentResolver = mStateContainer.getContentResolver();
100             // Settings.System.AIRPLANE_MODE_ON is deprecated in API 17
101             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
102                 return Settings.System
103                         .getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, defaultValue);
104             } else {
105                 return Settings.Global
106                         .getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, defaultValue);
107             }
108         }
109     }
110 
111     private class ScreenBrightnessModeSettingContainer extends SensorSettingContainer {
ScreenBrightnessModeSettingContainer()112         public ScreenBrightnessModeSettingContainer() {
113             super(Settings.ACTION_DISPLAY_SETTINGS, R.string.snsr_setting_screen_brightness_mode);
114         }
115 
116         @Override
getSettingMode(int defaultValue)117         public int getSettingMode(int defaultValue) {
118             return Settings.System.getInt(
119                     mStateContainer.getContentResolver(),
120                     Settings.System.SCREEN_BRIGHTNESS_MODE,
121                     defaultValue);
122         }
123     }
124 
125     private class AmbientDisplaySettingContainer extends SensorSettingContainer {
AmbientDisplaySettingContainer()126         public AmbientDisplaySettingContainer() {
127             super(Settings.ACTION_DISPLAY_SETTINGS, R.string.snsr_setting_ambient_display);
128         }
129 
130         @Override
getSettingMode(int defaultValue)131         protected int getSettingMode(int defaultValue) {
132             // TODO: replace the use of reflection with Settings.Secure.DOZE_ENABLED when the
133             //       static field is not hidden anymore
134             Class<?> secureSettingsClass = Settings.Secure.class;
135             Field dozeEnabledField;
136             try {
137                 dozeEnabledField = secureSettingsClass.getField("DOZE_ENABLED");
138             } catch (NoSuchFieldException e) {
139                 return defaultValue;
140             }
141 
142             String settingName;
143             try {
144                 settingName = (String) dozeEnabledField.get(null /* obj */);
145             } catch (IllegalAccessException e) {
146                 return defaultValue;
147             }
148 
149             return Settings.Secure.getInt(
150                     mStateContainer.getContentResolver(),
151                     settingName,
152                     defaultValue);
153         }
154     }
155 
156     private class AutoRotateScreenModeSettingContainer extends SensorSettingContainer {
AutoRotateScreenModeSettingContainer()157         public AutoRotateScreenModeSettingContainer() {
158             super(Settings.ACTION_ACCESSIBILITY_SETTINGS,
159                     R.string.snsr_setting_auto_rotate_screen_mode);
160         }
161 
162         @Override
getSettingMode(int defaultValue)163         protected int getSettingMode(int defaultValue) {
164             return Settings.System.getInt(
165                     mStateContainer.getContentResolver(),
166                     Settings.System.ACCELEROMETER_ROTATION,
167                     defaultValue);
168         }
169     }
170 
171     private class KeepScreenOnModeSettingContainer extends SensorSettingContainer {
KeepScreenOnModeSettingContainer()172         public KeepScreenOnModeSettingContainer() {
173             super(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS,
174                     R.string.snsr_setting_keep_screen_on);
175         }
176 
177         @Override
getSettingMode(int defaultValue)178         protected int getSettingMode(int defaultValue) {
179             return Settings.Global.getInt(
180                     mStateContainer.getContentResolver(),
181                     Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
182                     defaultValue);
183         }
184     }
185 
186     private class LocationModeSettingContainer extends SensorSettingContainer {
LocationModeSettingContainer()187         public LocationModeSettingContainer() {
188             super(Settings.ACTION_LOCATION_SOURCE_SETTINGS, R.string.snsr_setting_location_mode);
189         }
190 
191         @Override
getSettingMode(int defaultValue)192         protected int getSettingMode(int defaultValue) {
193             return Settings.Secure.getInt(
194                     mStateContainer.getContentResolver(),
195                     Settings.Secure.LOCATION_MODE,
196                     defaultValue);
197         }
198     }
199 }
200