blob: 2098ebd8814a1f2b552884f393b5ca8e2395c0bd [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 Yukawa930328c2017-10-18 20:19:53 -070019import android.annotation.AnyThread;
20import android.annotation.BinderThread;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070021import android.annotation.NonNull;
22import android.inputmethodservice.AbstractInputMethodService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.os.Bundle;
Yohei Yukawa612cce92016-02-11 17:47:33 -080024import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.RemoteException;
26import android.os.SystemClock;
27import android.util.Log;
28import android.view.KeyEvent;
29import android.view.inputmethod.CompletionInfo;
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -080030import android.view.inputmethod.CorrectionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.view.inputmethod.ExtractedText;
32import android.view.inputmethod.ExtractedTextRequest;
33import android.view.inputmethod.InputConnection;
Yohei Yukawa19a80a12016-03-14 22:57:37 -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 Yukawa45700fa2016-06-23 17:12:59 -070038import java.lang.ref.WeakReference;
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040public class InputConnectionWrapper implements InputConnection {
41 private static final int MAX_WAIT_TIME_MILLIS = 2000;
42 private final IInputContext mIInputContext;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070043 @NonNull
44 private final WeakReference<AbstractInputMethodService> mInputMethodService;
45
Yohei Yukawa19a80a12016-03-14 22:57:37 -070046 @MissingMethodFlags
47 private final int mMissingMethods;
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 static class InputContextCallback extends IInputContextCallback.Stub {
50 private static final String TAG = "InputConnectionWrapper.ICC";
51 public int mSeq;
52 public boolean mHaveValue;
53 public CharSequence mTextBeforeCursor;
54 public CharSequence mTextAfterCursor;
Amith Yamasania90b7f02010-08-25 18:27:20 -070055 public CharSequence mSelectedText;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 public ExtractedText mExtractedText;
57 public int mCursorCapsMode;
Yohei Yukawaa277db22014-08-21 18:38:44 -070058 public boolean mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawaadebb522016-06-17 10:10:39 -070059 public boolean mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -070060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 // A 'pool' of one InputContextCallback. Each ICW request will attempt to gain
62 // exclusive access to this object.
63 private static InputContextCallback sInstance = new InputContextCallback();
64 private static int sSequenceNumber = 1;
65
66 /**
67 * Returns an InputContextCallback object that is guaranteed not to be in use by
68 * any other thread. The returned object's 'have value' flag is cleared and its expected
69 * sequence number is set to a new integer. We use a sequence number so that replies that
70 * occur after a timeout has expired are not interpreted as replies to a later request.
71 */
Yohei Yukawa930328c2017-10-18 20:19:53 -070072 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 private static InputContextCallback getInstance() {
74 synchronized (InputContextCallback.class) {
75 // Return sInstance if it's non-null, otherwise construct a new callback
76 InputContextCallback callback;
77 if (sInstance != null) {
78 callback = sInstance;
79 sInstance = null;
80
81 // Reset the callback
82 callback.mHaveValue = false;
83 } else {
84 callback = new InputContextCallback();
85 }
86
87 // Set the sequence number
88 callback.mSeq = sSequenceNumber++;
89 return callback;
90 }
91 }
92
93 /**
94 * Makes the given InputContextCallback available for use in the future.
95 */
Yohei Yukawa930328c2017-10-18 20:19:53 -070096 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private void dispose() {
98 synchronized (InputContextCallback.class) {
99 // If sInstance is non-null, just let this object be garbage-collected
100 if (sInstance == null) {
101 // Allow any objects being held to be gc'ed
102 mTextAfterCursor = null;
103 mTextBeforeCursor = null;
104 mExtractedText = null;
105 sInstance = this;
106 }
107 }
108 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700109
110 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 public void setTextBeforeCursor(CharSequence textBeforeCursor, int seq) {
112 synchronized (this) {
113 if (seq == mSeq) {
114 mTextBeforeCursor = textBeforeCursor;
115 mHaveValue = true;
116 notifyAll();
117 } else {
118 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
119 + ") in setTextBeforeCursor, ignoring.");
120 }
121 }
122 }
123
Yohei Yukawa930328c2017-10-18 20:19:53 -0700124 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 public void setTextAfterCursor(CharSequence textAfterCursor, int seq) {
126 synchronized (this) {
127 if (seq == mSeq) {
128 mTextAfterCursor = textAfterCursor;
129 mHaveValue = true;
130 notifyAll();
131 } else {
132 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
133 + ") in setTextAfterCursor, ignoring.");
134 }
135 }
136 }
137
Yohei Yukawa930328c2017-10-18 20:19:53 -0700138 @BinderThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700139 public void setSelectedText(CharSequence selectedText, int seq) {
140 synchronized (this) {
141 if (seq == mSeq) {
142 mSelectedText = selectedText;
143 mHaveValue = true;
144 notifyAll();
145 } else {
146 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
147 + ") in setSelectedText, ignoring.");
148 }
149 }
150 }
151
Yohei Yukawa930328c2017-10-18 20:19:53 -0700152 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 public void setCursorCapsMode(int capsMode, int seq) {
154 synchronized (this) {
155 if (seq == mSeq) {
156 mCursorCapsMode = capsMode;
157 mHaveValue = true;
158 notifyAll();
159 } else {
160 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
161 + ") in setCursorCapsMode, ignoring.");
162 }
163 }
164 }
165
Yohei Yukawa930328c2017-10-18 20:19:53 -0700166 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 public void setExtractedText(ExtractedText extractedText, int seq) {
168 synchronized (this) {
169 if (seq == mSeq) {
170 mExtractedText = extractedText;
171 mHaveValue = true;
172 notifyAll();
173 } else {
174 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
175 + ") in setExtractedText, ignoring.");
176 }
177 }
178 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900179
Yohei Yukawa930328c2017-10-18 20:19:53 -0700180 @BinderThread
Yohei Yukawaa277db22014-08-21 18:38:44 -0700181 public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900182 synchronized (this) {
183 if (seq == mSeq) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700184 mRequestUpdateCursorAnchorInfoResult = result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900185 mHaveValue = true;
186 notifyAll();
187 } else {
188 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
189 + ") in setCursorAnchorInfoRequestResult, ignoring.");
190 }
191 }
192 }
193
Yohei Yukawa930328c2017-10-18 20:19:53 -0700194 @BinderThread
Yohei Yukawaadebb522016-06-17 10:10:39 -0700195 public void setCommitContentResult(boolean result, int seq) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700196 synchronized (this) {
197 if (seq == mSeq) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700198 mCommitContentResult = result;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700199 mHaveValue = true;
200 notifyAll();
201 } else {
202 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
Yohei Yukawaadebb522016-06-17 10:10:39 -0700203 + ") in setCommitContentResult, ignoring.");
Yohei Yukawa152944f2016-06-10 19:04:34 -0700204 }
205 }
206 }
207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 /**
209 * Waits for a result for up to {@link #MAX_WAIT_TIME_MILLIS} milliseconds.
210 *
211 * <p>The caller must be synchronized on this callback object.
212 */
Yohei Yukawa930328c2017-10-18 20:19:53 -0700213 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 void waitForResultLocked() {
215 long startTime = SystemClock.uptimeMillis();
216 long endTime = startTime + MAX_WAIT_TIME_MILLIS;
217
218 while (!mHaveValue) {
219 long remainingTime = endTime - SystemClock.uptimeMillis();
220 if (remainingTime <= 0) {
221 Log.w(TAG, "Timed out waiting on IInputContextCallback");
222 return;
223 }
224 try {
225 wait(remainingTime);
226 } catch (InterruptedException e) {
227 }
228 }
229 }
230 }
231
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700232 public InputConnectionWrapper(
233 @NonNull WeakReference<AbstractInputMethodService> inputMethodService,
234 IInputContext inputContext, @MissingMethodFlags final int missingMethods) {
235 mInputMethodService = inputMethodService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 mIInputContext = inputContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700237 mMissingMethods = missingMethods;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 }
239
Yohei Yukawa930328c2017-10-18 20:19:53 -0700240 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 public CharSequence getTextAfterCursor(int length, int flags) {
242 CharSequence value = null;
243 try {
244 InputContextCallback callback = InputContextCallback.getInstance();
245 mIInputContext.getTextAfterCursor(length, flags, callback.mSeq, callback);
246 synchronized (callback) {
247 callback.waitForResultLocked();
248 if (callback.mHaveValue) {
249 value = callback.mTextAfterCursor;
250 }
251 }
252 callback.dispose();
253 } catch (RemoteException e) {
254 return null;
255 }
256 return value;
257 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700258
259 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 public CharSequence getTextBeforeCursor(int length, int flags) {
261 CharSequence value = null;
262 try {
263 InputContextCallback callback = InputContextCallback.getInstance();
264 mIInputContext.getTextBeforeCursor(length, flags, callback.mSeq, callback);
265 synchronized (callback) {
266 callback.waitForResultLocked();
267 if (callback.mHaveValue) {
268 value = callback.mTextBeforeCursor;
269 }
270 }
271 callback.dispose();
272 } catch (RemoteException e) {
273 return null;
274 }
275 return value;
276 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700277
Yohei Yukawa930328c2017-10-18 20:19:53 -0700278 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700279 public CharSequence getSelectedText(int flags) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700280 if (isMethodMissing(MissingMethodFlags.GET_SELECTED_TEXT)) {
281 // This method is not implemented.
282 return null;
283 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700284 CharSequence value = null;
285 try {
286 InputContextCallback callback = InputContextCallback.getInstance();
287 mIInputContext.getSelectedText(flags, callback.mSeq, callback);
288 synchronized (callback) {
289 callback.waitForResultLocked();
290 if (callback.mHaveValue) {
291 value = callback.mSelectedText;
292 }
293 }
294 callback.dispose();
295 } catch (RemoteException e) {
296 return null;
297 }
298 return value;
299 }
300
Yohei Yukawa930328c2017-10-18 20:19:53 -0700301 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 public int getCursorCapsMode(int reqModes) {
303 int value = 0;
304 try {
305 InputContextCallback callback = InputContextCallback.getInstance();
306 mIInputContext.getCursorCapsMode(reqModes, callback.mSeq, callback);
307 synchronized (callback) {
308 callback.waitForResultLocked();
309 if (callback.mHaveValue) {
310 value = callback.mCursorCapsMode;
311 }
312 }
313 callback.dispose();
314 } catch (RemoteException e) {
315 return 0;
316 }
317 return value;
318 }
satoke3797a12011-03-22 06:34:48 +0900319
Yohei Yukawa930328c2017-10-18 20:19:53 -0700320 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
322 ExtractedText value = null;
323 try {
324 InputContextCallback callback = InputContextCallback.getInstance();
325 mIInputContext.getExtractedText(request, flags, callback.mSeq, callback);
326 synchronized (callback) {
327 callback.waitForResultLocked();
328 if (callback.mHaveValue) {
329 value = callback.mExtractedText;
330 }
331 }
332 callback.dispose();
333 } catch (RemoteException e) {
334 return null;
335 }
336 return value;
337 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700338
339 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 public boolean commitText(CharSequence text, int newCursorPosition) {
341 try {
342 mIInputContext.commitText(text, newCursorPosition);
343 return true;
344 } catch (RemoteException e) {
345 return false;
346 }
347 }
348
Yohei Yukawa930328c2017-10-18 20:19:53 -0700349 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 public boolean commitCompletion(CompletionInfo text) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700351 if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
352 // This method is not implemented.
353 return false;
354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 try {
356 mIInputContext.commitCompletion(text);
357 return true;
358 } catch (RemoteException e) {
359 return false;
360 }
361 }
362
Yohei Yukawa930328c2017-10-18 20:19:53 -0700363 @AnyThread
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800364 public boolean commitCorrection(CorrectionInfo correctionInfo) {
365 try {
366 mIInputContext.commitCorrection(correctionInfo);
367 return true;
368 } catch (RemoteException e) {
369 return false;
370 }
371 }
372
Yohei Yukawa930328c2017-10-18 20:19:53 -0700373 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 public boolean setSelection(int start, int end) {
375 try {
376 mIInputContext.setSelection(start, end);
377 return true;
378 } catch (RemoteException e) {
379 return false;
380 }
381 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700382
383 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 public boolean performEditorAction(int actionCode) {
385 try {
386 mIInputContext.performEditorAction(actionCode);
387 return true;
388 } catch (RemoteException e) {
389 return false;
390 }
391 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700392
393 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 public boolean performContextMenuAction(int id) {
395 try {
396 mIInputContext.performContextMenuAction(id);
397 return true;
398 } catch (RemoteException e) {
399 return false;
400 }
401 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700402
Yohei Yukawa930328c2017-10-18 20:19:53 -0700403 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700404 public boolean setComposingRegion(int start, int end) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700405 if (isMethodMissing(MissingMethodFlags.SET_COMPOSING_REGION)) {
406 // This method is not implemented.
407 return false;
408 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700409 try {
410 mIInputContext.setComposingRegion(start, end);
411 return true;
412 } catch (RemoteException e) {
413 return false;
414 }
415 }
416
Yohei Yukawa930328c2017-10-18 20:19:53 -0700417 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 public boolean setComposingText(CharSequence text, int newCursorPosition) {
419 try {
420 mIInputContext.setComposingText(text, newCursorPosition);
421 return true;
422 } catch (RemoteException e) {
423 return false;
424 }
425 }
426
Yohei Yukawa930328c2017-10-18 20:19:53 -0700427 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 public boolean finishComposingText() {
429 try {
430 mIInputContext.finishComposingText();
431 return true;
432 } catch (RemoteException e) {
433 return false;
434 }
435 }
436
Yohei Yukawa930328c2017-10-18 20:19:53 -0700437 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 public boolean beginBatchEdit() {
439 try {
440 mIInputContext.beginBatchEdit();
441 return true;
442 } catch (RemoteException e) {
443 return false;
444 }
445 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700446
447 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 public boolean endBatchEdit() {
449 try {
450 mIInputContext.endBatchEdit();
451 return true;
452 } catch (RemoteException e) {
453 return false;
454 }
455 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700456
457 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 public boolean sendKeyEvent(KeyEvent event) {
459 try {
460 mIInputContext.sendKeyEvent(event);
461 return true;
462 } catch (RemoteException e) {
463 return false;
464 }
465 }
466
Yohei Yukawa930328c2017-10-18 20:19:53 -0700467 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 public boolean clearMetaKeyStates(int states) {
469 try {
470 mIInputContext.clearMetaKeyStates(states);
471 return true;
472 } catch (RemoteException e) {
473 return false;
474 }
475 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800476
Yohei Yukawa930328c2017-10-18 20:19:53 -0700477 @AnyThread
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800478 public boolean deleteSurroundingText(int beforeLength, int afterLength) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 try {
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800480 mIInputContext.deleteSurroundingText(beforeLength, afterLength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 return true;
482 } catch (RemoteException e) {
483 return false;
484 }
485 }
486
Yohei Yukawa930328c2017-10-18 20:19:53 -0700487 @AnyThread
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800488 public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700489 if (isMethodMissing(MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS)) {
490 // This method is not implemented.
491 return false;
492 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800493 try {
494 mIInputContext.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
495 return true;
496 } catch (RemoteException e) {
497 return false;
498 }
499 }
500
Yohei Yukawa930328c2017-10-18 20:19:53 -0700501 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 public boolean reportFullscreenMode(boolean enabled) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800503 // Nothing should happen when called from input method.
504 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 }
506
Yohei Yukawa930328c2017-10-18 20:19:53 -0700507 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 public boolean performPrivateCommand(String action, Bundle data) {
509 try {
510 mIInputContext.performPrivateCommand(action, data);
511 return true;
512 } catch (RemoteException e) {
513 return false;
514 }
515 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900516
Yohei Yukawa930328c2017-10-18 20:19:53 -0700517 @AnyThread
Yohei Yukawad8636ea2014-09-02 22:03:30 -0700518 public boolean requestCursorUpdates(int cursorUpdateMode) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700519 boolean result = false;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700520 if (isMethodMissing(MissingMethodFlags.REQUEST_CURSOR_UPDATES)) {
521 // This method is not implemented.
522 return false;
523 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900524 try {
525 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawaa277db22014-08-21 18:38:44 -0700526 mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900527 synchronized (callback) {
528 callback.waitForResultLocked();
529 if (callback.mHaveValue) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700530 result = callback.mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900531 }
532 }
533 callback.dispose();
534 } catch (RemoteException e) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700535 return false;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900536 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700537 return result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900538 }
Yohei Yukawa612cce92016-02-11 17:47:33 -0800539
Yohei Yukawa930328c2017-10-18 20:19:53 -0700540 @AnyThread
Yohei Yukawa612cce92016-02-11 17:47:33 -0800541 public Handler getHandler() {
542 // Nothing should happen when called from input method.
543 return null;
544 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700545
Yohei Yukawa930328c2017-10-18 20:19:53 -0700546 @AnyThread
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700547 public void closeConnection() {
548 // Nothing should happen when called from input method.
549 }
550
Yohei Yukawa930328c2017-10-18 20:19:53 -0700551 @AnyThread
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700552 public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700553 boolean result = false;
Yohei Yukawaadebb522016-06-17 10:10:39 -0700554 if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700555 // This method is not implemented.
556 return false;
557 }
558 try {
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000559 if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700560 final AbstractInputMethodService inputMethodService = mInputMethodService.get();
561 if (inputMethodService == null) {
562 // This basically should not happen, because it's the the caller of this method.
563 return false;
564 }
565 inputMethodService.exposeContent(inputContentInfo, this);
566 }
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000567
Yohei Yukawa152944f2016-06-10 19:04:34 -0700568 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700569 mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700570 synchronized (callback) {
571 callback.waitForResultLocked();
572 if (callback.mHaveValue) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700573 result = callback.mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700574 }
575 }
576 callback.dispose();
577 } catch (RemoteException e) {
578 return false;
579 }
580 return result;
581 }
582
Yohei Yukawa930328c2017-10-18 20:19:53 -0700583 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700584 private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) {
585 return (mMissingMethods & methodFlag) == methodFlag;
586 }
587
Yohei Yukawa930328c2017-10-18 20:19:53 -0700588 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700589 @Override
590 public String toString() {
591 return "InputConnectionWrapper{idHash=#"
592 + Integer.toHexString(System.identityHashCode(this))
593 + " mMissingMethods="
594 + InputConnectionInspector.getMissingMethodFlagsAsString(mMissingMethods) + "}";
595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596}