1 /*
2  * Copyright (C) 2016 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.language;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.Mockito.doReturn;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.app.Activity;
30 import android.app.admin.DevicePolicyManager;
31 import android.content.ComponentName;
32 import android.content.ContentResolver;
33 import android.content.Context;
34 import android.content.pm.PackageManager;
35 import android.content.res.Resources;
36 import android.hardware.input.InputManager;
37 import android.os.UserManager;
38 import android.provider.Settings;
39 import android.view.autofill.AutofillManager;
40 import android.view.inputmethod.InputMethodInfo;
41 import android.view.inputmethod.InputMethodManager;
42 import android.view.textservice.TextServicesManager;
43 
44 import androidx.lifecycle.LifecycleObserver;
45 
46 import com.android.settings.R;
47 import com.android.settings.dashboard.SummaryLoader;
48 import com.android.settings.testutils.XmlTestUtils;
49 import com.android.settingslib.core.AbstractPreferenceController;
50 import com.android.settingslib.core.lifecycle.Lifecycle;
51 
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.Answers;
56 import org.mockito.Mock;
57 import org.mockito.MockitoAnnotations;
58 import org.robolectric.RobolectricTestRunner;
59 import org.robolectric.RuntimeEnvironment;
60 
61 import java.util.ArrayList;
62 import java.util.List;
63 
64 @RunWith(RobolectricTestRunner.class)
65 public class LanguageAndInputSettingsTest {
66 
67     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
68     private Activity mActivity;
69     @Mock
70     private PackageManager mPackageManager;
71     @Mock
72     private InputManager mIm;
73     @Mock
74     private InputMethodManager mImm;
75     @Mock
76     private DevicePolicyManager mDpm;
77     @Mock
78     private InputMethodManager mInputMethodManager;
79     @Mock
80     private AutofillManager mAutofillManager;
81     private TestFragment mFragment;
82 
83     @Before
setUp()84     public void setUp() {
85         MockitoAnnotations.initMocks(this);
86         when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mock(UserManager.class));
87         when(mActivity.getSystemService(Context.INPUT_SERVICE))
88                 .thenReturn(mock(InputManager.class));
89         when(mActivity.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
90         when(mActivity.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE))
91                 .thenReturn(mock(TextServicesManager.class));
92         when(mActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mDpm);
93         when(mActivity.getSystemService(Context.INPUT_METHOD_SERVICE)).thenReturn(mImm);
94         when((Object) mActivity.getSystemService(AutofillManager.class))
95                 .thenReturn(mAutofillManager);
96         mFragment = new TestFragment(mActivity);
97     }
98 
99     @Test
testGetPreferenceScreenResId()100     public void testGetPreferenceScreenResId() {
101         assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.language_and_input);
102     }
103 
104     @Test
testGetPreferenceControllers_shouldRegisterLifecycleObservers()105     public void testGetPreferenceControllers_shouldRegisterLifecycleObservers() {
106         final List<AbstractPreferenceController> controllers =
107                 mFragment.createPreferenceControllers(mActivity);
108         int lifecycleObserverCount = 0;
109         for (AbstractPreferenceController controller : controllers) {
110             if (controller instanceof LifecycleObserver) {
111                 lifecycleObserverCount++;
112             }
113         }
114         verify(mFragment.getSettingsLifecycle(), times(lifecycleObserverCount))
115                 .addObserver(any(LifecycleObserver.class));
116     }
117 
118     @Test
testGetPreferenceControllers_shouldAllBeCreated()119     public void testGetPreferenceControllers_shouldAllBeCreated() {
120         final List<AbstractPreferenceController> controllers =
121                 mFragment.createPreferenceControllers(mActivity);
122 
123         assertThat(controllers.isEmpty()).isFalse();
124     }
125 
126     @Test
testSummary_shouldSetToCurrentImeName()127     public void testSummary_shouldSetToCurrentImeName() {
128         final Activity activity = mock(Activity.class);
129         final SummaryLoader loader = mock(SummaryLoader.class);
130         final ComponentName componentName = new ComponentName("pkg", "cls");
131         final ContentResolver cr = activity.getContentResolver();
132         Settings.Secure.putString(cr, Settings.Secure.DEFAULT_INPUT_METHOD,
133                 componentName.flattenToString());
134         when(activity.getSystemService(Context.INPUT_METHOD_SERVICE))
135                 .thenReturn(mInputMethodManager);
136         when(activity.getPackageManager()).thenReturn(mPackageManager);
137         final List<InputMethodInfo> imis = new ArrayList<>();
138         imis.add(mock(InputMethodInfo.class));
139         when(imis.get(0).getPackageName()).thenReturn(componentName.getPackageName());
140         when(mInputMethodManager.getInputMethodList()).thenReturn(imis);
141 
142         SummaryLoader.SummaryProvider provider = LanguageAndInputSettings.SUMMARY_PROVIDER_FACTORY
143                 .createSummaryProvider(activity, loader);
144 
145         provider.setListening(true);
146 
147         verify(imis.get(0)).loadLabel(mPackageManager);
148         verify(loader).setSummary(provider, null);
149     }
150 
151     @Test
testNonIndexableKeys_existInXmlLayout()152     public void testNonIndexableKeys_existInXmlLayout() {
153         final Context context = spy(RuntimeEnvironment.application);
154         final Resources res = spy(RuntimeEnvironment.application.getResources());
155         final InputManager inputManager = mock(InputManager.class);
156         final TextServicesManager textServicesManager = mock(TextServicesManager.class);
157         when(inputManager.getInputDeviceIds()).thenReturn(new int[0]);
158         doReturn(inputManager).when(context).getSystemService(Context.INPUT_SERVICE);
159         doReturn(textServicesManager).when(context)
160             .getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
161         doReturn(res).when(context).getResources();
162         doReturn(false).when(res)
163                 .getBoolean(com.android.internal.R.bool.config_supportSystemNavigationKeys);
164         final List<String> niks =
165             LanguageAndInputSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context);
166         LanguageAndInputSettings settings = new LanguageAndInputSettings();
167         final int xmlId = settings.getPreferenceScreenResId();
168 
169         final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
170 
171         assertThat(keys).containsAllIn(niks);
172     }
173 
174     @Test
testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen()175     public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
176         final Context context = spy(RuntimeEnvironment.application);
177         final TextServicesManager textServicesManager = mock(TextServicesManager.class);
178         doReturn(textServicesManager).when(context)
179             .getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
180         final LanguageAndInputSettings fragment = new LanguageAndInputSettings();
181         final List<String> preferenceScreenKeys =
182             XmlTestUtils.getKeysFromPreferenceXml(context, fragment.getPreferenceScreenResId());
183         final List<String> preferenceKeys = new ArrayList<>();
184 
185         for (AbstractPreferenceController controller : fragment.createPreferenceControllers(context)) {
186             preferenceKeys.add(controller.getPreferenceKey());
187         }
188 
189         assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys);
190     }
191 
192     /**
193      * Test fragment to expose lifecycle and context so we can verify behavior for observables.
194      */
195     public static class TestFragment extends LanguageAndInputSettings {
196 
197         private Lifecycle mLifecycle;
198         private Context mContext;
199 
TestFragment(Context context)200         public TestFragment(Context context) {
201             mContext = context;
202             mLifecycle = mock(Lifecycle.class);
203         }
204 
205         @Override
getContext()206         public Context getContext() {
207             return mContext;
208         }
209 
210         @Override
getSettingsLifecycle()211         public Lifecycle getSettingsLifecycle() {
212             if (mLifecycle == null) {
213                 return super.getSettingsLifecycle();
214             }
215             return mLifecycle;
216         }
217     }
218 }
219