1 /*
2  * Copyright (C) 2016 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 android.system.helpers;
18 
19 import android.bluetooth.BluetoothAdapter;
20 import android.bluetooth.BluetoothManager;
21 import android.content.ComponentName;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.net.wifi.WifiManager;
26 import android.provider.Settings;
27 import android.provider.Settings.SettingNotFoundException;
28 import android.support.test.uiautomator.By;
29 import android.support.test.uiautomator.BySelector;
30 import android.support.test.uiautomator.Direction;
31 import android.support.test.uiautomator.UiDevice;
32 import android.support.test.uiautomator.UiObject;
33 import android.support.test.uiautomator.UiObject2;
34 import android.support.test.uiautomator.UiObjectNotFoundException;
35 import android.support.test.uiautomator.UiScrollable;
36 import android.support.test.uiautomator.UiSelector;
37 import android.support.test.uiautomator.Until;
38 import android.util.Log;
39 import android.widget.Switch;
40 import android.widget.TextView;
41 
42 import androidx.test.InstrumentationRegistry;
43 
44 import junit.framework.Assert;
45 
46 import java.util.Random;
47 import java.util.regex.Pattern;
48 
49 /**
50  * Implement common helper methods for settings.
51  */
52 public class SettingsHelper {
53     private static final String TAG = SettingsHelper.class.getSimpleName();
54     private static final String ANDROID_PACKAGE = "android";
55     private static final String SETTINGS_PACKAGE = "com.android.settings";
56     private static final String SETTINGS_PKG_SEARCH = "com.google.android.settings.intelligence";
57     private static final String SETTINGS_APP = "Settings";
58     private static final String SWITCH_WIDGET = "switch_widget";
59     private static final String WIFI = "Wi-Fi";
60     private static final String BLUETOOTH = "Bluetooth";
61     private static final String AIRPLANE = "Airplane mode";
62     private static final String LOCATION = "Location";
63     private static final String DND = "Do not disturb";
64     private static final String ZEN_MODE = "zen_mode";
65     private static final String FLASHLIGHT = "Flashlight";
66     private static final String AUTO_ROTATE_SCREEN = "Auto-rotate screen";
67     private static final BySelector SETTINGS_DASHBOARD = By.res(SETTINGS_PACKAGE,
68             "dashboard_container");
69     private static final String ACTION_SEARCH = "com.android.settings.action.SETTINGS_SEARCH";
70     private static final String NO_RESULT_QUERY = "no_result_query";
71     private static final String RES_ID_SEARCH_UI_TEXT_BOX = "search_src_text";
72     private static final String RES_ID_SEARCH_UI_EDIT_TEXT_BOX = "open_search_view_edit_text";
73     private static final String RES_ID_SEARCH_UI_NO_RESULT_IMAGE = "no_results_layout_v2";
74 
75     private static final UiSelector LIST_ITEM_VALUE =
76             new UiSelector().className(TextView.class);
77     public static final int TIMEOUT = 2000;
78 
79     private static SettingsHelper sInstance = null;
80     private ActivityHelper mActivityHelper = null;
81     private ContentResolver mResolver = null;
82     private Context mContext = null;
83     private UiDevice mDevice = null;
84 
SettingsHelper()85     public SettingsHelper() {
86         mContext = InstrumentationRegistry.getTargetContext();
87         mResolver = mContext.getContentResolver();
88         mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
89         mActivityHelper = ActivityHelper.getInstance();
90     }
91 
getInstance()92     public static SettingsHelper getInstance() {
93         if (sInstance == null) {
94             sInstance = new SettingsHelper();
95         }
96         return sInstance;
97     }
98 
99     /**
100      * Opens Settings search page
101      */
openSearch(Context context)102     public void openSearch(Context context) throws Exception {
103         launchSettingsPage(context, ACTION_SEARCH);
104         // Wait for the search UI to appear
105         mDevice.wait(Until.hasObject(By.res(RES_ID_SEARCH_UI_TEXT_BOX)),
106                 TIMEOUT);
107     }
108 
109     /**
110      * Performs a query that has no result and clears query afterwards.
111      */
performNoResultQuery()112     public void performNoResultQuery() {
113         final String randomQuery = NO_RESULT_QUERY + new Random().nextInt();
114 
115         mDevice.wait(
116                         Until.findObject(
117                                 By.res(SETTINGS_PKG_SEARCH, RES_ID_SEARCH_UI_EDIT_TEXT_BOX)),
118                         TIMEOUT)
119                 .setText(randomQuery);
120 
121         mDevice.wait(
122                 Until.hasObject(By.res(SETTINGS_PKG_SEARCH, RES_ID_SEARCH_UI_NO_RESULT_IMAGE)),
123                 TIMEOUT);
124         mDevice.wait(
125                         Until.findObject(
126                                 By.res(SETTINGS_PKG_SEARCH, RES_ID_SEARCH_UI_EDIT_TEXT_BOX)),
127                         TIMEOUT)
128                 .clear();
129     }
130 
131     public enum SettingsType {
132         SYSTEM, SECURE, GLOBAL
133     }
134 
135     /**
136      * @return Settings package name
137      */
getPackage()138     public String getPackage() {
139         return SETTINGS_PACKAGE;
140     }
141 
142     /**
143      * @return Settings app name
144      */
getLauncherName()145     public String getLauncherName() {
146         return SETTINGS_APP;
147     }
148 
149     /**
150      * Scroll through settings page
151      * @param numberOfFlings
152      * @throws Exception
153      */
scrollThroughSettings(int numberOfFlings)154     public void scrollThroughSettings(int numberOfFlings) throws Exception {
155         UiObject2 settingsList = loadAllSettings();
156         int count = 0;
157         while (count <= numberOfFlings && settingsList.fling(Direction.DOWN)) {
158             count++;
159         }
160     }
161 
162     /**
163      * Move to top of settings page
164      * @throws Exception
165      */
flingSettingsToStart()166     public void flingSettingsToStart() throws Exception {
167         UiObject2 settingsList = loadAllSettings();
168         while (settingsList.fling(Direction.UP));
169     }
170 
171     /**
172      * Launch specific settings page
173      * @param ctx
174      * @param pageName
175      * @throws Exception
176      */
launchSettingsPage(Context ctx, String pageName)177     public static void launchSettingsPage(Context ctx, String pageName) throws Exception {
178         Intent intent = new Intent(pageName);
179         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
180         ctx.startActivity(intent);
181         Thread.sleep(TIMEOUT * 2);
182     }
183 
184     /**
185      * Scroll vertically up or down
186      * @param isUp
187      */
scrollVert(boolean isUp)188     public void scrollVert(boolean isUp) {
189         int w = mDevice.getDisplayWidth();
190         int h = mDevice.getDisplayHeight();
191         mDevice.swipe(w / 2, h / 2, w / 2, isUp ? h : 0, 2);
192     }
193 
194     /**
195      * On N, the settingsDashboard is initially collapsed, and the user can see the "See all"
196      * element. On hitting "See all", the same settings dashboard element is now scrollable. For
197      * pre-N, the settings Dashboard is always scrollable, hence the check in the while loop. All
198      * this method does is expand the Settings list if needed, before returning the element.
199      */
loadAllSettings()200     public UiObject2 loadAllSettings() throws Exception {
201         UiObject2 settingsDashboard = mDevice.wait(Until.findObject(SETTINGS_DASHBOARD),
202                 TIMEOUT * 2);
203         Assert.assertNotNull("Could not find the settings dashboard object.", settingsDashboard);
204         int count = 0;
205         while (!settingsDashboard.isScrollable() && count <= 2) {
206             mDevice.wait(Until.findObject(By.text("SEE ALL")), TIMEOUT * 2).click();
207             settingsDashboard = mDevice.wait(Until.findObject(SETTINGS_DASHBOARD),
208                     TIMEOUT * 2);
209             count++;
210         }
211         return settingsDashboard;
212     }
213 
214     /**
215      * Performs click action on a setting when setting name is provided as exact string
216      * @param settingName
217      * @throws InterruptedException
218      */
clickSetting(String settingName)219     public void clickSetting(String settingName) throws InterruptedException {
220         int count = 5;
221         while (count > 0 && mDevice.wait(Until.findObject(By.text(settingName)), TIMEOUT) == null) {
222             scrollVert(false);
223             count--;
224         }
225         mDevice.wait(Until.findObject(By.text(settingName)), TIMEOUT).click();
226         Thread.sleep(TIMEOUT);
227     }
228 
229     /**
230      * Performs click action on a setting when setting has been found
231      *
232      * @throws InterruptedException,UiObjectNotFoundException
233      */
selectSettingFor(String settingName)234     public boolean selectSettingFor(String settingName)
235             throws InterruptedException, UiObjectNotFoundException {
236         UiScrollable settingsList = new UiScrollable(
237                 new UiSelector().resourceId("android:id/content"));
238         UiObject appSettings = settingsList.getChildByText(LIST_ITEM_VALUE, settingName);
239         if (appSettings != null) {
240             return appSettings.click();
241         }
242         return false;
243     }
244 
245     /**
246      * Performs click action on a setting when setting name is provided as pattern
247      *
248      * @param settingName
249      * @throws InterruptedException
250      */
clickSetting(Pattern settingName)251     public void clickSetting(Pattern settingName) throws InterruptedException {
252         mDevice.wait(Until.findObject(By.text(settingName)), TIMEOUT).click();
253         Thread.sleep(400);
254     }
255 
256     /**
257      * Gets string value of a setting
258      * @param type
259      * @param sName
260      * @return
261      */
getStringSetting(SettingsType type, String sName)262     public String getStringSetting(SettingsType type, String sName) {
263         switch (type) {
264             case SYSTEM:
265                 return Settings.System.getString(mResolver, sName);
266             case GLOBAL:
267                 return Settings.Global.getString(mResolver, sName);
268             case SECURE:
269                 return Settings.Secure.getString(mResolver, sName);
270         }
271         return "";
272     }
273 
274     /**
275      * Get int value of a setting
276      * @param type
277      * @param sName
278      * @return
279      * @throws SettingNotFoundException
280      */
getIntSetting(SettingsType type, String sName)281     public int getIntSetting(SettingsType type, String sName) throws SettingNotFoundException {
282         switch (type) {
283             case SYSTEM:
284                 return Settings.System.getInt(mResolver, sName);
285             case GLOBAL:
286                 return Settings.Global.getInt(mResolver, sName);
287             case SECURE:
288                 return Settings.Secure.getInt(mResolver, sName);
289         }
290         return Integer.MIN_VALUE;
291     }
292 
293     /**
294      * Set string value of a setting
295      * @param type
296      * @param sName
297      * @param value
298      */
setStringSetting(SettingsType type, String sName, String value)299     public void setStringSetting(SettingsType type, String sName, String value)
300             throws InterruptedException {
301         switch (type) {
302             case SYSTEM:
303                 Settings.System.putString(mResolver, sName, value);
304                 break;
305             case GLOBAL:
306                 Settings.Global.putString(mResolver, sName, value);
307                 break;
308             case SECURE:
309                 Settings.Secure.putString(mResolver, sName, value);
310                 break;
311         }
312         Thread.sleep(TIMEOUT);
313     }
314 
315     /**
316      * Sets int value of a setting
317      * @param type
318      * @param sName
319      * @param value
320      */
setIntSetting(SettingsType type, String sName, int value)321     public void setIntSetting(SettingsType type, String sName, int value)
322             throws InterruptedException {
323         switch (type) {
324             case SYSTEM:
325                 Settings.System.putInt(mResolver, sName, value);
326                 break;
327             case GLOBAL:
328                 Settings.Global.putInt(mResolver, sName, value);
329                 break;
330             case SECURE:
331                 Settings.Secure.putInt(mResolver, sName, value);
332                 break;
333         }
334         Thread.sleep(TIMEOUT);
335     }
336 
337     /**
338      * Toggles setting and verifies the action, when setting name is passed as string
339      * @param type
340      * @param settingAction
341      * @param settingName
342      * @param internalName
343      * @return
344      * @throws Exception
345      */
verifyToggleSetting(SettingsType type, String settingAction, String settingName, String internalName)346     public boolean verifyToggleSetting(SettingsType type, String settingAction,
347             String settingName, String internalName) throws Exception {
348         return verifyToggleSetting(
349                 type, settingAction, Pattern.compile(settingName), internalName, true);
350     }
351 
352     /**
353      * Toggles setting and verifies the action, when setting name is passed as pattern
354      * @param type
355      * @param settingAction
356      * @param settingName
357      * @param internalName
358      * @return
359      * @throws Exception
360      */
verifyToggleSetting(SettingsType type, String settingAction, Pattern settingName, String internalName)361     public boolean verifyToggleSetting(SettingsType type, String settingAction,
362             Pattern settingName, String internalName) throws Exception {
363         return verifyToggleSetting(type, settingAction, settingName, internalName, true);
364     }
365 
366     /**
367      * Toggles setting and verifies the action, when setting name is passed as string
368      * and settings page needs to be launched or not
369      * @param type
370      * @param settingAction
371      * @param settingName
372      * @param internalName
373      * @param doLaunch
374      * @return
375      * @throws Exception
376      */
verifyToggleSetting(SettingsType type, String settingAction, String settingName, String internalName, boolean doLaunch)377     public boolean verifyToggleSetting(SettingsType type, String settingAction,
378             String settingName, String internalName, boolean doLaunch) throws Exception {
379         return verifyToggleSetting(
380                 type, settingAction, Pattern.compile(settingName), internalName, doLaunch);
381     }
382 
383     /**
384      * Toggles setting and verifies the action
385      * @param type
386      * @param settingAction
387      * @param settingName
388      * @param internalName
389      * @param doLaunch
390      * @return
391      * @throws Exception
392      */
verifyToggleSetting(SettingsType type, String settingAction, Pattern settingName, String internalName, boolean doLaunch)393     public boolean verifyToggleSetting(SettingsType type, String settingAction,
394             Pattern settingName, String internalName, boolean doLaunch) throws Exception {
395         String onSettingBaseVal = getStringSetting(type, internalName);
396         if (onSettingBaseVal == null) {
397             // Per bug b/35717943 default for charging sounds is ON
398             // So if null, the value should be set to 1.
399             if (settingName.matcher("Charging sounds").matches()) {
400                 onSettingBaseVal = "1";
401             }
402             else {
403                 onSettingBaseVal = "0";
404             }
405         }
406         int onSetting = Integer.parseInt(onSettingBaseVal);
407         Log.d(TAG, "On Setting value is : " + onSetting);
408         if (doLaunch) {
409             launchSettingsPage(mContext, settingAction);
410         }
411         clickSetting(settingName);
412         Log.d(TAG, "Clicked setting : " + settingName);
413         Thread.sleep(5000);
414         String changedSetting = getStringSetting(type, internalName);
415         Log.d(TAG, "Changed Setting value is : " + changedSetting);
416         if (changedSetting == null) {
417             Log.d(TAG, "Changed Setting value is : NULL");
418             changedSetting = "0";
419         }
420         return (1 - onSetting) == Integer.parseInt(changedSetting);
421     }
422 
423     /**
424      * @param type
425      * @param settingAction
426      * @param baseName
427      * @param settingName
428      * @param internalName
429      * @param testVal
430      * @return
431      * @throws Exception
432      */
verifyRadioSetting(SettingsType type, String settingAction, String baseName, String settingName, String internalName, String testVal)433     public boolean verifyRadioSetting(SettingsType type, String settingAction,
434             String baseName, String settingName,
435             String internalName, String testVal) throws Exception {
436         if (baseName != null)
437             clickSetting(baseName);
438         clickSetting(settingName);
439         Thread.sleep(500);
440         return getStringSetting(type, internalName).equals(testVal);
441     }
442 
toggleWiFiOnOffAndVerify(boolean verifyOn, boolean isQuickSettings)443     public void toggleWiFiOnOffAndVerify(boolean verifyOn, boolean isQuickSettings)
444             throws Exception {
445         String switchText = (verifyOn ? "OFF" : "ON");
446         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
447         wifiManager.setWifiEnabled(!verifyOn);
448         Thread.sleep(TIMEOUT * 3);
449         if (isQuickSettings) {
450             launchAndClickSettings(isQuickSettings, null, By.descContains(WIFI)
451                     .clazz(Switch.class));
452         } else {
453             launchAndClickSettings(isQuickSettings, Settings.ACTION_WIFI_SETTINGS,
454                     By.res(SETTINGS_PACKAGE, SWITCH_WIDGET).text(switchText));
455         }
456         Thread.sleep(TIMEOUT * 3);
457         String wifiValue = Settings.Global.getString(mResolver, Settings.Global.WIFI_ON);
458         if (verifyOn) {
459             Assert.assertFalse(wifiValue == "0");
460         } else {
461             Assert.assertEquals("0", wifiValue);
462         }
463         mDevice.pressHome();
464         Thread.sleep(TIMEOUT * 3);
465     }
466 
toggleBTOnOffAndVerify(boolean verifyOn, boolean isQuickSettings)467     public void toggleBTOnOffAndVerify(boolean verifyOn, boolean isQuickSettings)
468             throws Exception {
469         String switchText = (verifyOn ? "OFF" : "ON");
470         BluetoothAdapter bluetoothAdapter = ((BluetoothManager) mContext
471                 .getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
472         boolean isEnabled = bluetoothAdapter.isEnabled();
473         boolean success = (verifyOn ? bluetoothAdapter.disable() : bluetoothAdapter.enable());
474         Thread.sleep(TIMEOUT * 3);
475         if (isQuickSettings) {
476             launchAndClickSettings(isQuickSettings, null,
477                     By.descContains(BLUETOOTH).clazz(Switch.class));
478         } else {
479             launchAndClickSettings(isQuickSettings, Settings.ACTION_BLUETOOTH_SETTINGS,
480                     By.res(SETTINGS_PACKAGE, SWITCH_WIDGET).text(switchText));
481         }
482         Thread.sleep(TIMEOUT * 3);
483         String bluetoothValue = Settings.Global.getString(
484                 mResolver,
485                 Settings.Global.BLUETOOTH_ON);
486         Assert.assertEquals((verifyOn ? "1" : "0"), bluetoothValue);
487         if (isEnabled) {
488             bluetoothAdapter.enable();
489         } else {
490             bluetoothAdapter.disable();
491         }
492         mDevice.pressHome();
493         Thread.sleep(TIMEOUT * 3);
494     }
495 
toggleAirplaneModeOnOrOffAndVerify(boolean verifyOn, boolean isQuickSettings)496     public void toggleAirplaneModeOnOrOffAndVerify(boolean verifyOn, boolean isQuickSettings)
497             throws Exception {
498         String settingValToPut = (verifyOn ? "0" : "1");
499         Settings.Global.putString(mResolver, Settings.Global.AIRPLANE_MODE_ON, settingValToPut);
500         if (isQuickSettings) {
501             launchAndClickSettings(isQuickSettings, null, By.descContains(AIRPLANE));
502         } else {
503             launchAndClickSettings(isQuickSettings, Settings.ACTION_WIRELESS_SETTINGS,
504                     By.text(AIRPLANE));
505         }
506         Thread.sleep(TIMEOUT * 3);
507         String airplaneModeValue = Settings.Global
508                 .getString(mResolver,
509                         Settings.Global.AIRPLANE_MODE_ON);
510         Assert.assertEquals((verifyOn ? "1" : "0"), airplaneModeValue);
511         mDevice.pressHome();
512         Thread.sleep(TIMEOUT * 3);
513     }
514 
toggleLocationSettingsOnOrOffAndVerify(boolean verifyOn, boolean isQuickSettings)515     public void toggleLocationSettingsOnOrOffAndVerify(boolean verifyOn, boolean isQuickSettings)
516             throws Exception {
517         // Set location flag
518         int settingValToPut = (verifyOn ? Settings.Secure.LOCATION_MODE_OFF
519                 : Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
520         Settings.Secure.putInt(mResolver, Settings.Secure.LOCATION_MODE, settingValToPut);
521         // Load location settings
522         if (isQuickSettings) {
523             launchAndClickSettings(isQuickSettings, null, By.descContains(LOCATION));
524         } else {
525             launchAndClickSettings(isQuickSettings, Settings.ACTION_LOCATION_SOURCE_SETTINGS,
526                     By.res(SETTINGS_PACKAGE, SWITCH_WIDGET));
527         }
528         Thread.sleep(TIMEOUT * 3);
529         // Verify change in setting
530         int locationEnabled = Settings.Secure.getInt(mResolver,
531                 Settings.Secure.LOCATION_MODE);
532         if (verifyOn) {
533             Assert.assertFalse("Location not enabled correctly", locationEnabled == 0);
534         } else {
535             Assert.assertEquals("Location not disabled correctly", 0, locationEnabled);
536         }
537         mDevice.pressHome();
538         Thread.sleep(TIMEOUT * 3);
539     }
540 
launchAndClickSettings(boolean isQuickSettings, String settingsPage, BySelector bySelector)541     public void launchAndClickSettings(boolean isQuickSettings, String settingsPage,
542             BySelector bySelector) throws Exception {
543         if (isQuickSettings) {
544             launchQuickSettingsAndWait();
545             UiObject2 qsTile = mDevice.wait(Until.findObject(bySelector), TIMEOUT * 3);
546             qsTile.findObject(By.clazz("android.widget.FrameLayout")).click();
547         } else {
548             mActivityHelper.launchIntent(settingsPage);
549             mDevice.wait(Until.findObject(bySelector), TIMEOUT * 3).click();
550         }
551     }
552 
553     /**
554      * Verify Quick Setting DND can be toggled DND default value is OFF
555      * @throws Exception
556      */
toggleQuickSettingDNDAndVerify()557     public void toggleQuickSettingDNDAndVerify() throws Exception {
558         try {
559             int onSetting = Settings.Global.getInt(mResolver, ZEN_MODE);
560             launchQuickSettingsAndWait();
561             mDevice.wait(Until.findObject(By.descContains(DND).clazz(Switch.class)),
562                     TIMEOUT * 3).getChildren().get(0).click();
563             Thread.sleep(TIMEOUT * 3);
564             int changedSetting = Settings.Global.getInt(mResolver, ZEN_MODE);
565             Assert.assertFalse(onSetting == changedSetting);
566             mDevice.pressHome();
567             Thread.sleep(TIMEOUT * 3);
568         } finally {
569             // change to DND default value
570             int setting = Settings.Global.getInt(mResolver, ZEN_MODE);
571             if (setting > 0) {
572                 launchQuickSettingsAndWait();
573                 mDevice.wait(Until.findObject(By.descContains(DND).clazz(Switch.class)),
574                         TIMEOUT * 3).getChildren().get(0).click();
575                 Thread.sleep(TIMEOUT * 3);
576             }
577         }
578     }
579 
toggleQuickSettingFlashLightAndVerify()580     public void toggleQuickSettingFlashLightAndVerify() throws Exception {
581         String lightOn = "On";
582         String lightOff = "Off";
583         boolean verifyOn = false;
584         launchQuickSettingsAndWait();
585         UiObject2 flashLight = mDevice.wait(
586                 Until.findObject(By.desc(FLASHLIGHT)),
587                 TIMEOUT * 3);
588         if (flashLight != null && flashLight.getText().equals(lightOn)) {
589             verifyOn = true;
590         }
591         mDevice.wait(Until.findObject(By.desc(FLASHLIGHT)),
592                 TIMEOUT * 3).click();
593         Thread.sleep(TIMEOUT * 3);
594         flashLight = mDevice.wait(
595                 Until.findObject(By.desc(FLASHLIGHT)),
596                 TIMEOUT * 3);
597         if (flashLight != null) {
598             String txt = flashLight.getText();
599             if (verifyOn) {
600                 Assert.assertTrue(txt.equals(lightOff));
601             } else {
602                 Assert.assertTrue(txt.equals(lightOn));
603                 mDevice.wait(Until.findObject(By.textContains(FLASHLIGHT)),
604                         TIMEOUT * 3).click();
605             }
606         }
607         mDevice.pressHome();
608         Thread.sleep(TIMEOUT * 3);
609     }
610 
toggleQuickSettingOrientationAndVerify()611     public void toggleQuickSettingOrientationAndVerify() throws Exception {
612         launchQuickSettingsAndWait();
613         mDevice.wait(Until.findObject(By.descContains(AUTO_ROTATE_SCREEN)),
614                 TIMEOUT * 3).click();
615         Thread.sleep(TIMEOUT * 3);
616         String rotation = Settings.System.getString(mResolver,
617                 Settings.System.ACCELEROMETER_ROTATION);
618         Assert.assertEquals("1", rotation);
619         mDevice.setOrientationNatural();
620         mDevice.pressHome();
621         Thread.sleep(TIMEOUT * 3);
622     }
623 
launchQuickSettingsAndWait()624     public void launchQuickSettingsAndWait() throws Exception {
625         mDevice.openQuickSettings();
626         Thread.sleep(TIMEOUT * 2);
627     }
628 
launchSettingsPageByComponentName(Context ctx, String name)629     public void launchSettingsPageByComponentName(Context ctx, String name) {
630         Intent intent = new Intent(Intent.ACTION_MAIN);
631         ComponentName settingComponent = new ComponentName(SETTINGS_PACKAGE,
632                 String.format("%s.%s$%s", SETTINGS_PACKAGE, SETTINGS_APP, name));
633         intent.setComponent(settingComponent);
634         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
635         ctx.startActivity(intent);
636     }
637 }
638