blob: 5b65bbe1e90e6aa49630be44d0dfa25a87ad3caf [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;
Tarandeep Singh1d113d02017-10-13 10:51:00 -070039import java.util.concurrent.atomic.AtomicBoolean;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041public class InputConnectionWrapper implements InputConnection {
42 private static final int MAX_WAIT_TIME_MILLIS = 2000;
43 private final IInputContext mIInputContext;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070044 @NonNull
45 private final WeakReference<AbstractInputMethodService> mInputMethodService;
46
Yohei Yukawa19a80a12016-03-14 22:57:37 -070047 @MissingMethodFlags
48 private final int mMissingMethods;
49
Tarandeep Singh1d113d02017-10-13 10:51:00 -070050 /**
51 * {@code true} if the system already decided to take away IME focus from the target app. This
52 * can be signaled even when the corresponding signal is in the task queue and
53 * {@link InputMethodService#onUnbindInput()} is not yet called back on the UI thread.
54 */
55 @NonNull
56 private final AtomicBoolean mIsUnbindIssued;
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 static class InputContextCallback extends IInputContextCallback.Stub {
59 private static final String TAG = "InputConnectionWrapper.ICC";
60 public int mSeq;
61 public boolean mHaveValue;
62 public CharSequence mTextBeforeCursor;
63 public CharSequence mTextAfterCursor;
Amith Yamasania90b7f02010-08-25 18:27:20 -070064 public CharSequence mSelectedText;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 public ExtractedText mExtractedText;
66 public int mCursorCapsMode;
Yohei Yukawaa277db22014-08-21 18:38:44 -070067 public boolean mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawaadebb522016-06-17 10:10:39 -070068 public boolean mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -070069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 // A 'pool' of one InputContextCallback. Each ICW request will attempt to gain
71 // exclusive access to this object.
72 private static InputContextCallback sInstance = new InputContextCallback();
73 private static int sSequenceNumber = 1;
74
75 /**
76 * Returns an InputContextCallback object that is guaranteed not to be in use by
77 * any other thread. The returned object's 'have value' flag is cleared and its expected
78 * sequence number is set to a new integer. We use a sequence number so that replies that
79 * occur after a timeout has expired are not interpreted as replies to a later request.
80 */
Yohei Yukawa930328c2017-10-18 20:19:53 -070081 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 private static InputContextCallback getInstance() {
83 synchronized (InputContextCallback.class) {
84 // Return sInstance if it's non-null, otherwise construct a new callback
85 InputContextCallback callback;
86 if (sInstance != null) {
87 callback = sInstance;
88 sInstance = null;
89
90 // Reset the callback
91 callback.mHaveValue = false;
92 } else {
93 callback = new InputContextCallback();
94 }
95
96 // Set the sequence number
97 callback.mSeq = sSequenceNumber++;
98 return callback;
99 }
100 }
101
102 /**
103 * Makes the given InputContextCallback available for use in the future.
104 */
Yohei Yukawa930328c2017-10-18 20:19:53 -0700105 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 private void dispose() {
107 synchronized (InputContextCallback.class) {
108 // If sInstance is non-null, just let this object be garbage-collected
109 if (sInstance == null) {
110 // Allow any objects being held to be gc'ed
111 mTextAfterCursor = null;
112 mTextBeforeCursor = null;
113 mExtractedText = null;
114 sInstance = this;
115 }
116 }
117 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700118
119 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 public void setTextBeforeCursor(CharSequence textBeforeCursor, int seq) {
121 synchronized (this) {
122 if (seq == mSeq) {
123 mTextBeforeCursor = textBeforeCursor;
124 mHaveValue = true;
125 notifyAll();
126 } else {
127 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
128 + ") in setTextBeforeCursor, ignoring.");
129 }
130 }
131 }
132
Yohei Yukawa930328c2017-10-18 20:19:53 -0700133 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 public void setTextAfterCursor(CharSequence textAfterCursor, int seq) {
135 synchronized (this) {
136 if (seq == mSeq) {
137 mTextAfterCursor = textAfterCursor;
138 mHaveValue = true;
139 notifyAll();
140 } else {
141 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
142 + ") in setTextAfterCursor, ignoring.");
143 }
144 }
145 }
146
Yohei Yukawa930328c2017-10-18 20:19:53 -0700147 @BinderThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700148 public void setSelectedText(CharSequence selectedText, int seq) {
149 synchronized (this) {
150 if (seq == mSeq) {
151 mSelectedText = selectedText;
152 mHaveValue = true;
153 notifyAll();
154 } else {
155 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
156 + ") in setSelectedText, ignoring.");
157 }
158 }
159 }
160
Yohei Yukawa930328c2017-10-18 20:19:53 -0700161 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 public void setCursorCapsMode(int capsMode, int seq) {
163 synchronized (this) {
164 if (seq == mSeq) {
165 mCursorCapsMode = capsMode;
166 mHaveValue = true;
167 notifyAll();
168 } else {
169 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
170 + ") in setCursorCapsMode, ignoring.");
171 }
172 }
173 }
174
Yohei Yukawa930328c2017-10-18 20:19:53 -0700175 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 public void setExtractedText(ExtractedText extractedText, int seq) {
177 synchronized (this) {
178 if (seq == mSeq) {
179 mExtractedText = extractedText;
180 mHaveValue = true;
181 notifyAll();
182 } else {
183 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
184 + ") in setExtractedText, ignoring.");
185 }
186 }
187 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900188
Yohei Yukawa930328c2017-10-18 20:19:53 -0700189 @BinderThread
Yohei Yukawaa277db22014-08-21 18:38:44 -0700190 public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900191 synchronized (this) {
192 if (seq == mSeq) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700193 mRequestUpdateCursorAnchorInfoResult = result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900194 mHaveValue = true;
195 notifyAll();
196 } else {
197 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
198 + ") in setCursorAnchorInfoRequestResult, ignoring.");
199 }
200 }
201 }
202
Yohei Yukawa930328c2017-10-18 20:19:53 -0700203 @BinderThread
Yohei Yukawaadebb522016-06-17 10:10:39 -0700204 public void setCommitContentResult(boolean result, int seq) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700205 synchronized (this) {
206 if (seq == mSeq) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700207 mCommitContentResult = result;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700208 mHaveValue = true;
209 notifyAll();
210 } else {
211 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
Yohei Yukawaadebb522016-06-17 10:10:39 -0700212 + ") in setCommitContentResult, ignoring.");
Yohei Yukawa152944f2016-06-10 19:04:34 -0700213 }
214 }
215 }
216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 /**
218 * Waits for a result for up to {@link #MAX_WAIT_TIME_MILLIS} milliseconds.
219 *
220 * <p>The caller must be synchronized on this callback object.
221 */
Yohei Yukawa930328c2017-10-18 20:19:53 -0700222 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 void waitForResultLocked() {
224 long startTime = SystemClock.uptimeMillis();
225 long endTime = startTime + MAX_WAIT_TIME_MILLIS;
226
227 while (!mHaveValue) {
228 long remainingTime = endTime - SystemClock.uptimeMillis();
229 if (remainingTime <= 0) {
230 Log.w(TAG, "Timed out waiting on IInputContextCallback");
231 return;
232 }
233 try {
234 wait(remainingTime);
235 } catch (InterruptedException e) {
236 }
237 }
238 }
239 }
240
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700241 public InputConnectionWrapper(
242 @NonNull WeakReference<AbstractInputMethodService> inputMethodService,
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700243 IInputContext inputContext, @MissingMethodFlags final int missingMethods,
244 @NonNull AtomicBoolean isUnbindIssued) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700245 mInputMethodService = inputMethodService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 mIInputContext = inputContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700247 mMissingMethods = missingMethods;
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700248 mIsUnbindIssued = isUnbindIssued;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 }
250
Yohei Yukawa930328c2017-10-18 20:19:53 -0700251 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 public CharSequence getTextAfterCursor(int length, int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700253 if (mIsUnbindIssued.get()) {
254 return null;
255 }
256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 CharSequence value = null;
258 try {
259 InputContextCallback callback = InputContextCallback.getInstance();
260 mIInputContext.getTextAfterCursor(length, flags, callback.mSeq, callback);
261 synchronized (callback) {
262 callback.waitForResultLocked();
263 if (callback.mHaveValue) {
264 value = callback.mTextAfterCursor;
265 }
266 }
267 callback.dispose();
268 } catch (RemoteException e) {
269 return null;
270 }
271 return value;
272 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700273
274 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 public CharSequence getTextBeforeCursor(int length, int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700276 if (mIsUnbindIssued.get()) {
277 return null;
278 }
279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 CharSequence value = null;
281 try {
282 InputContextCallback callback = InputContextCallback.getInstance();
283 mIInputContext.getTextBeforeCursor(length, flags, callback.mSeq, callback);
284 synchronized (callback) {
285 callback.waitForResultLocked();
286 if (callback.mHaveValue) {
287 value = callback.mTextBeforeCursor;
288 }
289 }
290 callback.dispose();
291 } catch (RemoteException e) {
292 return null;
293 }
294 return value;
295 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700296
Yohei Yukawa930328c2017-10-18 20:19:53 -0700297 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700298 public CharSequence getSelectedText(int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700299 if (mIsUnbindIssued.get()) {
300 return null;
301 }
302
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700303 if (isMethodMissing(MissingMethodFlags.GET_SELECTED_TEXT)) {
304 // This method is not implemented.
305 return null;
306 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700307 CharSequence value = null;
308 try {
309 InputContextCallback callback = InputContextCallback.getInstance();
310 mIInputContext.getSelectedText(flags, callback.mSeq, callback);
311 synchronized (callback) {
312 callback.waitForResultLocked();
313 if (callback.mHaveValue) {
314 value = callback.mSelectedText;
315 }
316 }
317 callback.dispose();
318 } catch (RemoteException e) {
319 return null;
320 }
321 return value;
322 }
323
Yohei Yukawa930328c2017-10-18 20:19:53 -0700324 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 public int getCursorCapsMode(int reqModes) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700326 if (mIsUnbindIssued.get()) {
327 return 0;
328 }
329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 int value = 0;
331 try {
332 InputContextCallback callback = InputContextCallback.getInstance();
333 mIInputContext.getCursorCapsMode(reqModes, callback.mSeq, callback);
334 synchronized (callback) {
335 callback.waitForResultLocked();
336 if (callback.mHaveValue) {
337 value = callback.mCursorCapsMode;
338 }
339 }
340 callback.dispose();
341 } catch (RemoteException e) {
342 return 0;
343 }
344 return value;
345 }
satoke3797a12011-03-22 06:34:48 +0900346
Yohei Yukawa930328c2017-10-18 20:19:53 -0700347 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700349 if (mIsUnbindIssued.get()) {
350 return null;
351 }
352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 ExtractedText value = null;
354 try {
355 InputContextCallback callback = InputContextCallback.getInstance();
356 mIInputContext.getExtractedText(request, flags, callback.mSeq, callback);
357 synchronized (callback) {
358 callback.waitForResultLocked();
359 if (callback.mHaveValue) {
360 value = callback.mExtractedText;
361 }
362 }
363 callback.dispose();
364 } catch (RemoteException e) {
365 return null;
366 }
367 return value;
368 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700369
370 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 public boolean commitText(CharSequence text, int newCursorPosition) {
372 try {
373 mIInputContext.commitText(text, newCursorPosition);
374 return true;
375 } catch (RemoteException e) {
376 return false;
377 }
378 }
379
Yohei Yukawa930328c2017-10-18 20:19:53 -0700380 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 public boolean commitCompletion(CompletionInfo text) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700382 if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
383 // This method is not implemented.
384 return false;
385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 try {
387 mIInputContext.commitCompletion(text);
388 return true;
389 } catch (RemoteException e) {
390 return false;
391 }
392 }
393
Yohei Yukawa930328c2017-10-18 20:19:53 -0700394 @AnyThread
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800395 public boolean commitCorrection(CorrectionInfo correctionInfo) {
396 try {
397 mIInputContext.commitCorrection(correctionInfo);
398 return true;
399 } catch (RemoteException e) {
400 return false;
401 }
402 }
403
Yohei Yukawa930328c2017-10-18 20:19:53 -0700404 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 public boolean setSelection(int start, int end) {
406 try {
407 mIInputContext.setSelection(start, end);
408 return true;
409 } catch (RemoteException e) {
410 return false;
411 }
412 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700413
414 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 public boolean performEditorAction(int actionCode) {
416 try {
417 mIInputContext.performEditorAction(actionCode);
418 return true;
419 } catch (RemoteException e) {
420 return false;
421 }
422 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700423
424 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 public boolean performContextMenuAction(int id) {
426 try {
427 mIInputContext.performContextMenuAction(id);
428 return true;
429 } catch (RemoteException e) {
430 return false;
431 }
432 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700433
Yohei Yukawa930328c2017-10-18 20:19:53 -0700434 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700435 public boolean setComposingRegion(int start, int end) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700436 if (isMethodMissing(MissingMethodFlags.SET_COMPOSING_REGION)) {
437 // This method is not implemented.
438 return false;
439 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700440 try {
441 mIInputContext.setComposingRegion(start, end);
442 return true;
443 } catch (RemoteException e) {
444 return false;
445 }
446 }
447
Yohei Yukawa930328c2017-10-18 20:19:53 -0700448 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 public boolean setComposingText(CharSequence text, int newCursorPosition) {
450 try {
451 mIInputContext.setComposingText(text, newCursorPosition);
452 return true;
453 } catch (RemoteException e) {
454 return false;
455 }
456 }
457
Yohei Yukawa930328c2017-10-18 20:19:53 -0700458 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 public boolean finishComposingText() {
460 try {
461 mIInputContext.finishComposingText();
462 return true;
463 } catch (RemoteException e) {
464 return false;
465 }
466 }
467
Yohei Yukawa930328c2017-10-18 20:19:53 -0700468 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 public boolean beginBatchEdit() {
470 try {
471 mIInputContext.beginBatchEdit();
472 return true;
473 } catch (RemoteException e) {
474 return false;
475 }
476 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700477
478 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 public boolean endBatchEdit() {
480 try {
481 mIInputContext.endBatchEdit();
482 return true;
483 } catch (RemoteException e) {
484 return false;
485 }
486 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700487
488 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 public boolean sendKeyEvent(KeyEvent event) {
490 try {
491 mIInputContext.sendKeyEvent(event);
492 return true;
493 } catch (RemoteException e) {
494 return false;
495 }
496 }
497
Yohei Yukawa930328c2017-10-18 20:19:53 -0700498 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 public boolean clearMetaKeyStates(int states) {
500 try {
501 mIInputContext.clearMetaKeyStates(states);
502 return true;
503 } catch (RemoteException e) {
504 return false;
505 }
506 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800507
Yohei Yukawa930328c2017-10-18 20:19:53 -0700508 @AnyThread
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800509 public boolean deleteSurroundingText(int beforeLength, int afterLength) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 try {
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800511 mIInputContext.deleteSurroundingText(beforeLength, afterLength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 return true;
513 } catch (RemoteException e) {
514 return false;
515 }
516 }
517
Yohei Yukawa930328c2017-10-18 20:19:53 -0700518 @AnyThread
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800519 public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700520 if (isMethodMissing(MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS)) {
521 // This method is not implemented.
522 return false;
523 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800524 try {
525 mIInputContext.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
526 return true;
527 } catch (RemoteException e) {
528 return false;
529 }
530 }
531
Yohei Yukawa930328c2017-10-18 20:19:53 -0700532 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 public boolean reportFullscreenMode(boolean enabled) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800534 // Nothing should happen when called from input method.
535 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 }
537
Yohei Yukawa930328c2017-10-18 20:19:53 -0700538 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 public boolean performPrivateCommand(String action, Bundle data) {
540 try {
541 mIInputContext.performPrivateCommand(action, data);
542 return true;
543 } catch (RemoteException e) {
544 return false;
545 }
546 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900547
Yohei Yukawa930328c2017-10-18 20:19:53 -0700548 @AnyThread
Yohei Yukawad8636ea2014-09-02 22:03:30 -0700549 public boolean requestCursorUpdates(int cursorUpdateMode) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700550 if (mIsUnbindIssued.get()) {
551 return false;
552 }
553
Yohei Yukawaa277db22014-08-21 18:38:44 -0700554 boolean result = false;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700555 if (isMethodMissing(MissingMethodFlags.REQUEST_CURSOR_UPDATES)) {
556 // This method is not implemented.
557 return false;
558 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900559 try {
560 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawaa277db22014-08-21 18:38:44 -0700561 mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900562 synchronized (callback) {
563 callback.waitForResultLocked();
564 if (callback.mHaveValue) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700565 result = callback.mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900566 }
567 }
568 callback.dispose();
569 } catch (RemoteException e) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700570 return false;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900571 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700572 return result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900573 }
Yohei Yukawa612cce92016-02-11 17:47:33 -0800574
Yohei Yukawa930328c2017-10-18 20:19:53 -0700575 @AnyThread
Yohei Yukawa612cce92016-02-11 17:47:33 -0800576 public Handler getHandler() {
577 // Nothing should happen when called from input method.
578 return null;
579 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700580
Yohei Yukawa930328c2017-10-18 20:19:53 -0700581 @AnyThread
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700582 public void closeConnection() {
583 // Nothing should happen when called from input method.
584 }
585
Yohei Yukawa930328c2017-10-18 20:19:53 -0700586 @AnyThread
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700587 public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700588 if (mIsUnbindIssued.get()) {
589 return false;
590 }
591
Yohei Yukawa152944f2016-06-10 19:04:34 -0700592 boolean result = false;
Yohei Yukawaadebb522016-06-17 10:10:39 -0700593 if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700594 // This method is not implemented.
595 return false;
596 }
597 try {
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000598 if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700599 final AbstractInputMethodService inputMethodService = mInputMethodService.get();
600 if (inputMethodService == null) {
601 // This basically should not happen, because it's the the caller of this method.
602 return false;
603 }
604 inputMethodService.exposeContent(inputContentInfo, this);
605 }
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000606
Yohei Yukawa152944f2016-06-10 19:04:34 -0700607 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700608 mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700609 synchronized (callback) {
610 callback.waitForResultLocked();
611 if (callback.mHaveValue) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700612 result = callback.mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700613 }
614 }
615 callback.dispose();
616 } catch (RemoteException e) {
617 return false;
618 }
619 return result;
620 }
621
Yohei Yukawa930328c2017-10-18 20:19:53 -0700622 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700623 private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) {
624 return (mMissingMethods & methodFlag) == methodFlag;
625 }
626
Yohei Yukawa930328c2017-10-18 20:19:53 -0700627 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700628 @Override
629 public String toString() {
630 return "InputConnectionWrapper{idHash=#"
631 + Integer.toHexString(System.identityHashCode(this))
632 + " mMissingMethods="
633 + InputConnectionInspector.getMissingMethodFlagsAsString(mMissingMethods) + "}";
634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635}