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