| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.settings.ui; |
| |
| import android.os.RemoteException; |
| import android.os.SystemProperties; |
| import android.provider.Settings; |
| import android.support.test.InstrumentationRegistry; |
| import android.support.test.filters.MediumTest; |
| import android.support.test.runner.AndroidJUnit4; |
| import android.support.test.uiautomator.By; |
| import android.support.test.uiautomator.BySelector; |
| import android.support.test.uiautomator.UiDevice; |
| import android.support.test.uiautomator.UiObject; |
| import android.support.test.uiautomator.UiObject2; |
| import android.support.test.uiautomator.UiObjectNotFoundException; |
| import android.support.test.uiautomator.UiScrollable; |
| import android.support.test.uiautomator.UiSelector; |
| import android.support.test.uiautomator.Until; |
| import android.system.helpers.SettingsHelper; |
| import android.system.helpers.SettingsHelper.SettingsType; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.TimeZone; |
| |
| import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE; |
| import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| |
| @MediumTest |
| @RunWith(AndroidJUnit4.class) |
| public class ZonePickerSettingsTest { |
| |
| private static final BySelector SELECTOR_SELECT_TIME_ZONE = |
| By.hasChild(By.text("Select time zone")); |
| |
| private UiDevice mDevice; |
| private SettingsHelper mHelper; |
| private String mIsV2EnabledByDefault; |
| private int mIsAutoZoneEnabled; |
| |
| @Before |
| public void setUp() throws Exception { |
| mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); |
| mHelper = SettingsHelper.getInstance(); |
| try { |
| mDevice.setOrientationNatural(); |
| } catch (RemoteException e) { |
| throw new RuntimeException("failed to freeze device orientation", e); |
| } |
| mIsV2EnabledByDefault = mHelper.getStringSetting(SettingsType.GLOBAL, |
| "settings_zone_picker_v2"); |
| mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2", "true"); |
| mIsAutoZoneEnabled = mHelper.getIntSetting(SettingsType.GLOBAL, |
| Settings.Global.AUTO_TIME_ZONE); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| // Go back to home for next test. |
| mDevice.pressBack(); |
| mDevice.pressBack(); |
| mDevice.pressHome(); |
| mDevice.waitForIdle(TIMEOUT * 2); |
| mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2", |
| mIsV2EnabledByDefault); |
| mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, |
| mIsAutoZoneEnabled); |
| } |
| |
| @Test |
| public void zonePickerDisabled() throws Exception { |
| mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 1); |
| |
| SettingsHelper.launchSettingsPage( |
| InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS); |
| UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE); |
| assertFalse(selectTimeZone.isEnabled()); |
| } |
| |
| // Test 2 time zones with no DST |
| @Test |
| public void testSelectReykjavik() throws Exception { |
| testSelectTimeZone("Iceland", "Reykjavik", "GMT+00:00", "Atlantic/Reykjavik", true); |
| } |
| |
| @Test |
| public void testSelectPhoenix() throws Exception { |
| testSelectTimeZone("United States", "Phoenix", "GMT-07:00", "America/Phoenix", false); |
| } |
| |
| private void testSelectTimeZone(String region, String timezone, String expectedTimeZoneOffset, |
| String expectedTimeZoneId, boolean assumeOneTimeZoneInRegion) throws Exception { |
| mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 0); |
| |
| SettingsHelper.launchSettingsPage( |
| InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS); |
| |
| UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE); |
| assertTrue(selectTimeZone.isEnabled()); |
| selectTimeZone.click(); |
| |
| wait(By.text("Region")).click(); |
| // Speed-up the test by searching with the first 2 characters of the region name |
| wait(By.res("android", "search_src_text")).setText(region.substring(0, 2)); |
| // Select region in the list |
| selectItemInList(new UiSelector().textContains(region)) |
| .click(); |
| |
| // Only select time zone explicitly if there are more than one time zones in a region |
| if (!assumeOneTimeZoneInRegion) { |
| wait(By.text("Time zone")); |
| selectItemInList(new UiSelector().textContains(timezone)) |
| .click(); |
| } |
| |
| mDevice.pressBack(); |
| // The select button should include the GMT offset in the summary |
| BySelector summarySelector = By.res("android:id/summary"); |
| UiObject2 selectedTimeZone = selectTimeZone.findObject(summarySelector); |
| assertUiObjectFound(selectedTimeZone, summarySelector); |
| assertTrue("Expect " + expectedTimeZoneOffset + " is shown for " + timezone, |
| selectedTimeZone.getText().startsWith(expectedTimeZoneOffset)); |
| |
| waitAndAssertTimeGetDefault(expectedTimeZoneId); |
| assertEquals("Time zone change in Settings should update persist.sys.timezone", |
| expectedTimeZoneId, SystemProperties.get("persist.sys.timezone")); |
| } |
| |
| private static final long CHECK_DEFAULT_TIMEZONE_INTERVAL = 200L; |
| private static final long CHECK_DEFAULT_TIMEZONE_TIMEOUT = 3000L; |
| |
| /** |
| * Wait for the broadcast ACTION_TIMEZONE_CHANGED propagated, and update the default TimeZone |
| * by ApplicationThread. |
| */ |
| private static void waitAndAssertTimeGetDefault(String expectedTimeZoneId) |
| throws InterruptedException { |
| for (int i = 0; i < CHECK_DEFAULT_TIMEZONE_TIMEOUT / CHECK_DEFAULT_TIMEZONE_INTERVAL; i++) { |
| if (expectedTimeZoneId.equals(TimeZone.getDefault().getID())) { |
| return; |
| } |
| Thread.sleep(CHECK_DEFAULT_TIMEZONE_INTERVAL); |
| } |
| |
| assertEquals(expectedTimeZoneId, TimeZone.getDefault().getID()); |
| } |
| |
| private UiObject selectItemInList(UiSelector childSelector) throws UiObjectNotFoundException { |
| UiScrollable recyclerView = new UiScrollable( |
| new UiSelector().resourceId(SETTINGS_PACKAGE + ":id/recycler_view")); |
| return selectScrollableItem(recyclerView, childSelector); |
| } |
| |
| /** |
| * Select the child object in the UiScrollable |
| * @throws UiObjectNotFoundException if scrollable or child is not found |
| */ |
| private UiObject selectScrollableItem(UiScrollable scrollable, UiSelector childSelector) |
| throws UiObjectNotFoundException { |
| if (!scrollable.waitForExists(TIMEOUT)) { |
| throw newUiObjectNotFoundException(scrollable.getSelector()); |
| } |
| scrollable.scrollIntoView(childSelector); |
| |
| UiObject child = mDevice.findObject(childSelector); |
| assertUiObjectFound(child, childSelector); |
| return child; |
| } |
| |
| /** |
| * @throws UiObjectNotFoundException if UiDevice.wait returns null |
| */ |
| private UiObject2 wait(BySelector selector) throws UiObjectNotFoundException { |
| UiObject2 item = mDevice.wait(Until.findObject(selector), TIMEOUT); |
| assertUiObjectFound(item, selector); |
| return item; |
| } |
| |
| private static void assertUiObjectFound(UiObject2 obj, BySelector selector) |
| throws UiObjectNotFoundException { |
| if (obj == null) { |
| throw newUiObjectNotFoundException(selector); |
| } |
| } |
| |
| |
| private static void assertUiObjectFound(UiObject obj, UiSelector selector) |
| throws UiObjectNotFoundException { |
| if (obj == null) { |
| throw newUiObjectNotFoundException(selector); |
| } |
| } |
| |
| private static UiObjectNotFoundException newUiObjectNotFoundException(Object selector) { |
| return new UiObjectNotFoundException( |
| String.format("UI object not found: %s", selector.toString())); |
| } |
| } |