• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.car.settings.common;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.annotation.Nullable;
22 import android.car.drivingstate.CarUxRestrictions;
23 
24 import androidx.fragment.app.Fragment;
25 import androidx.preference.Preference;
26 import androidx.test.platform.app.InstrumentationRegistry;
27 import androidx.test.rule.ActivityTestRule;
28 
29 import com.android.car.settings.R;
30 import com.android.car.settings.testutils.BaseTestSettingsFragment;
31 import com.android.car.settings.testutils.DualPaneTestActivity;
32 import com.android.car.settings.testutils.EmptySettingsFragment;
33 import com.android.car.settings.testutils.TestTopLevelMenuFragment;
34 import com.android.car.ui.toolbar.Toolbar;
35 import com.android.car.ui.toolbar.ToolbarController;
36 
37 import org.junit.Rule;
38 import org.junit.Test;
39 
40 import java.util.concurrent.atomic.AtomicReference;
41 
42 public class DualPaneBaseCarSettingsActivityTest
43         extends BaseCarSettingsActivityTestCase<DualPaneTestActivity> {
44 
45     @Rule
46     public ActivityTestRule<DualPaneTestActivity> mActivityTestRule =
47             new ActivityTestRule<>(DualPaneTestActivity.class);
48 
49     @Override
getActivityTestRule()50     ActivityTestRule<DualPaneTestActivity> getActivityTestRule() {
51         return mActivityTestRule;
52     }
53 
54     @Test
onPreferenceStartFragment_launchesFragment()55     public void onPreferenceStartFragment_launchesFragment() throws Throwable {
56         Preference pref = new Preference(mContext);
57         pref.setFragment(BaseTestSettingsFragment.class.getName());
58 
59         mActivityTestRule.runOnUiThread(() ->
60                 mActivity.onPreferenceStartFragment(/* caller= */ null, pref));
61         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
62 
63         assertThat(mActivity.getSupportFragmentManager().findFragmentById(
64                 R.id.fragment_container)).isInstanceOf(BaseTestSettingsFragment.class);
65     }
66 
67     @Test
onUxRestrictionsChanged_topFragmentInBackStackHasUpdatedUxRestrictions()68     public void onUxRestrictionsChanged_topFragmentInBackStackHasUpdatedUxRestrictions()
69             throws Throwable {
70         CarUxRestrictions oldUxRestrictions = new CarUxRestrictions.Builder(
71                 /* reqOpt= */ true,
72                 CarUxRestrictions.UX_RESTRICTIONS_BASELINE,
73                 /* timestamp= */ 0
74         ).build();
75 
76         CarUxRestrictions newUxRestrictions = new CarUxRestrictions.Builder(
77                 /* reqOpt= */ true,
78                 CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP,
79                 /* timestamp= */ 0
80         ).build();
81 
82         AtomicReference<BaseTestSettingsFragment> fragmentA = new AtomicReference<>();
83         AtomicReference<BaseTestSettingsFragment> fragmentB = new AtomicReference<>();
84 
85         mActivityTestRule.runOnUiThread(() -> {
86             fragmentA.set(new BaseTestSettingsFragment());
87             fragmentB.set(new BaseTestSettingsFragment());
88             mActivity.launchFragment(fragmentA.get());
89             mActivity.onUxRestrictionsChanged(oldUxRestrictions);
90             mActivity.launchFragment(fragmentB.get());
91             mActivity.onUxRestrictionsChanged(newUxRestrictions);
92         });
93         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
94 
95         assertThat(
96                 fragmentB.get().getUxRestrictions().isSameRestrictions(newUxRestrictions)).isTrue();
97     }
98 
99     @Test
onBackStackChanged_uxRestrictionsChanged_currentFragmentHasUpdatedUxRestrictions()100     public void onBackStackChanged_uxRestrictionsChanged_currentFragmentHasUpdatedUxRestrictions()
101             throws Throwable {
102         CarUxRestrictions oldUxRestrictions = new CarUxRestrictions.Builder(
103                 /* reqOpt= */ true,
104                 CarUxRestrictions.UX_RESTRICTIONS_BASELINE,
105                 /* timestamp= */ 0
106         ).build();
107 
108         CarUxRestrictions newUxRestrictions = new CarUxRestrictions.Builder(
109                 /* reqOpt= */ true,
110                 CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP,
111                 /* timestamp= */ 0
112         ).build();
113 
114         AtomicReference<BaseTestSettingsFragment> fragmentA = new AtomicReference<>();
115         AtomicReference<BaseTestSettingsFragment> fragmentB = new AtomicReference<>();
116 
117         mActivityTestRule.runOnUiThread(() -> {
118             fragmentA.set(new BaseTestSettingsFragment());
119             fragmentB.set(new BaseTestSettingsFragment());
120             mActivity.launchFragment(fragmentA.get());
121             mActivity.onUxRestrictionsChanged(oldUxRestrictions);
122             mActivity.launchFragment(fragmentB.get());
123             mActivity.onUxRestrictionsChanged(newUxRestrictions);
124             mActivity.goBack();
125         });
126         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
127 
128         assertThat(
129                 fragmentA.get().getUxRestrictions().isSameRestrictions(newUxRestrictions)).isTrue();
130     }
131 
132     @Test
onBackStackChanged_toolbarUpdated()133     public void onBackStackChanged_toolbarUpdated() throws Throwable {
134         ToolbarController toolbar = mActivity.getToolbar();
135 
136         mActivityTestRule.runOnUiThread(() -> {
137             BaseTestSettingsFragment fragment1 = new BaseTestSettingsFragment();
138             mActivity.launchFragment(fragment1);
139         });
140         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
141 
142         assertThat(toolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
143                 Toolbar.NavButtonMode.DISABLED);
144 
145         mActivityTestRule.runOnUiThread(() -> {
146             BaseTestSettingsFragment fragment2 = new BaseTestSettingsFragment();
147             mActivity.launchFragment(fragment2);
148         });
149         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
150 
151         assertThat(toolbar.getNavButtonMode()).isEqualTo(Toolbar.NavButtonMode.BACK);
152 
153         mActivityTestRule.runOnUiThread(() -> mActivity.goBack());
154         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
155 
156         assertThat(toolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
157                 Toolbar.NavButtonMode.DISABLED);
158     }
159 
160     @Test
onActivityCreated_noFragment_topLevelMenuFocused()161     public void onActivityCreated_noFragment_topLevelMenuFocused() throws Throwable {
162         assertThat(mActivity.findViewById(R.id.top_level_menu).hasFocus()).isTrue();
163     }
164 
165     @Test
onActivityCreated_homepage_topLevelMenuFocused()166     public void onActivityCreated_homepage_topLevelMenuFocused() throws Throwable {
167         ActivityTestRule<TestDualPaneHomepageActivity> activityTestRule =
168                 new ActivityTestRule<>(TestDualPaneHomepageActivity.class);
169         activityTestRule.launchActivity(null);
170         mActivity = activityTestRule.getActivity();
171         mFragmentManager = activityTestRule.getActivity().getSupportFragmentManager();
172 
173         assertThat(mActivity.findViewById(R.id.top_level_menu).hasFocus()).isTrue();
174     }
175 
176     @Test
onActivityCreated_hasFragment_contentFocused()177     public void onActivityCreated_hasFragment_contentFocused() throws Throwable {
178         ActivityTestRule<TestDualPaneFragmentActivity> activityTestRule =
179                 new ActivityTestRule<>(TestDualPaneFragmentActivity.class);
180         activityTestRule.launchActivity(null);
181         mActivity = activityTestRule.getActivity();
182         mFragmentManager = activityTestRule.getActivity().getSupportFragmentManager();
183 
184         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
185     }
186 
187     @Test
onTopLevelPreferenceTapped_focusUpdated()188     public void onTopLevelPreferenceTapped_focusUpdated() throws Throwable {
189         setUpTopLevelTestFragment();
190         mActivityTestRule.runOnUiThread(() ->
191                 mTopLevelFragment.getPreferenceScreen().getPreference(0).performClick());
192         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
193         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
194     }
195 
196     @Test
onFragmentLaunched_maintainContentFocus()197     public void onFragmentLaunched_maintainContentFocus() throws Throwable {
198         mActivityTestRule.runOnUiThread(() -> {
199             BaseTestSettingsFragment fragment = new BaseTestSettingsFragment();
200             mActivity.launchFragment(fragment);
201         });
202         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
203         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
204         mActivityTestRule.runOnUiThread(() ->
205                 getCurrentFragment().getPreferenceScreen().getPreference(0).performClick());
206         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
207         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
208     }
209 
210     @Test
onBack_maintainContentFocus()211     public void onBack_maintainContentFocus() throws Throwable {
212         mActivityTestRule.runOnUiThread(() -> {
213             BaseTestSettingsFragment fragment1 = new BaseTestSettingsFragment();
214             mActivity.launchFragment(fragment1);
215             BaseTestSettingsFragment fragment2 = new BaseTestSettingsFragment();
216             mActivity.launchFragment(fragment2);
217         });
218         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
219         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
220         mActivityTestRule.runOnUiThread(() -> mActivity.goBack());
221         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
222         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
223     }
224 
225     @Test
onPreferenceDisabled_maintainContentFocus()226     public void onPreferenceDisabled_maintainContentFocus() throws Throwable {
227         mActivityTestRule.runOnUiThread(() -> {
228             BaseTestSettingsFragment fragment = new BaseTestSettingsFragment();
229             mActivity.launchFragment(fragment);
230         });
231         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
232         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
233         mActivityTestRule.runOnUiThread(() ->
234                 getCurrentFragment().getPreferenceScreen().getPreference(0).setEnabled(false));
235         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
236         assertThat(getCurrentFragment().getView().hasFocus()).isTrue();
237     }
238 
239     @Test
onFragmentLaunched_noFocusableElements_parkingViewFocused()240     public void onFragmentLaunched_noFocusableElements_parkingViewFocused() throws Throwable {
241         mActivityTestRule.runOnUiThread(() -> {
242             EmptySettingsFragment fragment = new EmptySettingsFragment();
243             mActivity.launchFragment(fragment);
244         });
245         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
246         assertThat(mActivity.findViewById(R.id.settings_focus_parking_view).isFocused()).isTrue();
247     }
248 
setUpTopLevelTestFragment()249     private void setUpTopLevelTestFragment() throws Throwable {
250         String topLevelMenuTag = "top_level_menu";
251         mActivityTestRule.runOnUiThread(() -> {
252             mFragmentManager.beginTransaction()
253                     .replace(R.id.top_level_menu, new TestTopLevelMenuFragment(), topLevelMenuTag)
254                     .commitNow();
255         });
256         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
257         mTopLevelFragment = (TopLevelMenuFragment) mFragmentManager.findFragmentByTag(
258                 topLevelMenuTag);
259     }
260 
261     public static class TestDualPaneHomepageActivity extends DualPaneTestActivity {
262         @Nullable
263         @Override
getInitialFragment()264         protected Fragment getInitialFragment() {
265             return new BaseTestSettingsFragment();
266         }
267 
268         @Override
shouldFocusContentOnLaunch()269         protected boolean shouldFocusContentOnLaunch() {
270             return false;
271         }
272     }
273 
274     public static class TestDualPaneFragmentActivity extends DualPaneTestActivity {
275         @Nullable
276         @Override
getInitialFragment()277         protected Fragment getInitialFragment() {
278             return new BaseTestSettingsFragment();
279         }
280     }
281 }
282