blob: dce9d2cc55808ab7d950e2187643f272af5cd3b8 [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2008 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package com.android.internal.view;
18
Yohei Yukawaaaa38c92016-03-27 23:46:04 -070019import com.android.internal.annotations.GuardedBy;
20
21import android.annotation.NonNull;
22import android.annotation.Nullable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.os.Bundle;
24import android.os.Handler;
25import android.os.Looper;
26import android.os.Message;
27import android.os.RemoteException;
28import android.util.Log;
29import android.view.KeyEvent;
30import android.view.inputmethod.CompletionInfo;
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -080031import android.view.inputmethod.CorrectionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.view.inputmethod.ExtractedTextRequest;
33import android.view.inputmethod.InputConnection;
Yohei Yukawa9f9afe522016-03-30 12:03:51 -070034import android.view.inputmethod.InputConnectionInspector;
35import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
Yohei Yukawa152944f2016-06-10 19:04:34 -070036import android.view.inputmethod.InputContentInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Yohei Yukawa159dd472016-01-07 16:52:33 -080038public abstract class IInputConnectionWrapper extends IInputContext.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 static final String TAG = "IInputConnectionWrapper";
Amith Yamasania90b7f02010-08-25 18:27:20 -070040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 private static final int DO_GET_TEXT_AFTER_CURSOR = 10;
42 private static final int DO_GET_TEXT_BEFORE_CURSOR = 20;
Amith Yamasania90b7f02010-08-25 18:27:20 -070043 private static final int DO_GET_SELECTED_TEXT = 25;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 private static final int DO_GET_CURSOR_CAPS_MODE = 30;
45 private static final int DO_GET_EXTRACTED_TEXT = 40;
46 private static final int DO_COMMIT_TEXT = 50;
47 private static final int DO_COMMIT_COMPLETION = 55;
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -080048 private static final int DO_COMMIT_CORRECTION = 56;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 private static final int DO_SET_SELECTION = 57;
50 private static final int DO_PERFORM_EDITOR_ACTION = 58;
51 private static final int DO_PERFORM_CONTEXT_MENU_ACTION = 59;
52 private static final int DO_SET_COMPOSING_TEXT = 60;
Amith Yamasania90b7f02010-08-25 18:27:20 -070053 private static final int DO_SET_COMPOSING_REGION = 63;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 private static final int DO_FINISH_COMPOSING_TEXT = 65;
55 private static final int DO_SEND_KEY_EVENT = 70;
56 private static final int DO_DELETE_SURROUNDING_TEXT = 80;
Yohei Yukawac89e22a2016-01-13 22:48:14 -080057 private static final int DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS = 81;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 private static final int DO_BEGIN_BATCH_EDIT = 90;
59 private static final int DO_END_BATCH_EDIT = 95;
60 private static final int DO_REPORT_FULLSCREEN_MODE = 100;
61 private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
62 private static final int DO_CLEAR_META_KEY_STATES = 130;
Yohei Yukawaa277db22014-08-21 18:38:44 -070063 private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
Yohei Yukawa9f9afe522016-03-30 12:03:51 -070064 private static final int DO_CLOSE_CONNECTION = 150;
Yohei Yukawaadebb522016-06-17 10:10:39 -070065 private static final int DO_COMMIT_CONTENT = 160;
Amith Yamasania90b7f02010-08-25 18:27:20 -070066
Yohei Yukawaaaa38c92016-03-27 23:46:04 -070067 @GuardedBy("mLock")
68 @Nullable
69 private InputConnection mInputConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070
71 private Looper mMainLooper;
72 private Handler mH;
Yohei Yukawaaaa38c92016-03-27 23:46:04 -070073 private Object mLock = new Object();
74 @GuardedBy("mLock")
75 private boolean mFinished = false;
Yohei Yukawa1544def2016-04-26 17:13:38 -070076 @GuardedBy("mLock")
77 private String mInputMethodId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078
79 static class SomeArgs {
80 Object arg1;
81 Object arg2;
82 IInputContextCallback callback;
83 int seq;
84 }
85
86 class MyHandler extends Handler {
87 MyHandler(Looper looper) {
88 super(looper);
89 }
90
91 @Override
92 public void handleMessage(Message msg) {
93 executeMessage(msg);
94 }
95 }
96
Yohei Yukawaaaa38c92016-03-27 23:46:04 -070097 public IInputConnectionWrapper(Looper mainLooper, @NonNull InputConnection inputConnection) {
98 mInputConnection = inputConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 mMainLooper = mainLooper;
100 mH = new MyHandler(mMainLooper);
101 }
102
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700103 @Nullable
104 public InputConnection getInputConnection() {
105 synchronized (mLock) {
106 return mInputConnection;
107 }
108 }
109
110 protected boolean isFinished() {
111 synchronized (mLock) {
112 return mFinished;
113 }
114 }
115
Yohei Yukawa1544def2016-04-26 17:13:38 -0700116 public String getInputMethodId() {
117 synchronized (mLock) {
118 return mInputMethodId;
119 }
120 }
121
122 public void setInputMethodId(final String inputMethodId) {
123 synchronized (mLock) {
124 mInputMethodId = inputMethodId;
125 }
126 }
127
Yohei Yukawa159dd472016-01-07 16:52:33 -0800128 abstract protected boolean isActive();
129
130 /**
131 * Called when the user took some actions that should be taken into consideration to update the
132 * LRU list for input method rotation.
133 */
134 abstract protected void onUserAction();
135
136 /**
137 * Called when the input method started or stopped full-screen mode.
Yohei Yukawa1544def2016-04-26 17:13:38 -0700138 * @param enabled {@code true} if the input method starts full-screen mode.
139 * @param calledInBackground {@code true} if this input connection is in a state when incoming
140 * events are usually ignored.
Yohei Yukawa159dd472016-01-07 16:52:33 -0800141 */
Yohei Yukawa1544def2016-04-26 17:13:38 -0700142 abstract protected void onReportFullscreenMode(boolean enabled, boolean calledInBackground);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) {
145 dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback));
146 }
147
148 public void getTextBeforeCursor(int length, int flags, int seq, IInputContextCallback callback) {
149 dispatchMessage(obtainMessageIISC(DO_GET_TEXT_BEFORE_CURSOR, length, flags, seq, callback));
150 }
151
Amith Yamasania90b7f02010-08-25 18:27:20 -0700152 public void getSelectedText(int flags, int seq, IInputContextCallback callback) {
153 dispatchMessage(obtainMessageISC(DO_GET_SELECTED_TEXT, flags, seq, callback));
154 }
155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 public void getCursorCapsMode(int reqModes, int seq, IInputContextCallback callback) {
157 dispatchMessage(obtainMessageISC(DO_GET_CURSOR_CAPS_MODE, reqModes, seq, callback));
158 }
159
160 public void getExtractedText(ExtractedTextRequest request,
161 int flags, int seq, IInputContextCallback callback) {
162 dispatchMessage(obtainMessageIOSC(DO_GET_EXTRACTED_TEXT, flags,
163 request, seq, callback));
164 }
165
166 public void commitText(CharSequence text, int newCursorPosition) {
167 dispatchMessage(obtainMessageIO(DO_COMMIT_TEXT, newCursorPosition, text));
168 }
169
170 public void commitCompletion(CompletionInfo text) {
171 dispatchMessage(obtainMessageO(DO_COMMIT_COMPLETION, text));
172 }
173
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800174 public void commitCorrection(CorrectionInfo info) {
175 dispatchMessage(obtainMessageO(DO_COMMIT_CORRECTION, info));
176 }
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 public void setSelection(int start, int end) {
179 dispatchMessage(obtainMessageII(DO_SET_SELECTION, start, end));
180 }
181
182 public void performEditorAction(int id) {
183 dispatchMessage(obtainMessageII(DO_PERFORM_EDITOR_ACTION, id, 0));
184 }
185
186 public void performContextMenuAction(int id) {
187 dispatchMessage(obtainMessageII(DO_PERFORM_CONTEXT_MENU_ACTION, id, 0));
188 }
189
Amith Yamasania90b7f02010-08-25 18:27:20 -0700190 public void setComposingRegion(int start, int end) {
191 dispatchMessage(obtainMessageII(DO_SET_COMPOSING_REGION, start, end));
192 }
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 public void setComposingText(CharSequence text, int newCursorPosition) {
195 dispatchMessage(obtainMessageIO(DO_SET_COMPOSING_TEXT, newCursorPosition, text));
196 }
197
198 public void finishComposingText() {
199 dispatchMessage(obtainMessage(DO_FINISH_COMPOSING_TEXT));
200 }
201
202 public void sendKeyEvent(KeyEvent event) {
203 dispatchMessage(obtainMessageO(DO_SEND_KEY_EVENT, event));
204 }
205
206 public void clearMetaKeyStates(int states) {
207 dispatchMessage(obtainMessageII(DO_CLEAR_META_KEY_STATES, states, 0));
208 }
209
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800210 public void deleteSurroundingText(int beforeLength, int afterLength) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 dispatchMessage(obtainMessageII(DO_DELETE_SURROUNDING_TEXT,
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800212 beforeLength, afterLength));
213 }
214
215 public void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
216 dispatchMessage(obtainMessageII(DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS,
217 beforeLength, afterLength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 }
219
220 public void beginBatchEdit() {
221 dispatchMessage(obtainMessage(DO_BEGIN_BATCH_EDIT));
222 }
223
224 public void endBatchEdit() {
225 dispatchMessage(obtainMessage(DO_END_BATCH_EDIT));
226 }
227
228 public void reportFullscreenMode(boolean enabled) {
229 dispatchMessage(obtainMessageII(DO_REPORT_FULLSCREEN_MODE, enabled ? 1 : 0, 0));
230 }
231
232 public void performPrivateCommand(String action, Bundle data) {
233 dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
234 }
satokadb43582011-03-09 10:08:47 +0900235
Yohei Yukawaa277db22014-08-21 18:38:44 -0700236 public void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900237 IInputContextCallback callback) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700238 dispatchMessage(obtainMessageISC(DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO, cursorUpdateMode,
239 seq, callback));
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900240 }
241
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700242 public void closeConnection() {
243 dispatchMessage(obtainMessage(DO_CLOSE_CONNECTION));
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700244 }
245
Yohei Yukawaadebb522016-06-17 10:10:39 -0700246 public void commitContent(InputContentInfo inputContentInfo, Bundle opts,
Yohei Yukawa152944f2016-06-10 19:04:34 -0700247 int seq, IInputContextCallback callback) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700248 dispatchMessage(obtainMessageOOSC(DO_COMMIT_CONTENT, inputContentInfo, opts, seq, callback));
Yohei Yukawa152944f2016-06-10 19:04:34 -0700249 }
250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 void dispatchMessage(Message msg) {
252 // If we are calling this from the main thread, then we can call
253 // right through. Otherwise, we need to send the message to the
254 // main thread.
255 if (Looper.myLooper() == mMainLooper) {
256 executeMessage(msg);
257 msg.recycle();
258 return;
259 }
260
261 mH.sendMessage(msg);
262 }
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 void executeMessage(Message msg) {
265 switch (msg.what) {
266 case DO_GET_TEXT_AFTER_CURSOR: {
267 SomeArgs args = (SomeArgs)msg.obj;
268 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700269 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 if (ic == null || !isActive()) {
271 Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
272 args.callback.setTextAfterCursor(null, args.seq);
273 return;
274 }
275 args.callback.setTextAfterCursor(ic.getTextAfterCursor(
276 msg.arg1, msg.arg2), args.seq);
277 } catch (RemoteException e) {
278 Log.w(TAG, "Got RemoteException calling setTextAfterCursor", e);
279 }
280 return;
281 }
282 case DO_GET_TEXT_BEFORE_CURSOR: {
283 SomeArgs args = (SomeArgs)msg.obj;
284 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700285 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 if (ic == null || !isActive()) {
287 Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
288 args.callback.setTextBeforeCursor(null, args.seq);
289 return;
290 }
291 args.callback.setTextBeforeCursor(ic.getTextBeforeCursor(
292 msg.arg1, msg.arg2), args.seq);
293 } catch (RemoteException e) {
294 Log.w(TAG, "Got RemoteException calling setTextBeforeCursor", e);
295 }
296 return;
297 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700298 case DO_GET_SELECTED_TEXT: {
299 SomeArgs args = (SomeArgs)msg.obj;
300 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700301 InputConnection ic = getInputConnection();
Amith Yamasania90b7f02010-08-25 18:27:20 -0700302 if (ic == null || !isActive()) {
303 Log.w(TAG, "getSelectedText on inactive InputConnection");
304 args.callback.setSelectedText(null, args.seq);
305 return;
306 }
307 args.callback.setSelectedText(ic.getSelectedText(
308 msg.arg1), args.seq);
309 } catch (RemoteException e) {
310 Log.w(TAG, "Got RemoteException calling setSelectedText", e);
311 }
312 return;
313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 case DO_GET_CURSOR_CAPS_MODE: {
315 SomeArgs args = (SomeArgs)msg.obj;
316 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700317 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 if (ic == null || !isActive()) {
319 Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
320 args.callback.setCursorCapsMode(0, args.seq);
321 return;
322 }
323 args.callback.setCursorCapsMode(ic.getCursorCapsMode(msg.arg1),
324 args.seq);
325 } catch (RemoteException e) {
326 Log.w(TAG, "Got RemoteException calling setCursorCapsMode", e);
327 }
328 return;
329 }
330 case DO_GET_EXTRACTED_TEXT: {
331 SomeArgs args = (SomeArgs)msg.obj;
332 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700333 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 if (ic == null || !isActive()) {
335 Log.w(TAG, "getExtractedText on inactive InputConnection");
336 args.callback.setExtractedText(null, args.seq);
337 return;
338 }
339 args.callback.setExtractedText(ic.getExtractedText(
340 (ExtractedTextRequest)args.arg1, msg.arg1), args.seq);
341 } catch (RemoteException e) {
342 Log.w(TAG, "Got RemoteException calling setExtractedText", e);
343 }
344 return;
345 }
346 case DO_COMMIT_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700347 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 if (ic == null || !isActive()) {
349 Log.w(TAG, "commitText on inactive InputConnection");
350 return;
351 }
352 ic.commitText((CharSequence)msg.obj, msg.arg1);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800353 onUserAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 return;
355 }
356 case DO_SET_SELECTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700357 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 if (ic == null || !isActive()) {
359 Log.w(TAG, "setSelection on inactive InputConnection");
360 return;
361 }
362 ic.setSelection(msg.arg1, msg.arg2);
363 return;
364 }
365 case DO_PERFORM_EDITOR_ACTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700366 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 if (ic == null || !isActive()) {
368 Log.w(TAG, "performEditorAction on inactive InputConnection");
369 return;
370 }
371 ic.performEditorAction(msg.arg1);
372 return;
373 }
374 case DO_PERFORM_CONTEXT_MENU_ACTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700375 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 if (ic == null || !isActive()) {
377 Log.w(TAG, "performContextMenuAction on inactive InputConnection");
378 return;
379 }
380 ic.performContextMenuAction(msg.arg1);
381 return;
382 }
383 case DO_COMMIT_COMPLETION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700384 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 if (ic == null || !isActive()) {
386 Log.w(TAG, "commitCompletion on inactive InputConnection");
387 return;
388 }
389 ic.commitCompletion((CompletionInfo)msg.obj);
390 return;
391 }
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800392 case DO_COMMIT_CORRECTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700393 InputConnection ic = getInputConnection();
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800394 if (ic == null || !isActive()) {
395 Log.w(TAG, "commitCorrection on inactive InputConnection");
396 return;
397 }
398 ic.commitCorrection((CorrectionInfo)msg.obj);
399 return;
400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 case DO_SET_COMPOSING_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700402 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 if (ic == null || !isActive()) {
404 Log.w(TAG, "setComposingText on inactive InputConnection");
405 return;
406 }
407 ic.setComposingText((CharSequence)msg.obj, msg.arg1);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800408 onUserAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 return;
410 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700411 case DO_SET_COMPOSING_REGION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700412 InputConnection ic = getInputConnection();
Amith Yamasania90b7f02010-08-25 18:27:20 -0700413 if (ic == null || !isActive()) {
414 Log.w(TAG, "setComposingRegion on inactive InputConnection");
415 return;
416 }
417 ic.setComposingRegion(msg.arg1, msg.arg2);
418 return;
419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 case DO_FINISH_COMPOSING_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700421 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 // Note we do NOT check isActive() here, because this is safe
423 // for an IME to call at any time, and we need to allow it
424 // through to clean up our state after the IME has switched to
425 // another client.
426 if (ic == null) {
427 Log.w(TAG, "finishComposingText on inactive InputConnection");
428 return;
429 }
430 ic.finishComposingText();
431 return;
432 }
433 case DO_SEND_KEY_EVENT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700434 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 if (ic == null || !isActive()) {
436 Log.w(TAG, "sendKeyEvent on inactive InputConnection");
437 return;
438 }
439 ic.sendKeyEvent((KeyEvent)msg.obj);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800440 onUserAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 return;
442 }
443 case DO_CLEAR_META_KEY_STATES: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700444 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 if (ic == null || !isActive()) {
446 Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
447 return;
448 }
449 ic.clearMetaKeyStates(msg.arg1);
450 return;
451 }
452 case DO_DELETE_SURROUNDING_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700453 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 if (ic == null || !isActive()) {
455 Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
456 return;
457 }
458 ic.deleteSurroundingText(msg.arg1, msg.arg2);
459 return;
460 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800461 case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700462 InputConnection ic = getInputConnection();
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800463 if (ic == null || !isActive()) {
464 Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
465 return;
466 }
467 ic.deleteSurroundingTextInCodePoints(msg.arg1, msg.arg2);
468 return;
469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 case DO_BEGIN_BATCH_EDIT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700471 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 if (ic == null || !isActive()) {
473 Log.w(TAG, "beginBatchEdit on inactive InputConnection");
474 return;
475 }
476 ic.beginBatchEdit();
477 return;
478 }
479 case DO_END_BATCH_EDIT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700480 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 if (ic == null || !isActive()) {
482 Log.w(TAG, "endBatchEdit on inactive InputConnection");
483 return;
484 }
485 ic.endBatchEdit();
486 return;
487 }
488 case DO_REPORT_FULLSCREEN_MODE: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700489 InputConnection ic = getInputConnection();
Yohei Yukawa1544def2016-04-26 17:13:38 -0700490 boolean isBackground = false;
491 if (ic == null || !isActive()) {
Andrei Stingaceanuda589df2015-06-17 10:38:08 +0100492 Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
Yohei Yukawa1544def2016-04-26 17:13:38 -0700493 isBackground = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800495 final boolean enabled = msg.arg1 == 1;
Yohei Yukawa1544def2016-04-26 17:13:38 -0700496 if (!isBackground) {
497 ic.reportFullscreenMode(enabled);
498 }
499 // Due to the nature of asynchronous event handling, currently InputMethodService
500 // has relied on the fact that #reportFullscreenMode() can be handled even when the
501 // InputConnection is inactive. We have to notify this event to InputMethodManager.
502 onReportFullscreenMode(enabled, isBackground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 return;
504 }
505 case DO_PERFORM_PRIVATE_COMMAND: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700506 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 if (ic == null || !isActive()) {
508 Log.w(TAG, "performPrivateCommand on inactive InputConnection");
509 return;
510 }
511 SomeArgs args = (SomeArgs)msg.obj;
512 ic.performPrivateCommand((String)args.arg1,
513 (Bundle)args.arg2);
514 return;
515 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700516 case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900517 SomeArgs args = (SomeArgs)msg.obj;
518 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700519 InputConnection ic = getInputConnection();
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900520 if (ic == null || !isActive()) {
521 Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
Yohei Yukawaa277db22014-08-21 18:38:44 -0700522 args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900523 return;
524 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700525 args.callback.setRequestUpdateCursorAnchorInfoResult(
Yohei Yukawad8636ea2014-09-02 22:03:30 -0700526 ic.requestCursorUpdates(msg.arg1), args.seq);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900527 } catch (RemoteException e) {
528 Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
529 }
530 return;
531 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700532 case DO_CLOSE_CONNECTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700533 // Note that we do not need to worry about race condition here, because 1) mFinished
534 // is updated only inside this block, and 2) the code here is running on a Handler
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700535 // hence we assume multiple DO_CLOSE_CONNECTION messages will not be handled at the
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700536 // same time.
537 if (isFinished()) {
538 return;
539 }
540 try {
541 InputConnection ic = getInputConnection();
542 // Note we do NOT check isActive() here, because this is safe
543 // for an IME to call at any time, and we need to allow it
544 // through to clean up our state after the IME has switched to
545 // another client.
546 if (ic == null) {
547 return;
548 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700549 @MissingMethodFlags
550 final int missingMethods = InputConnectionInspector.getMissingMethodFlags(ic);
551 if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) {
552 ic.closeConnection();
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700553 }
554 } finally {
555 synchronized (mLock) {
556 mInputConnection = null;
557 mFinished = true;
558 }
559 }
560 return;
561 }
Yohei Yukawaadebb522016-06-17 10:10:39 -0700562 case DO_COMMIT_CONTENT: {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700563 SomeArgs args = (SomeArgs) msg.obj;
564 try {
565 InputConnection ic = getInputConnection();
566 if (ic == null || !isActive()) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700567 Log.w(TAG, "commitContent on inactive InputConnection");
568 args.callback.setCommitContentResult(false, args.seq);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700569 return;
570 }
571 final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
572 if (inputContentInfo == null || !inputContentInfo.validate()) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700573 Log.w(TAG, "commitContent with invalid inputContentInfo="
Yohei Yukawa152944f2016-06-10 19:04:34 -0700574 + inputContentInfo);
Yohei Yukawaadebb522016-06-17 10:10:39 -0700575 args.callback.setCommitContentResult(false, args.seq);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700576 return;
577 }
Yohei Yukawaadebb522016-06-17 10:10:39 -0700578 args.callback.setCommitContentResult(
579 ic.commitContent(inputContentInfo, (Bundle) args.arg2), args.seq);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700580 } catch (RemoteException e) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700581 Log.w(TAG, "Got RemoteException calling commitContent", e);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700582 }
583 return;
584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 }
586 Log.w(TAG, "Unhandled message code: " + msg.what);
587 }
588
589 Message obtainMessage(int what) {
590 return mH.obtainMessage(what);
591 }
592
593 Message obtainMessageII(int what, int arg1, int arg2) {
594 return mH.obtainMessage(what, arg1, arg2);
595 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 Message obtainMessageO(int what, Object arg1) {
598 return mH.obtainMessage(what, 0, 0, arg1);
599 }
600
601 Message obtainMessageISC(int what, int arg1, int seq, IInputContextCallback callback) {
602 SomeArgs args = new SomeArgs();
603 args.callback = callback;
604 args.seq = seq;
605 return mH.obtainMessage(what, arg1, 0, args);
606 }
607
608 Message obtainMessageIISC(int what, int arg1, int arg2, int seq, IInputContextCallback callback) {
609 SomeArgs args = new SomeArgs();
610 args.callback = callback;
611 args.seq = seq;
612 return mH.obtainMessage(what, arg1, arg2, args);
613 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900614
Yohei Yukawa152944f2016-06-10 19:04:34 -0700615 Message obtainMessageOOSC(int what, Object arg1, Object arg2, int seq,
616 IInputContextCallback callback) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900617 SomeArgs args = new SomeArgs();
618 args.arg1 = arg1;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700619 args.arg2 = arg2;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900620 args.callback = callback;
621 args.seq = seq;
622 return mH.obtainMessage(what, 0, 0, args);
623 }
624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq,
626 IInputContextCallback callback) {
627 SomeArgs args = new SomeArgs();
628 args.arg1 = arg2;
629 args.callback = callback;
630 args.seq = seq;
631 return mH.obtainMessage(what, arg1, 0, args);
632 }
633
634 Message obtainMessageIO(int what, int arg1, Object arg2) {
635 return mH.obtainMessage(what, arg1, 0, arg2);
636 }
637
638 Message obtainMessageOO(int what, Object arg1, Object arg2) {
639 SomeArgs args = new SomeArgs();
640 args.arg1 = arg1;
641 args.arg2 = arg2;
642 return mH.obtainMessage(what, 0, 0, args);
643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644}