1 /* 2 * Copyright (C) 2021 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.settings.display.darkmode; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.app.Instrumentation; 22 import android.app.TimePickerDialog; 23 import android.app.UiModeManager; 24 import android.content.Intent; 25 import android.content.res.Configuration; 26 import android.provider.Settings; 27 import android.util.Log; 28 29 import androidx.fragment.app.Fragment; 30 import androidx.fragment.app.FragmentActivity; 31 import androidx.test.core.app.ActivityScenario; 32 import androidx.test.ext.junit.rules.ActivityScenarioRule; 33 import androidx.test.ext.junit.runners.AndroidJUnit4; 34 import androidx.test.filters.SmallTest; 35 import androidx.test.platform.app.InstrumentationRegistry; 36 import androidx.test.runner.lifecycle.Stage; 37 38 import com.android.settings.testutils.CommonUtils; 39 import com.android.settings.testutils.UiUtils; 40 41 import org.junit.After; 42 import org.junit.Before; 43 import org.junit.Rule; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 47 import java.time.LocalTime; 48 49 @RunWith(AndroidJUnit4.class) 50 @SmallTest 51 public class DarkThemeScheduleComponentTest { 52 private static final int DIALOG_START_TIME = 0; 53 private static final int DIALOG_END_TIME = 1; 54 /** The identifier for the positive button. */ 55 private static final int BUTTON_POSITIVE = -1; 56 public final String TAG = this.getClass().getName(); 57 private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); 58 59 @Rule 60 public ActivityScenarioRule<com.android.settings.Settings.DarkThemeSettingsActivity> rule = 61 new ActivityScenarioRule<>( 62 new Intent( 63 Settings.ACTION_DARK_THEME_SETTINGS).setFlags( 64 Intent.FLAG_ACTIVITY_NEW_TASK)); 65 private UiModeManager mUiModeManager; 66 67 @Before setUp()68 public void setUp() { 69 mUiModeManager = mInstrumentation.getTargetContext().getSystemService(UiModeManager.class); 70 if (mUiModeManager.getNightMode() != UiModeManager.MODE_NIGHT_NO) { 71 mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO); 72 } 73 } 74 test_step_for_custom_time(int startTimeDiff, int endTimeDiff)75 private void test_step_for_custom_time(int startTimeDiff, int endTimeDiff) { 76 77 ActivityScenario scenario = rule.getScenario(); 78 scenario.onActivity(activity -> { 79 mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_CUSTOM); 80 Fragment f = 81 ((FragmentActivity) activity).getSupportFragmentManager().getFragments().get(0); 82 DarkModeSettingsFragment fragment = (DarkModeSettingsFragment) f; 83 84 setCustomTime(fragment, DIALOG_START_TIME, LocalTime.now().plusMinutes(startTimeDiff)); 85 setCustomTime(fragment, DIALOG_END_TIME, LocalTime.now().plusMinutes(endTimeDiff)); 86 87 // The night mode need to reopen the screen to trigger UI change after mode change. 88 CommonUtils.reopenScreen(); 89 }); 90 91 // Relaunch the scenario to make sure UI apply new mode. 92 scenario.onActivity(activity -> { 93 Log.d(TAG, "Activity Recreated!"); 94 UiUtils.waitForActivitiesInStage(2000, Stage.RESUMED); 95 }); 96 } 97 98 @Test test_dark_mode_in_custom_time()99 public void test_dark_mode_in_custom_time() { 100 test_step_for_custom_time(-1, 11); 101 assertThat(checkNightMode(true)).isTrue(); 102 } 103 104 @Test test_dark_mode_after_custom_time()105 public void test_dark_mode_after_custom_time() { 106 test_step_for_custom_time(-11, -1); 107 assertThat(checkNightMode(false)).isTrue(); 108 } 109 110 @Test test_dark_mode_before_custom_time()111 public void test_dark_mode_before_custom_time() { 112 test_step_for_custom_time(2, 20); 113 assertThat(checkNightMode(false)).isTrue(); 114 } 115 116 /** 117 * Sets custom time for night mode. 118 * 119 * @param fragment The DarkModeSettingsFragment. 120 * @param dialogId Dialog id for start time or end time. 121 * @param time The time to be set. 122 */ setCustomTime(DarkModeSettingsFragment fragment, int dialogId, LocalTime time)123 private void setCustomTime(DarkModeSettingsFragment fragment, int dialogId, LocalTime time) { 124 Log.d(TAG, "Start to set custom time " + (dialogId == DIALOG_START_TIME ? "StartTime" 125 : "EndTime") + " to " + time.getHour() + ":" + time.getMinute()); 126 TimePickerDialog startTimeDialog = (TimePickerDialog) fragment.onCreateDialog(dialogId); 127 startTimeDialog.updateTime(time.getHour(), time.getMinute()); 128 startTimeDialog.onClick(startTimeDialog, BUTTON_POSITIVE); 129 } 130 checkNightMode(boolean isNightMode)131 private boolean checkNightMode(boolean isNightMode) { 132 int mask = (isNightMode ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO); 133 int mode = mInstrumentation.getTargetContext().getResources().getConfiguration().uiMode; 134 return (mode & mask) != 0; 135 } 136 137 @After tearDown()138 public void tearDown() { 139 Log.d(TAG, "tearDown."); 140 if (mUiModeManager.getNightMode() != UiModeManager.MODE_NIGHT_NO) { 141 mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO); 142 } 143 } 144 } 145