1 /* 2 * Copyright (C) 2014 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.tv.settings.system; 18 19 import com.android.tv.settings.ActionBehavior; 20 import com.android.tv.settings.ActionKey; 21 import com.android.tv.settings.BaseSettingsActivity; 22 import com.android.tv.settings.R; 23 import com.android.tv.settings.dialog.old.Action; 24 import com.android.tv.settings.dialog.old.ActionAdapter; 25 26 import android.app.ActivityManagerNative; 27 import android.content.Intent; 28 import android.content.pm.PackageManager; 29 import android.os.Bundle; 30 import android.os.RemoteException; 31 import android.os.UserHandle; 32 import android.provider.Settings; 33 import android.text.TextUtils; 34 import android.util.Log; 35 import android.view.inputmethod.InputMethodInfo; 36 import android.view.inputmethod.InputMethodManager; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 41 public class KeyboardActivity extends BaseSettingsActivity implements ActionAdapter.Listener { 42 43 private static final String TAG = "KeyboardActivity"; 44 private static final boolean DEBUG = false; 45 46 private static final String INPUT_METHOD_SEPARATOR = ":"; 47 private InputMethodManager mInputMan; 48 49 @Override 50 public void onCreate(Bundle savedInstanceState) { 51 mInputMan = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 52 // enable all available input methods 53 enableAllInputMethods(); 54 55 super.onCreate(savedInstanceState); 56 } 57 58 @Override 59 public void onActionClicked(Action action) { 60 /* 61 * For list preferences 62 */ 63 String key = action.getKey(); 64 switch ((ActionType) mState) { 65 case KEYBOARD_OVERVIEW_CURRENT_KEYBOARD: 66 setInputMethod(key); 67 goBack(); 68 return; 69 default: 70 break; 71 } 72 73 /* 74 * For regular states 75 */ 76 ActionKey<ActionType, ActionBehavior> actionKey = new ActionKey<ActionType, ActionBehavior>( 77 ActionType.class, ActionBehavior.class, action.getKey()); 78 final ActionType type = actionKey.getType(); 79 switch (type) { 80 case KEYBOARD_OVERVIEW_CONFIGURE: 81 InputMethodInfo currentInputMethodInfo = getCurrentInputMethodInfo(); 82 if (currentInputMethodInfo != null && 83 currentInputMethodInfo.getSettingsActivity() != null) { 84 startActivity(getInputMethodSettingsIntent(currentInputMethodInfo)); 85 } 86 return; 87 default: 88 } 89 90 final ActionBehavior behavior = actionKey.getBehavior(); 91 if (behavior == null) { 92 return; 93 } 94 switch (behavior) { 95 case INIT: 96 setState(type, true); 97 break; 98 case ON: 99 setProperty(true); 100 break; 101 case OFF: 102 setProperty(false); 103 break; 104 default: 105 } 106 } 107 108 @Override 109 protected Object getInitialState() { 110 return ActionType.KEYBOARD_OVERVIEW; 111 } 112 113 @Override 114 protected void refreshActionList() { 115 mActions.clear(); 116 InputMethodInfo currentInputMethodInfo = getCurrentInputMethodInfo(); 117 switch ((ActionType) mState) { 118 case KEYBOARD_OVERVIEW: 119 String name = getDefaultInputMethodName(); 120 mActions.add(ActionType.KEYBOARD_OVERVIEW_CURRENT_KEYBOARD 121 .toAction(mResources, TextUtils.isEmpty(name) ? "" : name)); 122 123 if (currentInputMethodInfo != null 124 && currentInputMethodInfo.getSettingsActivity() != null) { 125 mActions.add(ActionType.KEYBOARD_OVERVIEW_CONFIGURE.toAction(mResources)); 126 } 127 break; 128 case KEYBOARD_OVERVIEW_CURRENT_KEYBOARD: 129 mActions = Action.createActionsFromArrays(getInputMethodIds(), 130 getInputMethodNames()); 131 for (Action action : mActions) { 132 action.setChecked(currentInputMethodInfo != null && 133 action.getKey().equals(currentInputMethodInfo.getId())); 134 } 135 break; 136 default: 137 break; 138 } 139 } 140 141 @Override 142 protected void updateView() { 143 refreshActionList(); 144 switch ((ActionType) mState) { 145 case KEYBOARD_OVERVIEW: 146 setView(R.string.system_keyboard, R.string.settings_app_name, 0, 147 R.drawable.ic_settings_keyboard); 148 break; 149 case KEYBOARD_OVERVIEW_CURRENT_KEYBOARD: 150 setView(R.string.title_current_keyboard, R.string.system_keyboard, 0, 151 R.drawable.ic_settings_keyboard); 152 break; 153 default: 154 break; 155 } 156 } 157 158 @Override 159 protected void setProperty(boolean enable) { 160 } 161 162 private String getDefaultInputMethodId() { 163 return Settings.Secure.getString(getContentResolver(), 164 Settings.Secure.DEFAULT_INPUT_METHOD); 165 } 166 167 private String getDefaultInputMethodName() { 168 String defaultInputMethodInfo = getDefaultInputMethodId(); 169 170 List<InputMethodInfo> enabledInputMethodInfos = new ArrayList<InputMethodInfo>( 171 mInputMan.getEnabledInputMethodList()); 172 for (InputMethodInfo info : enabledInputMethodInfos) { 173 if (defaultInputMethodInfo.equals(info.getId())) { 174 return info.loadLabel(getPackageManager()).toString(); 175 } 176 } 177 return null; 178 } 179 180 private InputMethodInfo getCurrentInputMethodInfo() { 181 String defaultInputMethodInfo = getDefaultInputMethodId(); 182 183 List<InputMethodInfo> enabledInputMethodInfos = new ArrayList<InputMethodInfo>( 184 mInputMan.getEnabledInputMethodList()); 185 for (InputMethodInfo info : enabledInputMethodInfos) { 186 if (defaultInputMethodInfo.equals(info.getId())) { 187 return info; 188 } 189 } 190 return null; 191 } 192 193 private String[] getInputMethodNames() { 194 List<InputMethodInfo> enabledInputMethodInfos = new ArrayList<InputMethodInfo>( 195 mInputMan.getEnabledInputMethodList()); 196 int totalInputMethods = enabledInputMethodInfos.size(); 197 String[] inputMethodNames = new String[totalInputMethods]; 198 for (int i = 0; i < totalInputMethods; i++) { 199 inputMethodNames[i] = enabledInputMethodInfos.get(i) 200 .loadLabel(getPackageManager()).toString(); 201 } 202 return inputMethodNames; 203 } 204 205 private String[] getInputMethodIds() { 206 List<InputMethodInfo> enabledInputMethodInfos = new ArrayList<InputMethodInfo>( 207 mInputMan.getEnabledInputMethodList()); 208 int totalInputMethods = enabledInputMethodInfos.size(); 209 String[] inputMethodIds = new String[totalInputMethods]; 210 for (int i = 0; i < totalInputMethods; i++) { 211 inputMethodIds[i] = enabledInputMethodInfos.get(i).getId(); 212 } 213 return inputMethodIds; 214 } 215 216 private void setInputMethod(String imid) { 217 if (imid == null) { 218 throw new IllegalArgumentException("Unknown id: " + imid); 219 } 220 221 int userId; 222 try { 223 userId = ActivityManagerNative.getDefault().getCurrentUser().id; 224 Settings.Secure.putStringForUser(getContentResolver(), 225 Settings.Secure.DEFAULT_INPUT_METHOD, imid, userId); 226 227 if (ActivityManagerNative.isSystemReady()) { 228 Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED); 229 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 230 intent.putExtra("input_method_id", imid); 231 sendBroadcastAsUser(intent, UserHandle.CURRENT); 232 } 233 } catch (RemoteException e) { 234 Log.d(TAG, "set default input method remote exception"); 235 } 236 } 237 238 private void enableAllInputMethods() { 239 List<InputMethodInfo> allInputMethodInfos = 240 new ArrayList<InputMethodInfo>(mInputMan.getInputMethodList()); 241 boolean needAppendSeparator = false; 242 StringBuilder builder = new StringBuilder(); 243 for (InputMethodInfo imi : allInputMethodInfos) { 244 if (needAppendSeparator) { 245 builder.append(INPUT_METHOD_SEPARATOR); 246 } else { 247 needAppendSeparator = true; 248 } 249 builder.append(imi.getId()); 250 } 251 Settings.Secure.putString(getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS, 252 builder.toString()); 253 } 254 255 private Intent getInputMethodSettingsIntent(InputMethodInfo imi) { 256 final PackageManager pm = getPackageManager(); 257 final CharSequence label = imi.loadLabel(pm);// IME settings 258 final Intent intent; 259 final String settingsActivity = imi.getSettingsActivity(); 260 if (!TextUtils.isEmpty(settingsActivity)) { 261 intent = new Intent(Intent.ACTION_MAIN); 262 intent.setClassName(imi.getPackageName(), settingsActivity); 263 } else { 264 intent = null; 265 } 266 return intent; 267 } 268 } 269