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 android.app.Activity;
20 import android.app.settings.SettingsEnums;
21 import android.content.ComponentName;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.provider.SearchIndexableResource;
26 import android.provider.Settings;
27 import android.text.TextUtils;
28 import android.view.inputmethod.InputMethodInfo;
29 import android.view.inputmethod.InputMethodManager;
30 
31 import androidx.annotation.NonNull;
32 import androidx.annotation.Nullable;
33 
34 import com.android.settings.R;
35 import com.android.settings.dashboard.DashboardFragment;
36 import com.android.settings.dashboard.SummaryLoader;
37 import com.android.settings.inputmethod.PhysicalKeyboardPreferenceController;
38 import com.android.settings.inputmethod.SpellCheckerPreferenceController;
39 import com.android.settings.inputmethod.VirtualKeyboardPreferenceController;
40 import com.android.settings.search.BaseSearchIndexProvider;
41 import com.android.settings.widget.PreferenceCategoryController;
42 import com.android.settingslib.core.AbstractPreferenceController;
43 import com.android.settingslib.core.lifecycle.Lifecycle;
44 import com.android.settingslib.search.SearchIndexable;
45 
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.List;
49 
50 @SearchIndexable
51 public class LanguageAndInputSettings extends DashboardFragment {
52 
53     private static final String TAG = "LangAndInputSettings";
54 
55     private static final String KEY_KEYBOARDS_CATEGORY = "keyboards_category";
56     private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
57     private static final String KEY_POINTER_AND_TTS_CATEGORY = "pointer_and_tts_category";
58 
59     @Override
getMetricsCategory()60     public int getMetricsCategory() {
61         return SettingsEnums.SETTINGS_LANGUAGE_CATEGORY;
62     }
63 
64     @Override
getLogTag()65     protected String getLogTag() {
66         return TAG;
67     }
68 
69     @Override
onResume()70     public void onResume() {
71         super.onResume();
72         // Hack to update action bar title. It's necessary to refresh title because this page user
73         // can change locale from here and fragment won't relaunch. Once language changes, title
74         // must display in the new language.
75         final Activity activity = getActivity();
76         if (activity == null) {
77             return;
78         }
79         activity.setTitle(R.string.language_settings);
80     }
81 
82     @Override
getPreferenceScreenResId()83     protected int getPreferenceScreenResId() {
84         return R.xml.language_and_input;
85     }
86 
87     @Override
createPreferenceControllers(Context context)88     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
89         return buildPreferenceControllers(context, getSettingsLifecycle());
90     }
91 
buildPreferenceControllers( @onNull Context context, @Nullable Lifecycle lifecycle)92     private static List<AbstractPreferenceController> buildPreferenceControllers(
93             @NonNull Context context, @Nullable Lifecycle lifecycle) {
94         final List<AbstractPreferenceController> controllers = new ArrayList<>();
95         // Language
96         controllers.add(new PhoneLanguagePreferenceController(context));
97 
98         // Input
99         final VirtualKeyboardPreferenceController virtualKeyboardPreferenceController =
100                 new VirtualKeyboardPreferenceController(context);
101         final PhysicalKeyboardPreferenceController physicalKeyboardPreferenceController =
102                 new PhysicalKeyboardPreferenceController(context, lifecycle);
103         controllers.add(virtualKeyboardPreferenceController);
104         controllers.add(physicalKeyboardPreferenceController);
105         controllers.add(new PreferenceCategoryController(context,
106                 KEY_KEYBOARDS_CATEGORY).setChildren(
107                 Arrays.asList(virtualKeyboardPreferenceController,
108                         physicalKeyboardPreferenceController)));
109 
110         // Pointer and Tts
111         final TtsPreferenceController ttsPreferenceController =
112                 new TtsPreferenceController(context, KEY_TEXT_TO_SPEECH);
113         controllers.add(ttsPreferenceController);
114         final PointerSpeedController pointerController = new PointerSpeedController(context);
115         controllers.add(pointerController);
116         controllers.add(new PreferenceCategoryController(context,
117                 KEY_POINTER_AND_TTS_CATEGORY).setChildren(
118                 Arrays.asList(pointerController, ttsPreferenceController)));
119 
120         // Input Assistance
121         controllers.add(new SpellCheckerPreferenceController(context));
122 
123         return controllers;
124     }
125 
126     private static class SummaryProvider implements SummaryLoader.SummaryProvider {
127 
128         private final Context mContext;
129         private final SummaryLoader mSummaryLoader;
130 
SummaryProvider(Context context, SummaryLoader summaryLoader)131         public SummaryProvider(Context context, SummaryLoader summaryLoader) {
132             mContext = context;
133             mSummaryLoader = summaryLoader;
134         }
135 
136         @Override
setListening(boolean listening)137         public void setListening(boolean listening) {
138             final ContentResolver contentResolver = mContext.getContentResolver();
139             if (listening) {
140                 final String flattenComponent = Settings.Secure.getString(
141                         contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD);
142                 if (!TextUtils.isEmpty(flattenComponent)) {
143                     final PackageManager packageManage = mContext.getPackageManager();
144                     final String pkg = ComponentName.unflattenFromString(flattenComponent)
145                             .getPackageName();
146                     final InputMethodManager imm = (InputMethodManager)
147                             mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
148                     final List<InputMethodInfo> imis = imm.getInputMethodList();
149                     for (InputMethodInfo imi : imis) {
150                         if (TextUtils.equals(imi.getPackageName(), pkg)) {
151                             mSummaryLoader.setSummary(this, imi.loadLabel(packageManage));
152                             return;
153                         }
154                     }
155                 }
156                 mSummaryLoader.setSummary(this, "");
157             }
158         }
159     }
160 
161     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
162             = (activity, summaryLoader) -> new SummaryProvider(activity, summaryLoader);
163 
164     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
165             new BaseSearchIndexProvider() {
166                 @Override
167                 public List<SearchIndexableResource> getXmlResourcesToIndex(
168                         Context context, boolean enabled) {
169                     final SearchIndexableResource sir = new SearchIndexableResource(context);
170                     sir.xmlResId = R.xml.language_and_input;
171                     return Arrays.asList(sir);
172                 }
173 
174                 @Override
175                 public List<AbstractPreferenceController> createPreferenceControllers(
176                         Context context) {
177                     return buildPreferenceControllers(context, null);
178                 }
179             };
180 }
181