• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 com.android.settings.ui;
17 
18 import android.os.RemoteException;
19 import android.os.SystemProperties;
20 import android.provider.Settings;
21 import android.support.test.InstrumentationRegistry;
22 import android.support.test.filters.MediumTest;
23 import android.support.test.runner.AndroidJUnit4;
24 import android.support.test.uiautomator.By;
25 import android.support.test.uiautomator.BySelector;
26 import android.support.test.uiautomator.UiDevice;
27 import android.support.test.uiautomator.UiObject;
28 import android.support.test.uiautomator.UiObject2;
29 import android.support.test.uiautomator.UiObjectNotFoundException;
30 import android.support.test.uiautomator.UiScrollable;
31 import android.support.test.uiautomator.UiSelector;
32 import android.support.test.uiautomator.Until;
33 import android.system.helpers.SettingsHelper;
34 import android.system.helpers.SettingsHelper.SettingsType;
35 
36 import org.junit.After;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 
41 import java.util.TimeZone;
42 
43 import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
44 import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertFalse;
47 import static org.junit.Assert.assertTrue;
48 
49 @MediumTest
50 @RunWith(AndroidJUnit4.class)
51 public class ZonePickerSettingsTest {
52 
53     private static final BySelector SELECTOR_SELECT_TIME_ZONE =
54             By.hasChild(By.text("Select time zone"));
55 
56     private UiDevice mDevice;
57     private SettingsHelper mHelper;
58     private String mIsV2EnabledByDefault;
59     private int mIsAutoZoneEnabled;
60 
61     @Before
setUp()62     public void setUp() throws Exception {
63         mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
64         mHelper = SettingsHelper.getInstance();
65         try {
66             mDevice.setOrientationNatural();
67         } catch (RemoteException e) {
68             throw new RuntimeException("failed to freeze device orientation", e);
69         }
70         mIsV2EnabledByDefault = mHelper.getStringSetting(SettingsType.GLOBAL,
71                 "settings_zone_picker_v2");
72         mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2", "true");
73         mIsAutoZoneEnabled = mHelper.getIntSetting(SettingsType.GLOBAL,
74                 Settings.Global.AUTO_TIME_ZONE);
75     }
76 
77     @After
tearDown()78     public void tearDown() throws Exception {
79         // Go back to home for next test.
80         mDevice.pressBack();
81         mDevice.pressBack();
82         mDevice.pressHome();
83         mDevice.waitForIdle(TIMEOUT * 2);
84         mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2",
85                 mIsV2EnabledByDefault);
86         mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE,
87                 mIsAutoZoneEnabled);
88     }
89 
90     @Test
zonePickerDisabled()91     public void zonePickerDisabled() throws Exception {
92         mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 1);
93 
94         SettingsHelper.launchSettingsPage(
95                 InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
96         UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
97         assertFalse(selectTimeZone.isEnabled());
98     }
99 
100     // Test 2 time zones with no DST
101     @Test
testSelectReykjavik()102     public void testSelectReykjavik() throws Exception {
103         testSelectTimeZone("Iceland", "Reykjavik", "GMT+00:00", "Atlantic/Reykjavik", true);
104     }
105 
106     @Test
testSelectPhoenix()107     public void testSelectPhoenix() throws Exception {
108         testSelectTimeZone("United States", "Phoenix", "GMT-07:00", "America/Phoenix", false);
109     }
110 
testSelectTimeZone(String region, String timezone, String expectedTimeZoneOffset, String expectedTimeZoneId, boolean assumeOneTimeZoneInRegion)111     private void testSelectTimeZone(String region, String timezone, String expectedTimeZoneOffset,
112             String expectedTimeZoneId, boolean assumeOneTimeZoneInRegion) throws Exception {
113         mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 0);
114 
115         SettingsHelper.launchSettingsPage(
116                 InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
117 
118         UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
119         assertTrue(selectTimeZone.isEnabled());
120         selectTimeZone.click();
121 
122         wait(By.text("Region")).click();
123         // Speed-up the test by searching with the first 2 characters of the region name
124         wait(By.res("android", "search_src_text")).setText(region.substring(0, 2));
125         // Select region in the list
126         selectItemInList(new UiSelector().textContains(region))
127                 .click();
128 
129         // Only select time zone explicitly if there are more than one time zones in a region
130         if (!assumeOneTimeZoneInRegion) {
131             wait(By.text("Time zone"));
132             selectItemInList(new UiSelector().textContains(timezone))
133                     .click();
134         }
135 
136         mDevice.pressBack();
137         // The select button should include the GMT offset in the summary
138         BySelector summarySelector = By.res("android:id/summary");
139         UiObject2 selectedTimeZone = selectTimeZone.findObject(summarySelector);
140         assertUiObjectFound(selectedTimeZone, summarySelector);
141         assertTrue("Expect " + expectedTimeZoneOffset + " is shown for " + timezone,
142                 selectedTimeZone.getText().startsWith(expectedTimeZoneOffset));
143 
144         waitAndAssertTimeGetDefault(expectedTimeZoneId);
145         assertEquals("Time zone change in Settings should update persist.sys.timezone",
146                 expectedTimeZoneId, SystemProperties.get("persist.sys.timezone"));
147     }
148 
149     private static final long CHECK_DEFAULT_TIMEZONE_INTERVAL = 200L;
150     private static final long CHECK_DEFAULT_TIMEZONE_TIMEOUT = 3000L;
151 
152     /**
153      * Wait for the broadcast ACTION_TIMEZONE_CHANGED propagated, and update the default TimeZone
154      * by ApplicationThread.
155      */
waitAndAssertTimeGetDefault(String expectedTimeZoneId)156     private static void waitAndAssertTimeGetDefault(String expectedTimeZoneId)
157             throws InterruptedException {
158         for (int i = 0; i < CHECK_DEFAULT_TIMEZONE_TIMEOUT / CHECK_DEFAULT_TIMEZONE_INTERVAL; i++) {
159             if (expectedTimeZoneId.equals(TimeZone.getDefault().getID())) {
160                 return;
161             }
162             Thread.sleep(CHECK_DEFAULT_TIMEZONE_INTERVAL);
163         }
164 
165         assertEquals(expectedTimeZoneId, TimeZone.getDefault().getID());
166     }
167 
selectItemInList(UiSelector childSelector)168     private UiObject selectItemInList(UiSelector childSelector) throws UiObjectNotFoundException {
169         UiScrollable recyclerView = new UiScrollable(
170                 new UiSelector().resourceId(SETTINGS_PACKAGE + ":id/recycler_view"));
171         return selectScrollableItem(recyclerView, childSelector);
172     }
173 
174     /**
175      * Select the child object in the UiScrollable
176      * @throws UiObjectNotFoundException if scrollable or child is not found
177      */
selectScrollableItem(UiScrollable scrollable, UiSelector childSelector)178     private UiObject selectScrollableItem(UiScrollable scrollable, UiSelector childSelector)
179             throws UiObjectNotFoundException {
180         if (!scrollable.waitForExists(TIMEOUT)) {
181             throw newUiObjectNotFoundException(scrollable.getSelector());
182         }
183         scrollable.scrollIntoView(childSelector);
184 
185         UiObject child = mDevice.findObject(childSelector);
186         assertUiObjectFound(child, childSelector);
187         return child;
188     }
189 
190     /**
191      * @throws UiObjectNotFoundException if UiDevice.wait returns null
192      */
wait(BySelector selector)193     private UiObject2 wait(BySelector selector) throws UiObjectNotFoundException {
194         UiObject2 item = mDevice.wait(Until.findObject(selector), TIMEOUT);
195         assertUiObjectFound(item, selector);
196         return item;
197     }
198 
assertUiObjectFound(UiObject2 obj, BySelector selector)199     private static void assertUiObjectFound(UiObject2 obj, BySelector selector)
200             throws UiObjectNotFoundException {
201         if (obj == null) {
202             throw newUiObjectNotFoundException(selector);
203         }
204     }
205 
206 
assertUiObjectFound(UiObject obj, UiSelector selector)207     private static void assertUiObjectFound(UiObject obj, UiSelector selector)
208             throws UiObjectNotFoundException {
209         if (obj == null) {
210             throw newUiObjectNotFoundException(selector);
211         }
212     }
213 
newUiObjectNotFoundException(Object selector)214     private static UiObjectNotFoundException newUiObjectNotFoundException(Object selector) {
215         return new UiObjectNotFoundException(
216                 String.format("UI object not found: %s", selector.toString()));
217     }
218 }
219