blob: 3bd3072c0ebe9760bed674ec32a59c086f7b4960 [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);
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700374 notifyUserActionIfNecessary();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 return true;
376 } catch (RemoteException e) {
377 return false;
378 }
379 }
380
Yohei Yukawa930328c2017-10-18 20:19:53 -0700381 @AnyThread
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700382 private void notifyUserActionIfNecessary() {
383 final AbstractInputMethodService inputMethodService = mInputMethodService.get();
384 if (inputMethodService == null) {
385 // This basically should not happen, because it's the the caller of this method.
386 return;
387 }
388 inputMethodService.notifyUserActionIfNecessary();
389 }
390
391 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 public boolean commitCompletion(CompletionInfo text) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700393 if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
394 // This method is not implemented.
395 return false;
396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 try {
398 mIInputContext.commitCompletion(text);
399 return true;
400 } catch (RemoteException e) {
401 return false;
402 }
403 }
404
Yohei Yukawa930328c2017-10-18 20:19:53 -0700405 @AnyThread
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800406 public boolean commitCorrection(CorrectionInfo correctionInfo) {
407 try {
408 mIInputContext.commitCorrection(correctionInfo);
409 return true;
410 } catch (RemoteException e) {
411 return false;
412 }
413 }
414
Yohei Yukawa930328c2017-10-18 20:19:53 -0700415 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 public boolean setSelection(int start, int end) {
417 try {
418 mIInputContext.setSelection(start, end);
419 return true;
420 } catch (RemoteException e) {
421 return false;
422 }
423 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700424
425 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 public boolean performEditorAction(int actionCode) {
427 try {
428 mIInputContext.performEditorAction(actionCode);
429 return true;
430 } catch (RemoteException e) {
431 return false;
432 }
433 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700434
435 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 public boolean performContextMenuAction(int id) {
437 try {
438 mIInputContext.performContextMenuAction(id);
439 return true;
440 } catch (RemoteException e) {
441 return false;
442 }
443 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700444
Yohei Yukawa930328c2017-10-18 20:19:53 -0700445 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700446 public boolean setComposingRegion(int start, int end) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700447 if (isMethodMissing(MissingMethodFlags.SET_COMPOSING_REGION)) {
448 // This method is not implemented.
449 return false;
450 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700451 try {
452 mIInputContext.setComposingRegion(start, end);
453 return true;
454 } catch (RemoteException e) {
455 return false;
456 }
457 }
458
Yohei Yukawa930328c2017-10-18 20:19:53 -0700459 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 public boolean setComposingText(CharSequence text, int newCursorPosition) {
461 try {
462 mIInputContext.setComposingText(text, newCursorPosition);
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700463 notifyUserActionIfNecessary();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 return true;
465 } catch (RemoteException e) {
466 return false;
467 }
468 }
469
Yohei Yukawa930328c2017-10-18 20:19:53 -0700470 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 public boolean finishComposingText() {
472 try {
473 mIInputContext.finishComposingText();
474 return true;
475 } catch (RemoteException e) {
476 return false;
477 }
478 }
479
Yohei Yukawa930328c2017-10-18 20:19:53 -0700480 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 public boolean beginBatchEdit() {
482 try {
483 mIInputContext.beginBatchEdit();
484 return true;
485 } catch (RemoteException e) {
486 return false;
487 }
488 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700489
490 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 public boolean endBatchEdit() {
492 try {
493 mIInputContext.endBatchEdit();
494 return true;
495 } catch (RemoteException e) {
496 return false;
497 }
498 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700499
500 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 public boolean sendKeyEvent(KeyEvent event) {
502 try {
503 mIInputContext.sendKeyEvent(event);
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700504 notifyUserActionIfNecessary();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 return true;
506 } catch (RemoteException e) {
507 return false;
508 }
509 }
510
Yohei Yukawa930328c2017-10-18 20:19:53 -0700511 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 public boolean clearMetaKeyStates(int states) {
513 try {
514 mIInputContext.clearMetaKeyStates(states);
515 return true;
516 } catch (RemoteException e) {
517 return false;
518 }
519 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800520
Yohei Yukawa930328c2017-10-18 20:19:53 -0700521 @AnyThread
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800522 public boolean deleteSurroundingText(int beforeLength, int afterLength) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 try {
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800524 mIInputContext.deleteSurroundingText(beforeLength, afterLength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 return true;
526 } catch (RemoteException e) {
527 return false;
528 }
529 }
530
Yohei Yukawa930328c2017-10-18 20:19:53 -0700531 @AnyThread
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800532 public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700533 if (isMethodMissing(MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS)) {
534 // This method is not implemented.
535 return false;
536 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800537 try {
538 mIInputContext.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
539 return true;
540 } catch (RemoteException e) {
541 return false;
542 }
543 }
544
Yohei Yukawa930328c2017-10-18 20:19:53 -0700545 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 public boolean reportFullscreenMode(boolean enabled) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800547 // Nothing should happen when called from input method.
548 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 }
550
Yohei Yukawa930328c2017-10-18 20:19:53 -0700551 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 public boolean performPrivateCommand(String action, Bundle data) {
553 try {
554 mIInputContext.performPrivateCommand(action, data);
555 return true;
556 } catch (RemoteException e) {
557 return false;
558 }
559 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900560
Yohei Yukawa930328c2017-10-18 20:19:53 -0700561 @AnyThread
Yohei Yukawad8636ea2014-09-02 22:03:30 -0700562 public boolean requestCursorUpdates(int cursorUpdateMode) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700563 if (mIsUnbindIssued.get()) {
564 return false;
565 }
566
Yohei Yukawaa277db22014-08-21 18:38:44 -0700567 boolean result = false;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700568 if (isMethodMissing(MissingMethodFlags.REQUEST_CURSOR_UPDATES)) {
569 // This method is not implemented.
570 return false;
571 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900572 try {
573 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawaa277db22014-08-21 18:38:44 -0700574 mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900575 synchronized (callback) {
576 callback.waitForResultLocked();
577 if (callback.mHaveValue) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700578 result = callback.mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900579 }
580 }
581 callback.dispose();
582 } catch (RemoteException e) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700583 return false;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900584 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700585 return result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900586 }
Yohei Yukawa612cce92016-02-11 17:47:33 -0800587
Yohei Yukawa930328c2017-10-18 20:19:53 -0700588 @AnyThread
Yohei Yukawa612cce92016-02-11 17:47:33 -0800589 public Handler getHandler() {
590 // Nothing should happen when called from input method.
591 return null;
592 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700593
Yohei Yukawa930328c2017-10-18 20:19:53 -0700594 @AnyThread
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700595 public void closeConnection() {
596 // Nothing should happen when called from input method.
597 }
598
Yohei Yukawa930328c2017-10-18 20:19:53 -0700599 @AnyThread
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700600 public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700601 if (mIsUnbindIssued.get()) {
602 return false;
603 }
604
Yohei Yukawa152944f2016-06-10 19:04:34 -0700605 boolean result = false;
Yohei Yukawaadebb522016-06-17 10:10:39 -0700606 if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700607 // This method is not implemented.
608 return false;
609 }
610 try {
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000611 if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700612 final AbstractInputMethodService inputMethodService = mInputMethodService.get();
613 if (inputMethodService == null) {
614 // This basically should not happen, because it's the the caller of this method.
615 return false;
616 }
617 inputMethodService.exposeContent(inputContentInfo, this);
618 }
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000619
Yohei Yukawa152944f2016-06-10 19:04:34 -0700620 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700621 mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700622 synchronized (callback) {
623 callback.waitForResultLocked();
624 if (callback.mHaveValue) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700625 result = callback.mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700626 }
627 }
628 callback.dispose();
629 } catch (RemoteException e) {
630 return false;
631 }
632 return result;
633 }
634
Yohei Yukawa930328c2017-10-18 20:19:53 -0700635 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700636 private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) {
637 return (mMissingMethods & methodFlag) == methodFlag;
638 }
639
Yohei Yukawa930328c2017-10-18 20:19:53 -0700640 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700641 @Override
642 public String toString() {
643 return "InputConnectionWrapper{idHash=#"
644 + Integer.toHexString(System.identityHashCode(this))
645 + " mMissingMethods="
646 + InputConnectionInspector.getMissingMethodFlagsAsString(mMissingMethods) + "}";
647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648}