• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package android.system.helpers;
17 
18 import android.app.Instrumentation;
19 import android.content.Context;
20 import android.provider.Settings;
21 import android.support.test.uiautomator.By;
22 import android.support.test.uiautomator.UiDevice;
23 import android.support.test.uiautomator.UiObject2;
24 import android.support.test.uiautomator.UiObjectNotFoundException;
25 import android.support.test.uiautomator.UiScrollable;
26 import android.support.test.uiautomator.UiSelector;
27 import android.support.test.uiautomator.Until;
28 
29 /**
30  * Implement common helper functions for accessibility.
31  */
32 public class AccessibilityHelper {
33     public static final String SETTINGS_PACKAGE = "com.android.settings";
34     public static final String BUTTON = "android.widget.Button";
35     public static final String CHECK_BOX = "android.widget.CheckBox";
36     public static final String IMAGE_BUTTON = "android.widget.ImageButton";
37     public static final String TEXT_VIEW = "android.widget.TextView";
38     public static final String SWITCH = "android.widget.Switch";
39     public static final String CHECKED_TEXT_VIEW = "android.widget.CheckedTextView";
40     public static final String RADIO_BUTTON = "android.widget.RadioButton";
41     public static final String SEEK_BAR = "android.widget.SeekBar";
42     public static final String SPINNER = "android.widget.Spinner";
43     public static final int SHORT_TIMEOUT = 2000;
44     public static final int LONG_TIMEOUT = 5000;
45     public static AccessibilityHelper sInstance = null;
46     private Context mContext = null;
47     private Instrumentation mInstrumentation = null;
48     private UiDevice mDevice = null;
49     private SettingsHelper mSettingsHelper = null;
50 
51     public enum SwitchStatus {
52         ON,
53         OFF;
54     }
55 
AccessibilityHelper(Instrumentation instr)56     private AccessibilityHelper(Instrumentation instr) {
57         mInstrumentation = instr;
58         mSettingsHelper = SettingsHelper.getInstance();
59         mDevice = UiDevice.getInstance(instr);
60         mContext = mInstrumentation.getTargetContext();
61     }
62 
getInstance(Instrumentation instr)63     public static AccessibilityHelper getInstance(Instrumentation instr) {
64         if (sInstance == null) {
65             sInstance = new AccessibilityHelper(instr);
66         }
67         return sInstance;
68     }
69 
70     /**
71      * Set Talkback "ON"/"OFF".
72      *
73      * @param value "ON"/"OFF"
74      * @throws Exception
75      */
setTalkBackSetting(SwitchStatus value)76     public void setTalkBackSetting(SwitchStatus value) throws Exception {
77         launchSpecificAccessibilitySetting("TalkBack");
78         UiObject2 swtBar = mDevice.wait(
79                 Until.findObject(By.res(SETTINGS_PACKAGE, "switch_bar")), SHORT_TIMEOUT)
80                 .findObject(By.res(SETTINGS_PACKAGE, "switch_widget"));
81         if (swtBar != null && !swtBar.getText().equals(value.toString())) {
82             swtBar.click();
83             UiObject2 confirmBtn = mDevice.wait(
84                     Until.findObject(By.res("android:id/button1")), LONG_TIMEOUT);
85             if (confirmBtn != null) {
86                 confirmBtn.click();
87             }
88             // First time enable talkback, tutorial open.
89             if (mDevice.wait(Until.hasObject(By.text("TalkBack tutorial")), SHORT_TIMEOUT)) {
90                 mDevice.pressBack(); // back to talkback setting page
91             }
92         }
93         mDevice.pressBack();
94     }
95 
96     /**
97      * Set high contrast "ON"/"OFF".
98      *
99      * @param value "ON"/"OFF"
100      * @throws Exception
101      */
setHighContrast(SwitchStatus value)102     public void setHighContrast(SwitchStatus value) throws Exception {
103         launchSpecificAccessibilitySetting("Accessibility");
104         setSettingSwitchValue("High contrast text", value);
105     }
106 
107     /**
108      * Launch specific accessibility setting page.
109      *
110      * @param settingName Specific accessibility setting name
111      * @throws Exception
112      */
launchSpecificAccessibilitySetting(String settingName)113     public void launchSpecificAccessibilitySetting(String settingName) throws Exception {
114         mSettingsHelper.launchSettingsPage(mContext, Settings.ACTION_ACCESSIBILITY_SETTINGS);
115         int maxTry = 3;
116         while (maxTry-- >= 0) {
117             Thread.sleep(SHORT_TIMEOUT);
118             UiObject2 actionBar = mDevice.wait(Until.findObject(
119                     By.res(SETTINGS_PACKAGE, "action_bar").enabled(true)), SHORT_TIMEOUT);
120             if (actionBar == null) {
121                 mSettingsHelper.launchSettingsPage(mContext,
122                         Settings.ACTION_ACCESSIBILITY_SETTINGS);
123             } else {
124                 String actionBarText = actionBar.findObject(By.clazz(TEXT_VIEW)).getText();
125                 if (actionBarText.equals(settingName)) {
126                     break;
127                 } else if (actionBarText.equals("Accessibility")) {
128                     getSettingFromList(settingName).click();
129                 } else {
130                     mDevice.wait(Until.findObject(By.res(SETTINGS_PACKAGE, "action_bar")
131                             .enabled(true)), SHORT_TIMEOUT)
132                             .findObject(By.clazz(IMAGE_BUTTON)).click();
133                 }
134             }
135         }
136     }
137 
138     /**
139      * Set switch "ON"/"OFF".
140      *
141      * @param settingTag setting name
142      * @param value "ON"/"OFF"
143      * @return true/false
144      * @throws UiObjectNotFoundException
145      * @throws InterruptedException
146      */
setSettingSwitchValue(String settingTag, SwitchStatus value)147     private boolean setSettingSwitchValue(String settingTag, SwitchStatus value)
148             throws UiObjectNotFoundException, InterruptedException {
149         UiObject2 cellSwitch = getSettingFromList(settingTag)
150                 .getParent().getParent().findObject(By.clazz(SWITCH));
151         if (cellSwitch != null) {
152             if (!cellSwitch.getText().equals(value.toString())) {
153                 cellSwitch.click();
154                 UiObject2 okBtn = mDevice.wait(Until.findObject(
155                         By.res("android:id/button1")), LONG_TIMEOUT);
156                 if (okBtn != null) {
157                     okBtn.click();
158                 }
159             }
160             return cellSwitch.getText().equals(value.toString());
161         }
162         return false;
163     }
164 
165     /**
166      * Get setting name text object from list.
167      *
168      * @param settingName setting name
169      * @return UiObject2
170      * @throws UiObjectNotFoundException
171      */
getSettingFromList(String settingName)172     private UiObject2 getSettingFromList(String settingName)
173             throws UiObjectNotFoundException {
174         UiScrollable listScrollable = new UiScrollable(
175                 new UiSelector().resourceId(SETTINGS_PACKAGE + ":id/recycler_view"));
176         if (listScrollable != null) {
177             listScrollable.scrollToBeginning(100);
178             listScrollable.scrollIntoView(
179                     new UiSelector().resourceId("android:id/title").text(settingName));
180             return mDevice.findObject(By.res("android:id/title").text(settingName));
181         } else {
182             throw new UiObjectNotFoundException("Fail to get scrollable list %s.");
183         }
184     }
185 }
186