blob: 644c7e90f8b024a0ddf41d36ca28db926b7ce988 [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 Yukawa45700fa2016-06-23 17:12:59 -0700246 public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts,
Yohei Yukawa152944f2016-06-10 19:04:34 -0700247 int seq, IInputContextCallback callback) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700248 dispatchMessage(obtainMessageIOOSC(DO_COMMIT_CONTENT, flags, inputContentInfo, opts, seq,
249 callback));
Yohei Yukawa152944f2016-06-10 19:04:34 -0700250 }
251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 void dispatchMessage(Message msg) {
253 // If we are calling this from the main thread, then we can call
254 // right through. Otherwise, we need to send the message to the
255 // main thread.
256 if (Looper.myLooper() == mMainLooper) {
257 executeMessage(msg);
258 msg.recycle();
259 return;
260 }
261
262 mH.sendMessage(msg);
263 }
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 void executeMessage(Message msg) {
266 switch (msg.what) {
267 case DO_GET_TEXT_AFTER_CURSOR: {
268 SomeArgs args = (SomeArgs)msg.obj;
269 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700270 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 if (ic == null || !isActive()) {
272 Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
273 args.callback.setTextAfterCursor(null, args.seq);
274 return;
275 }
276 args.callback.setTextAfterCursor(ic.getTextAfterCursor(
277 msg.arg1, msg.arg2), args.seq);
278 } catch (RemoteException e) {
279 Log.w(TAG, "Got RemoteException calling setTextAfterCursor", e);
280 }
281 return;
282 }
283 case DO_GET_TEXT_BEFORE_CURSOR: {
284 SomeArgs args = (SomeArgs)msg.obj;
285 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700286 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 if (ic == null || !isActive()) {
288 Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
289 args.callback.setTextBeforeCursor(null, args.seq);
290 return;
291 }
292 args.callback.setTextBeforeCursor(ic.getTextBeforeCursor(
293 msg.arg1, msg.arg2), args.seq);
294 } catch (RemoteException e) {
295 Log.w(TAG, "Got RemoteException calling setTextBeforeCursor", e);
296 }
297 return;
298 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700299 case DO_GET_SELECTED_TEXT: {
300 SomeArgs args = (SomeArgs)msg.obj;
301 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700302 InputConnection ic = getInputConnection();
Amith Yamasania90b7f02010-08-25 18:27:20 -0700303 if (ic == null || !isActive()) {
304 Log.w(TAG, "getSelectedText on inactive InputConnection");
305 args.callback.setSelectedText(null, args.seq);
306 return;
307 }
308 args.callback.setSelectedText(ic.getSelectedText(
309 msg.arg1), args.seq);
310 } catch (RemoteException e) {
311 Log.w(TAG, "Got RemoteException calling setSelectedText", e);
312 }
313 return;
314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 case DO_GET_CURSOR_CAPS_MODE: {
316 SomeArgs args = (SomeArgs)msg.obj;
317 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700318 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 if (ic == null || !isActive()) {
320 Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
321 args.callback.setCursorCapsMode(0, args.seq);
322 return;
323 }
324 args.callback.setCursorCapsMode(ic.getCursorCapsMode(msg.arg1),
325 args.seq);
326 } catch (RemoteException e) {
327 Log.w(TAG, "Got RemoteException calling setCursorCapsMode", e);
328 }
329 return;
330 }
331 case DO_GET_EXTRACTED_TEXT: {
332 SomeArgs args = (SomeArgs)msg.obj;
333 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700334 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 if (ic == null || !isActive()) {
336 Log.w(TAG, "getExtractedText on inactive InputConnection");
337 args.callback.setExtractedText(null, args.seq);
338 return;
339 }
340 args.callback.setExtractedText(ic.getExtractedText(
341 (ExtractedTextRequest)args.arg1, msg.arg1), args.seq);
342 } catch (RemoteException e) {
343 Log.w(TAG, "Got RemoteException calling setExtractedText", e);
344 }
345 return;
346 }
347 case DO_COMMIT_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700348 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 if (ic == null || !isActive()) {
350 Log.w(TAG, "commitText on inactive InputConnection");
351 return;
352 }
353 ic.commitText((CharSequence)msg.obj, msg.arg1);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800354 onUserAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 return;
356 }
357 case DO_SET_SELECTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700358 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 if (ic == null || !isActive()) {
360 Log.w(TAG, "setSelection on inactive InputConnection");
361 return;
362 }
363 ic.setSelection(msg.arg1, msg.arg2);
364 return;
365 }
366 case DO_PERFORM_EDITOR_ACTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700367 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 if (ic == null || !isActive()) {
369 Log.w(TAG, "performEditorAction on inactive InputConnection");
370 return;
371 }
372 ic.performEditorAction(msg.arg1);
373 return;
374 }
375 case DO_PERFORM_CONTEXT_MENU_ACTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700376 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 if (ic == null || !isActive()) {
378 Log.w(TAG, "performContextMenuAction on inactive InputConnection");
379 return;
380 }
381 ic.performContextMenuAction(msg.arg1);
382 return;
383 }
384 case DO_COMMIT_COMPLETION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700385 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 if (ic == null || !isActive()) {
387 Log.w(TAG, "commitCompletion on inactive InputConnection");
388 return;
389 }
390 ic.commitCompletion((CompletionInfo)msg.obj);
391 return;
392 }
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800393 case DO_COMMIT_CORRECTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700394 InputConnection ic = getInputConnection();
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800395 if (ic == null || !isActive()) {
396 Log.w(TAG, "commitCorrection on inactive InputConnection");
397 return;
398 }
399 ic.commitCorrection((CorrectionInfo)msg.obj);
400 return;
401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 case DO_SET_COMPOSING_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700403 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 if (ic == null || !isActive()) {
405 Log.w(TAG, "setComposingText on inactive InputConnection");
406 return;
407 }
408 ic.setComposingText((CharSequence)msg.obj, msg.arg1);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800409 onUserAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 return;
411 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700412 case DO_SET_COMPOSING_REGION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700413 InputConnection ic = getInputConnection();
Amith Yamasania90b7f02010-08-25 18:27:20 -0700414 if (ic == null || !isActive()) {
415 Log.w(TAG, "setComposingRegion on inactive InputConnection");
416 return;
417 }
418 ic.setComposingRegion(msg.arg1, msg.arg2);
419 return;
420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 case DO_FINISH_COMPOSING_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700422 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 // Note we do NOT check isActive() here, because this is safe
424 // for an IME to call at any time, and we need to allow it
425 // through to clean up our state after the IME has switched to
426 // another client.
427 if (ic == null) {
428 Log.w(TAG, "finishComposingText on inactive InputConnection");
429 return;
430 }
431 ic.finishComposingText();
432 return;
433 }
434 case DO_SEND_KEY_EVENT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700435 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 if (ic == null || !isActive()) {
437 Log.w(TAG, "sendKeyEvent on inactive InputConnection");
438 return;
439 }
440 ic.sendKeyEvent((KeyEvent)msg.obj);
Yohei Yukawa159dd472016-01-07 16:52:33 -0800441 onUserAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 return;
443 }
444 case DO_CLEAR_META_KEY_STATES: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700445 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 if (ic == null || !isActive()) {
447 Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
448 return;
449 }
450 ic.clearMetaKeyStates(msg.arg1);
451 return;
452 }
453 case DO_DELETE_SURROUNDING_TEXT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700454 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 if (ic == null || !isActive()) {
456 Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
457 return;
458 }
459 ic.deleteSurroundingText(msg.arg1, msg.arg2);
460 return;
461 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800462 case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700463 InputConnection ic = getInputConnection();
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800464 if (ic == null || !isActive()) {
465 Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
466 return;
467 }
468 ic.deleteSurroundingTextInCodePoints(msg.arg1, msg.arg2);
469 return;
470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 case DO_BEGIN_BATCH_EDIT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700472 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 if (ic == null || !isActive()) {
474 Log.w(TAG, "beginBatchEdit on inactive InputConnection");
475 return;
476 }
477 ic.beginBatchEdit();
478 return;
479 }
480 case DO_END_BATCH_EDIT: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700481 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 if (ic == null || !isActive()) {
483 Log.w(TAG, "endBatchEdit on inactive InputConnection");
484 return;
485 }
486 ic.endBatchEdit();
487 return;
488 }
489 case DO_REPORT_FULLSCREEN_MODE: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700490 InputConnection ic = getInputConnection();
Yohei Yukawa1544def2016-04-26 17:13:38 -0700491 boolean isBackground = false;
492 if (ic == null || !isActive()) {
Andrei Stingaceanuda589df2015-06-17 10:38:08 +0100493 Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
Yohei Yukawa1544def2016-04-26 17:13:38 -0700494 isBackground = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800496 final boolean enabled = msg.arg1 == 1;
Yohei Yukawa1544def2016-04-26 17:13:38 -0700497 if (!isBackground) {
498 ic.reportFullscreenMode(enabled);
499 }
500 // Due to the nature of asynchronous event handling, currently InputMethodService
501 // has relied on the fact that #reportFullscreenMode() can be handled even when the
502 // InputConnection is inactive. We have to notify this event to InputMethodManager.
503 onReportFullscreenMode(enabled, isBackground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 return;
505 }
506 case DO_PERFORM_PRIVATE_COMMAND: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700507 InputConnection ic = getInputConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 if (ic == null || !isActive()) {
509 Log.w(TAG, "performPrivateCommand on inactive InputConnection");
510 return;
511 }
512 SomeArgs args = (SomeArgs)msg.obj;
513 ic.performPrivateCommand((String)args.arg1,
514 (Bundle)args.arg2);
515 return;
516 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700517 case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900518 SomeArgs args = (SomeArgs)msg.obj;
519 try {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700520 InputConnection ic = getInputConnection();
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900521 if (ic == null || !isActive()) {
522 Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
Yohei Yukawaa277db22014-08-21 18:38:44 -0700523 args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900524 return;
525 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700526 args.callback.setRequestUpdateCursorAnchorInfoResult(
Yohei Yukawad8636ea2014-09-02 22:03:30 -0700527 ic.requestCursorUpdates(msg.arg1), args.seq);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900528 } catch (RemoteException e) {
529 Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
530 }
531 return;
532 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700533 case DO_CLOSE_CONNECTION: {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700534 // Note that we do not need to worry about race condition here, because 1) mFinished
535 // is updated only inside this block, and 2) the code here is running on a Handler
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700536 // hence we assume multiple DO_CLOSE_CONNECTION messages will not be handled at the
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700537 // same time.
538 if (isFinished()) {
539 return;
540 }
541 try {
542 InputConnection ic = getInputConnection();
543 // Note we do NOT check isActive() here, because this is safe
544 // for an IME to call at any time, and we need to allow it
545 // through to clean up our state after the IME has switched to
546 // another client.
547 if (ic == null) {
548 return;
549 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700550 @MissingMethodFlags
551 final int missingMethods = InputConnectionInspector.getMissingMethodFlags(ic);
552 if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) {
553 ic.closeConnection();
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700554 }
555 } finally {
556 synchronized (mLock) {
557 mInputConnection = null;
558 mFinished = true;
559 }
560 }
561 return;
562 }
Yohei Yukawaadebb522016-06-17 10:10:39 -0700563 case DO_COMMIT_CONTENT: {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700564 final int flags = msg.arg1;
Yohei Yukawaf3806f52016-06-30 16:27:46 -0700565 final boolean grantUriPermission =
566 (flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700567 SomeArgs args = (SomeArgs) msg.obj;
568 try {
569 InputConnection ic = getInputConnection();
570 if (ic == null || !isActive()) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700571 Log.w(TAG, "commitContent on inactive InputConnection");
572 args.callback.setCommitContentResult(false, args.seq);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700573 return;
574 }
575 final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
576 if (inputContentInfo == null || !inputContentInfo.validate()) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700577 Log.w(TAG, "commitContent with invalid inputContentInfo="
Yohei Yukawa152944f2016-06-10 19:04:34 -0700578 + inputContentInfo);
Yohei Yukawaadebb522016-06-17 10:10:39 -0700579 args.callback.setCommitContentResult(false, args.seq);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700580 return;
581 }
Yohei Yukawaf3806f52016-06-30 16:27:46 -0700582 if (grantUriPermission) {
583 inputContentInfo.requestPermission();
584 }
585 final boolean result =
586 ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
587 // If this request is not handled, then there is no reason to keep the URI
588 // permission.
589 if (grantUriPermission && !result) {
590 inputContentInfo.releasePermission();
591 }
592 args.callback.setCommitContentResult(result, args.seq);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700593 } catch (RemoteException e) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700594 Log.w(TAG, "Got RemoteException calling commitContent", e);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700595 }
596 return;
597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 }
599 Log.w(TAG, "Unhandled message code: " + msg.what);
600 }
601
602 Message obtainMessage(int what) {
603 return mH.obtainMessage(what);
604 }
605
606 Message obtainMessageII(int what, int arg1, int arg2) {
607 return mH.obtainMessage(what, arg1, arg2);
608 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 Message obtainMessageO(int what, Object arg1) {
611 return mH.obtainMessage(what, 0, 0, arg1);
612 }
613
614 Message obtainMessageISC(int what, int arg1, int seq, IInputContextCallback callback) {
615 SomeArgs args = new SomeArgs();
616 args.callback = callback;
617 args.seq = seq;
618 return mH.obtainMessage(what, arg1, 0, args);
619 }
620
621 Message obtainMessageIISC(int what, int arg1, int arg2, int seq, IInputContextCallback callback) {
622 SomeArgs args = new SomeArgs();
623 args.callback = callback;
624 args.seq = seq;
625 return mH.obtainMessage(what, arg1, arg2, args);
626 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900627
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700628 Message obtainMessageIOOSC(int what, int arg1, Object objArg1, Object objArg2, int seq,
Yohei Yukawa152944f2016-06-10 19:04:34 -0700629 IInputContextCallback callback) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900630 SomeArgs args = new SomeArgs();
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700631 args.arg1 = objArg1;
632 args.arg2 = objArg2;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900633 args.callback = callback;
634 args.seq = seq;
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700635 return mH.obtainMessage(what, arg1, 0, args);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900636 }
637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq,
639 IInputContextCallback callback) {
640 SomeArgs args = new SomeArgs();
641 args.arg1 = arg2;
642 args.callback = callback;
643 args.seq = seq;
644 return mH.obtainMessage(what, arg1, 0, args);
645 }
646
647 Message obtainMessageIO(int what, int arg1, Object arg2) {
648 return mH.obtainMessage(what, arg1, 0, arg2);
649 }
650
651 Message obtainMessageOO(int what, Object arg1, Object arg2) {
652 SomeArgs args = new SomeArgs();
653 args.arg1 = arg1;
654 args.arg2 = arg2;
655 return mH.obtainMessage(what, 0, 0, args);
656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657}