IInputConnectionWrapper.java revision d24b8183b93e781080b2c16c487e60d51c12da31
1package com.android.internal.view; 2 3import com.android.internal.view.IInputContext; 4 5import android.os.Bundle; 6import android.os.Handler; 7import android.os.Looper; 8import android.os.Message; 9import android.os.RemoteException; 10import android.util.Log; 11import android.view.KeyEvent; 12import android.view.inputmethod.CompletionInfo; 13import android.view.inputmethod.ExtractedTextRequest; 14import android.view.inputmethod.InputConnection; 15 16import java.lang.ref.WeakReference; 17 18public class IInputConnectionWrapper extends IInputContext.Stub { 19 static final String TAG = "IInputConnectionWrapper"; 20 21 private static final int DO_GET_TEXT_AFTER_CURSOR = 10; 22 private static final int DO_GET_TEXT_BEFORE_CURSOR = 20; 23 private static final int DO_GET_CURSOR_CAPS_MODE = 30; 24 private static final int DO_GET_EXTRACTED_TEXT = 40; 25 private static final int DO_COMMIT_TEXT = 50; 26 private static final int DO_COMMIT_COMPLETION = 55; 27 private static final int DO_SET_SELECTION = 57; 28 private static final int DO_PERFORM_CONTEXT_MENU_ACTION = 58; 29 private static final int DO_SET_COMPOSING_TEXT = 60; 30 private static final int DO_FINISH_COMPOSING_TEXT = 65; 31 private static final int DO_SEND_KEY_EVENT = 70; 32 private static final int DO_DELETE_SURROUNDING_TEXT = 80; 33 private static final int DO_BEGIN_BATCH_EDIT = 90; 34 private static final int DO_END_BATCH_EDIT = 95; 35 private static final int DO_HIDE_STATUS_ICON = 100; 36 private static final int DO_SHOW_STATUS_ICON = 110; 37 private static final int DO_PERFORM_PRIVATE_COMMAND = 120; 38 private static final int DO_CLEAR_META_KEY_STATES = 130; 39 40 private WeakReference<InputConnection> mInputConnection; 41 42 private Looper mMainLooper; 43 private Handler mH; 44 45 static class SomeArgs { 46 Object arg1; 47 Object arg2; 48 IInputContextCallback callback; 49 int seq; 50 } 51 52 class MyHandler extends Handler { 53 MyHandler(Looper looper) { 54 super(looper); 55 } 56 57 @Override 58 public void handleMessage(Message msg) { 59 executeMessage(msg); 60 } 61 } 62 63 public IInputConnectionWrapper(Looper mainLooper, InputConnection conn) { 64 mInputConnection = new WeakReference<InputConnection>(conn); 65 mMainLooper = mainLooper; 66 mH = new MyHandler(mMainLooper); 67 } 68 69 public boolean isActive() { 70 return true; 71 } 72 73 public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) { 74 dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback)); 75 } 76 77 public void getTextBeforeCursor(int length, int flags, int seq, IInputContextCallback callback) { 78 dispatchMessage(obtainMessageIISC(DO_GET_TEXT_BEFORE_CURSOR, length, flags, seq, callback)); 79 } 80 81 public void getCursorCapsMode(int reqModes, int seq, IInputContextCallback callback) { 82 dispatchMessage(obtainMessageISC(DO_GET_CURSOR_CAPS_MODE, reqModes, seq, callback)); 83 } 84 85 public void getExtractedText(ExtractedTextRequest request, 86 int flags, int seq, IInputContextCallback callback) { 87 dispatchMessage(obtainMessageIOSC(DO_GET_EXTRACTED_TEXT, flags, 88 request, seq, callback)); 89 } 90 91 public void commitText(CharSequence text, int newCursorPosition) { 92 dispatchMessage(obtainMessageIO(DO_COMMIT_TEXT, newCursorPosition, text)); 93 } 94 95 public void commitCompletion(CompletionInfo text) { 96 dispatchMessage(obtainMessageO(DO_COMMIT_COMPLETION, text)); 97 } 98 99 public void setSelection(int start, int end) { 100 dispatchMessage(obtainMessageII(DO_SET_SELECTION, start, end)); 101 } 102 103 public void performContextMenuAction(int id) { 104 dispatchMessage(obtainMessageII(DO_PERFORM_CONTEXT_MENU_ACTION, id, 0)); 105 } 106 107 public void setComposingText(CharSequence text, int newCursorPosition) { 108 dispatchMessage(obtainMessageIO(DO_SET_COMPOSING_TEXT, newCursorPosition, text)); 109 } 110 111 public void finishComposingText() { 112 dispatchMessage(obtainMessage(DO_FINISH_COMPOSING_TEXT)); 113 } 114 115 public void sendKeyEvent(KeyEvent event) { 116 dispatchMessage(obtainMessageO(DO_SEND_KEY_EVENT, event)); 117 } 118 119 public void clearMetaKeyStates(int states) { 120 dispatchMessage(obtainMessageII(DO_CLEAR_META_KEY_STATES, states, 0)); 121 } 122 123 public void deleteSurroundingText(int leftLength, int rightLength) { 124 dispatchMessage(obtainMessageII(DO_DELETE_SURROUNDING_TEXT, 125 leftLength, rightLength)); 126 } 127 128 public void beginBatchEdit() { 129 dispatchMessage(obtainMessage(DO_BEGIN_BATCH_EDIT)); 130 } 131 132 public void endBatchEdit() { 133 dispatchMessage(obtainMessage(DO_END_BATCH_EDIT)); 134 } 135 136 public void hideStatusIcon() { 137 dispatchMessage(obtainMessage(DO_HIDE_STATUS_ICON)); 138 } 139 140 public void showStatusIcon(String packageName, int resId) { 141 dispatchMessage(obtainMessageIO(DO_SHOW_STATUS_ICON, resId, packageName)); 142 } 143 144 public void performPrivateCommand(String action, Bundle data) { 145 dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data)); 146 } 147 148 void dispatchMessage(Message msg) { 149 // If we are calling this from the main thread, then we can call 150 // right through. Otherwise, we need to send the message to the 151 // main thread. 152 if (Looper.myLooper() == mMainLooper) { 153 executeMessage(msg); 154 msg.recycle(); 155 return; 156 } 157 158 mH.sendMessage(msg); 159 } 160 161 void executeMessage(Message msg) { 162 switch (msg.what) { 163 case DO_GET_TEXT_AFTER_CURSOR: { 164 SomeArgs args = (SomeArgs)msg.obj; 165 try { 166 InputConnection ic = mInputConnection.get(); 167 if (ic == null || !isActive()) { 168 Log.w(TAG, "getTextAfterCursor on inactive InputConnection"); 169 args.callback.setTextAfterCursor(null, args.seq); 170 return; 171 } 172 args.callback.setTextAfterCursor(ic.getTextAfterCursor( 173 msg.arg1, msg.arg2), args.seq); 174 } catch (RemoteException e) { 175 Log.w(TAG, "Got RemoteException calling setTextAfterCursor", e); 176 } 177 return; 178 } 179 case DO_GET_TEXT_BEFORE_CURSOR: { 180 SomeArgs args = (SomeArgs)msg.obj; 181 try { 182 InputConnection ic = mInputConnection.get(); 183 if (ic == null || !isActive()) { 184 Log.w(TAG, "getTextBeforeCursor on inactive InputConnection"); 185 args.callback.setTextBeforeCursor(null, args.seq); 186 return; 187 } 188 args.callback.setTextBeforeCursor(ic.getTextBeforeCursor( 189 msg.arg1, msg.arg2), args.seq); 190 } catch (RemoteException e) { 191 Log.w(TAG, "Got RemoteException calling setTextBeforeCursor", e); 192 } 193 return; 194 } 195 case DO_GET_CURSOR_CAPS_MODE: { 196 SomeArgs args = (SomeArgs)msg.obj; 197 try { 198 InputConnection ic = mInputConnection.get(); 199 if (ic == null || !isActive()) { 200 Log.w(TAG, "getCursorCapsMode on inactive InputConnection"); 201 args.callback.setCursorCapsMode(0, args.seq); 202 return; 203 } 204 args.callback.setCursorCapsMode(ic.getCursorCapsMode(msg.arg1), 205 args.seq); 206 } catch (RemoteException e) { 207 Log.w(TAG, "Got RemoteException calling setCursorCapsMode", e); 208 } 209 return; 210 } 211 case DO_GET_EXTRACTED_TEXT: { 212 SomeArgs args = (SomeArgs)msg.obj; 213 try { 214 InputConnection ic = mInputConnection.get(); 215 if (ic == null || !isActive()) { 216 Log.w(TAG, "getExtractedText on inactive InputConnection"); 217 args.callback.setExtractedText(null, args.seq); 218 return; 219 } 220 args.callback.setExtractedText(ic.getExtractedText( 221 (ExtractedTextRequest)args.arg1, msg.arg1), args.seq); 222 } catch (RemoteException e) { 223 Log.w(TAG, "Got RemoteException calling setExtractedText", e); 224 } 225 return; 226 } 227 case DO_COMMIT_TEXT: { 228 InputConnection ic = mInputConnection.get(); 229 if (ic == null || !isActive()) { 230 Log.w(TAG, "commitText on inactive InputConnection"); 231 return; 232 } 233 ic.commitText((CharSequence)msg.obj, msg.arg1); 234 return; 235 } 236 case DO_SET_SELECTION: { 237 InputConnection ic = mInputConnection.get(); 238 if (ic == null || !isActive()) { 239 Log.w(TAG, "setSelection on inactive InputConnection"); 240 return; 241 } 242 ic.setSelection(msg.arg1, msg.arg2); 243 return; 244 } 245 case DO_PERFORM_CONTEXT_MENU_ACTION: { 246 InputConnection ic = mInputConnection.get(); 247 if (ic == null || !isActive()) { 248 Log.w(TAG, "performContextMenuAction on inactive InputConnection"); 249 return; 250 } 251 ic.performContextMenuAction(msg.arg1); 252 return; 253 } 254 case DO_COMMIT_COMPLETION: { 255 InputConnection ic = mInputConnection.get(); 256 if (ic == null || !isActive()) { 257 Log.w(TAG, "commitCompletion on inactive InputConnection"); 258 return; 259 } 260 ic.commitCompletion((CompletionInfo)msg.obj); 261 return; 262 } 263 case DO_SET_COMPOSING_TEXT: { 264 InputConnection ic = mInputConnection.get(); 265 if (ic == null || !isActive()) { 266 Log.w(TAG, "setComposingText on inactive InputConnection"); 267 return; 268 } 269 ic.setComposingText((CharSequence)msg.obj, msg.arg1); 270 return; 271 } 272 case DO_FINISH_COMPOSING_TEXT: { 273 InputConnection ic = mInputConnection.get(); 274 if (ic == null || !isActive()) { 275 Log.w(TAG, "finishComposingText on inactive InputConnection"); 276 return; 277 } 278 ic.finishComposingText(); 279 return; 280 } 281 case DO_SEND_KEY_EVENT: { 282 InputConnection ic = mInputConnection.get(); 283 if (ic == null || !isActive()) { 284 Log.w(TAG, "sendKeyEvent on inactive InputConnection"); 285 return; 286 } 287 ic.sendKeyEvent((KeyEvent)msg.obj); 288 return; 289 } 290 case DO_CLEAR_META_KEY_STATES: { 291 InputConnection ic = mInputConnection.get(); 292 if (ic == null || !isActive()) { 293 Log.w(TAG, "clearMetaKeyStates on inactive InputConnection"); 294 return; 295 } 296 ic.clearMetaKeyStates(msg.arg1); 297 return; 298 } 299 case DO_DELETE_SURROUNDING_TEXT: { 300 InputConnection ic = mInputConnection.get(); 301 if (ic == null || !isActive()) { 302 Log.w(TAG, "deleteSurroundingText on inactive InputConnection"); 303 return; 304 } 305 ic.deleteSurroundingText(msg.arg1, msg.arg2); 306 return; 307 } 308 case DO_BEGIN_BATCH_EDIT: { 309 InputConnection ic = mInputConnection.get(); 310 if (ic == null || !isActive()) { 311 Log.w(TAG, "beginBatchEdit on inactive InputConnection"); 312 return; 313 } 314 ic.beginBatchEdit(); 315 return; 316 } 317 case DO_END_BATCH_EDIT: { 318 InputConnection ic = mInputConnection.get(); 319 if (ic == null || !isActive()) { 320 Log.w(TAG, "endBatchEdit on inactive InputConnection"); 321 return; 322 } 323 ic.endBatchEdit(); 324 return; 325 } 326 case DO_HIDE_STATUS_ICON: { 327 InputConnection ic = mInputConnection.get(); 328 if (ic == null || !isActive()) { 329 Log.w(TAG, "hideStatusIcon on inactive InputConnection"); 330 return; 331 } 332 ic.hideStatusIcon(); 333 return; 334 } 335 case DO_SHOW_STATUS_ICON: { 336 InputConnection ic = mInputConnection.get(); 337 if (ic == null || !isActive()) { 338 Log.w(TAG, "showStatusIcon on inactive InputConnection"); 339 return; 340 } 341 ic.showStatusIcon((String)msg.obj, msg.arg1); 342 return; 343 } 344 case DO_PERFORM_PRIVATE_COMMAND: { 345 InputConnection ic = mInputConnection.get(); 346 if (ic == null || !isActive()) { 347 Log.w(TAG, "performPrivateCommand on inactive InputConnection"); 348 return; 349 } 350 SomeArgs args = (SomeArgs)msg.obj; 351 ic.performPrivateCommand((String)args.arg1, 352 (Bundle)args.arg2); 353 return; 354 } 355 } 356 Log.w(TAG, "Unhandled message code: " + msg.what); 357 } 358 359 Message obtainMessage(int what) { 360 return mH.obtainMessage(what); 361 } 362 363 Message obtainMessageII(int what, int arg1, int arg2) { 364 return mH.obtainMessage(what, arg1, arg2); 365 } 366 367 Message obtainMessageO(int what, Object arg1) { 368 return mH.obtainMessage(what, 0, 0, arg1); 369 } 370 371 Message obtainMessageISC(int what, int arg1, int seq, IInputContextCallback callback) { 372 SomeArgs args = new SomeArgs(); 373 args.callback = callback; 374 args.seq = seq; 375 return mH.obtainMessage(what, arg1, 0, args); 376 } 377 378 Message obtainMessageIISC(int what, int arg1, int arg2, int seq, IInputContextCallback callback) { 379 SomeArgs args = new SomeArgs(); 380 args.callback = callback; 381 args.seq = seq; 382 return mH.obtainMessage(what, arg1, arg2, args); 383 } 384 385 Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq, 386 IInputContextCallback callback) { 387 SomeArgs args = new SomeArgs(); 388 args.arg1 = arg2; 389 args.callback = callback; 390 args.seq = seq; 391 return mH.obtainMessage(what, arg1, 0, args); 392 } 393 394 Message obtainMessageIO(int what, int arg1, Object arg2) { 395 return mH.obtainMessage(what, arg1, 0, arg2); 396 } 397 398 Message obtainMessageOO(int what, Object arg1, Object arg2) { 399 SomeArgs args = new SomeArgs(); 400 args.arg1 = arg1; 401 args.arg2 = arg2; 402 return mH.obtainMessage(what, 0, 0, args); 403 } 404} 405