blob: 0c057ea6df59bf2e3df9acbaf44b3e79f529adc4 [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;
Andrei Onea15884392019-03-22 17:28:11 +000022import android.annotation.UnsupportedAppUsage;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070023import android.inputmethodservice.AbstractInputMethodService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.os.Bundle;
Yohei Yukawa612cce92016-02-11 17:47:33 -080025import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.os.RemoteException;
27import android.os.SystemClock;
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.ExtractedText;
33import android.view.inputmethod.ExtractedTextRequest;
34import android.view.inputmethod.InputConnection;
Yohei Yukawa19a80a12016-03-14 22:57:37 -070035import android.view.inputmethod.InputConnectionInspector;
36import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
Yohei Yukawa152944f2016-06-10 19:04:34 -070037import android.view.inputmethod.InputContentInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
Yohei Yukawa45700fa2016-06-23 17:12:59 -070039import java.lang.ref.WeakReference;
Tarandeep Singh1d113d02017-10-13 10:51:00 -070040import java.util.concurrent.atomic.AtomicBoolean;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042public class InputConnectionWrapper implements InputConnection {
43 private static final int MAX_WAIT_TIME_MILLIS = 2000;
44 private final IInputContext mIInputContext;
Yohei Yukawa45700fa2016-06-23 17:12:59 -070045 @NonNull
46 private final WeakReference<AbstractInputMethodService> mInputMethodService;
47
Yohei Yukawa19a80a12016-03-14 22:57:37 -070048 @MissingMethodFlags
49 private final int mMissingMethods;
50
Tarandeep Singh1d113d02017-10-13 10:51:00 -070051 /**
52 * {@code true} if the system already decided to take away IME focus from the target app. This
53 * can be signaled even when the corresponding signal is in the task queue and
54 * {@link InputMethodService#onUnbindInput()} is not yet called back on the UI thread.
55 */
56 @NonNull
57 private final AtomicBoolean mIsUnbindIssued;
58
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 static class InputContextCallback extends IInputContextCallback.Stub {
60 private static final String TAG = "InputConnectionWrapper.ICC";
61 public int mSeq;
62 public boolean mHaveValue;
63 public CharSequence mTextBeforeCursor;
64 public CharSequence mTextAfterCursor;
Amith Yamasania90b7f02010-08-25 18:27:20 -070065 public CharSequence mSelectedText;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066 public ExtractedText mExtractedText;
67 public int mCursorCapsMode;
Yohei Yukawaa277db22014-08-21 18:38:44 -070068 public boolean mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawaadebb522016-06-17 10:10:39 -070069 public boolean mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -070070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 // A 'pool' of one InputContextCallback. Each ICW request will attempt to gain
72 // exclusive access to this object.
73 private static InputContextCallback sInstance = new InputContextCallback();
74 private static int sSequenceNumber = 1;
75
76 /**
77 * Returns an InputContextCallback object that is guaranteed not to be in use by
78 * any other thread. The returned object's 'have value' flag is cleared and its expected
79 * sequence number is set to a new integer. We use a sequence number so that replies that
80 * occur after a timeout has expired are not interpreted as replies to a later request.
81 */
Andrei Onea15884392019-03-22 17:28:11 +000082 @UnsupportedAppUsage
Yohei Yukawa930328c2017-10-18 20:19:53 -070083 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 private static InputContextCallback getInstance() {
85 synchronized (InputContextCallback.class) {
86 // Return sInstance if it's non-null, otherwise construct a new callback
87 InputContextCallback callback;
88 if (sInstance != null) {
89 callback = sInstance;
90 sInstance = null;
91
92 // Reset the callback
93 callback.mHaveValue = false;
94 } else {
95 callback = new InputContextCallback();
96 }
97
98 // Set the sequence number
99 callback.mSeq = sSequenceNumber++;
100 return callback;
101 }
102 }
103
104 /**
105 * Makes the given InputContextCallback available for use in the future.
106 */
Andrei Onea15884392019-03-22 17:28:11 +0000107 @UnsupportedAppUsage
Yohei Yukawa930328c2017-10-18 20:19:53 -0700108 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 private void dispose() {
110 synchronized (InputContextCallback.class) {
111 // If sInstance is non-null, just let this object be garbage-collected
112 if (sInstance == null) {
113 // Allow any objects being held to be gc'ed
114 mTextAfterCursor = null;
115 mTextBeforeCursor = null;
116 mExtractedText = null;
117 sInstance = this;
118 }
119 }
120 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700121
122 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 public void setTextBeforeCursor(CharSequence textBeforeCursor, int seq) {
124 synchronized (this) {
125 if (seq == mSeq) {
126 mTextBeforeCursor = textBeforeCursor;
127 mHaveValue = true;
128 notifyAll();
129 } else {
130 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
131 + ") in setTextBeforeCursor, ignoring.");
132 }
133 }
134 }
135
Yohei Yukawa930328c2017-10-18 20:19:53 -0700136 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 public void setTextAfterCursor(CharSequence textAfterCursor, int seq) {
138 synchronized (this) {
139 if (seq == mSeq) {
140 mTextAfterCursor = textAfterCursor;
141 mHaveValue = true;
142 notifyAll();
143 } else {
144 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
145 + ") in setTextAfterCursor, ignoring.");
146 }
147 }
148 }
149
Yohei Yukawa930328c2017-10-18 20:19:53 -0700150 @BinderThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700151 public void setSelectedText(CharSequence selectedText, int seq) {
152 synchronized (this) {
153 if (seq == mSeq) {
154 mSelectedText = selectedText;
155 mHaveValue = true;
156 notifyAll();
157 } else {
158 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
159 + ") in setSelectedText, ignoring.");
160 }
161 }
162 }
163
Yohei Yukawa930328c2017-10-18 20:19:53 -0700164 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 public void setCursorCapsMode(int capsMode, int seq) {
166 synchronized (this) {
167 if (seq == mSeq) {
168 mCursorCapsMode = capsMode;
169 mHaveValue = true;
170 notifyAll();
171 } else {
172 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
173 + ") in setCursorCapsMode, ignoring.");
174 }
175 }
176 }
177
Yohei Yukawa930328c2017-10-18 20:19:53 -0700178 @BinderThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 public void setExtractedText(ExtractedText extractedText, int seq) {
180 synchronized (this) {
181 if (seq == mSeq) {
182 mExtractedText = extractedText;
183 mHaveValue = true;
184 notifyAll();
185 } else {
186 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
187 + ") in setExtractedText, ignoring.");
188 }
189 }
190 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900191
Yohei Yukawa930328c2017-10-18 20:19:53 -0700192 @BinderThread
Yohei Yukawaa277db22014-08-21 18:38:44 -0700193 public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900194 synchronized (this) {
195 if (seq == mSeq) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700196 mRequestUpdateCursorAnchorInfoResult = result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900197 mHaveValue = true;
198 notifyAll();
199 } else {
200 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
201 + ") in setCursorAnchorInfoRequestResult, ignoring.");
202 }
203 }
204 }
205
Yohei Yukawa930328c2017-10-18 20:19:53 -0700206 @BinderThread
Yohei Yukawaadebb522016-06-17 10:10:39 -0700207 public void setCommitContentResult(boolean result, int seq) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700208 synchronized (this) {
209 if (seq == mSeq) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700210 mCommitContentResult = result;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700211 mHaveValue = true;
212 notifyAll();
213 } else {
214 Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
Yohei Yukawaadebb522016-06-17 10:10:39 -0700215 + ") in setCommitContentResult, ignoring.");
Yohei Yukawa152944f2016-06-10 19:04:34 -0700216 }
217 }
218 }
219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 /**
221 * Waits for a result for up to {@link #MAX_WAIT_TIME_MILLIS} milliseconds.
222 *
223 * <p>The caller must be synchronized on this callback object.
224 */
Yohei Yukawa930328c2017-10-18 20:19:53 -0700225 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 void waitForResultLocked() {
227 long startTime = SystemClock.uptimeMillis();
228 long endTime = startTime + MAX_WAIT_TIME_MILLIS;
229
230 while (!mHaveValue) {
231 long remainingTime = endTime - SystemClock.uptimeMillis();
232 if (remainingTime <= 0) {
233 Log.w(TAG, "Timed out waiting on IInputContextCallback");
234 return;
235 }
236 try {
237 wait(remainingTime);
238 } catch (InterruptedException e) {
239 }
240 }
241 }
242 }
243
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700244 public InputConnectionWrapper(
245 @NonNull WeakReference<AbstractInputMethodService> inputMethodService,
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700246 IInputContext inputContext, @MissingMethodFlags final int missingMethods,
247 @NonNull AtomicBoolean isUnbindIssued) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700248 mInputMethodService = inputMethodService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 mIInputContext = inputContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700250 mMissingMethods = missingMethods;
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700251 mIsUnbindIssued = isUnbindIssued;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 }
253
Yohei Yukawa930328c2017-10-18 20:19:53 -0700254 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 public CharSequence getTextAfterCursor(int length, int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700256 if (mIsUnbindIssued.get()) {
257 return null;
258 }
259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 CharSequence value = null;
261 try {
262 InputContextCallback callback = InputContextCallback.getInstance();
263 mIInputContext.getTextAfterCursor(length, flags, callback.mSeq, callback);
264 synchronized (callback) {
265 callback.waitForResultLocked();
266 if (callback.mHaveValue) {
267 value = callback.mTextAfterCursor;
268 }
269 }
270 callback.dispose();
271 } catch (RemoteException e) {
272 return null;
273 }
274 return value;
275 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700276
277 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 public CharSequence getTextBeforeCursor(int length, int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700279 if (mIsUnbindIssued.get()) {
280 return null;
281 }
282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 CharSequence value = null;
284 try {
285 InputContextCallback callback = InputContextCallback.getInstance();
286 mIInputContext.getTextBeforeCursor(length, flags, callback.mSeq, callback);
287 synchronized (callback) {
288 callback.waitForResultLocked();
289 if (callback.mHaveValue) {
290 value = callback.mTextBeforeCursor;
291 }
292 }
293 callback.dispose();
294 } catch (RemoteException e) {
295 return null;
296 }
297 return value;
298 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700299
Yohei Yukawa930328c2017-10-18 20:19:53 -0700300 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700301 public CharSequence getSelectedText(int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700302 if (mIsUnbindIssued.get()) {
303 return null;
304 }
305
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700306 if (isMethodMissing(MissingMethodFlags.GET_SELECTED_TEXT)) {
307 // This method is not implemented.
308 return null;
309 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700310 CharSequence value = null;
311 try {
312 InputContextCallback callback = InputContextCallback.getInstance();
313 mIInputContext.getSelectedText(flags, callback.mSeq, callback);
314 synchronized (callback) {
315 callback.waitForResultLocked();
316 if (callback.mHaveValue) {
317 value = callback.mSelectedText;
318 }
319 }
320 callback.dispose();
321 } catch (RemoteException e) {
322 return null;
323 }
324 return value;
325 }
326
Yohei Yukawa930328c2017-10-18 20:19:53 -0700327 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 public int getCursorCapsMode(int reqModes) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700329 if (mIsUnbindIssued.get()) {
330 return 0;
331 }
332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 int value = 0;
334 try {
335 InputContextCallback callback = InputContextCallback.getInstance();
336 mIInputContext.getCursorCapsMode(reqModes, callback.mSeq, callback);
337 synchronized (callback) {
338 callback.waitForResultLocked();
339 if (callback.mHaveValue) {
340 value = callback.mCursorCapsMode;
341 }
342 }
343 callback.dispose();
344 } catch (RemoteException e) {
345 return 0;
346 }
347 return value;
348 }
satoke3797a12011-03-22 06:34:48 +0900349
Yohei Yukawa930328c2017-10-18 20:19:53 -0700350 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700352 if (mIsUnbindIssued.get()) {
353 return null;
354 }
355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 ExtractedText value = null;
357 try {
358 InputContextCallback callback = InputContextCallback.getInstance();
359 mIInputContext.getExtractedText(request, flags, callback.mSeq, callback);
360 synchronized (callback) {
361 callback.waitForResultLocked();
362 if (callback.mHaveValue) {
363 value = callback.mExtractedText;
364 }
365 }
366 callback.dispose();
367 } catch (RemoteException e) {
368 return null;
369 }
370 return value;
371 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700372
373 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 public boolean commitText(CharSequence text, int newCursorPosition) {
375 try {
376 mIInputContext.commitText(text, newCursorPosition);
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700377 notifyUserActionIfNecessary();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 return true;
379 } catch (RemoteException e) {
380 return false;
381 }
382 }
383
Yohei Yukawa930328c2017-10-18 20:19:53 -0700384 @AnyThread
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700385 private void notifyUserActionIfNecessary() {
386 final AbstractInputMethodService inputMethodService = mInputMethodService.get();
387 if (inputMethodService == null) {
388 // This basically should not happen, because it's the the caller of this method.
389 return;
390 }
391 inputMethodService.notifyUserActionIfNecessary();
392 }
393
394 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 public boolean commitCompletion(CompletionInfo text) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700396 if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
397 // This method is not implemented.
398 return false;
399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 try {
401 mIInputContext.commitCompletion(text);
402 return true;
403 } catch (RemoteException e) {
404 return false;
405 }
406 }
407
Yohei Yukawa930328c2017-10-18 20:19:53 -0700408 @AnyThread
Gilles Debunnecf9cf2f2010-12-08 17:43:58 -0800409 public boolean commitCorrection(CorrectionInfo correctionInfo) {
410 try {
411 mIInputContext.commitCorrection(correctionInfo);
412 return true;
413 } catch (RemoteException e) {
414 return false;
415 }
416 }
417
Yohei Yukawa930328c2017-10-18 20:19:53 -0700418 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 public boolean setSelection(int start, int end) {
420 try {
421 mIInputContext.setSelection(start, end);
422 return true;
423 } catch (RemoteException e) {
424 return false;
425 }
426 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700427
428 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 public boolean performEditorAction(int actionCode) {
430 try {
431 mIInputContext.performEditorAction(actionCode);
432 return true;
433 } catch (RemoteException e) {
434 return false;
435 }
436 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700437
438 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 public boolean performContextMenuAction(int id) {
440 try {
441 mIInputContext.performContextMenuAction(id);
442 return true;
443 } catch (RemoteException e) {
444 return false;
445 }
446 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700447
Yohei Yukawa930328c2017-10-18 20:19:53 -0700448 @AnyThread
Amith Yamasania90b7f02010-08-25 18:27:20 -0700449 public boolean setComposingRegion(int start, int end) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700450 if (isMethodMissing(MissingMethodFlags.SET_COMPOSING_REGION)) {
451 // This method is not implemented.
452 return false;
453 }
Amith Yamasania90b7f02010-08-25 18:27:20 -0700454 try {
455 mIInputContext.setComposingRegion(start, end);
456 return true;
457 } catch (RemoteException e) {
458 return false;
459 }
460 }
461
Yohei Yukawa930328c2017-10-18 20:19:53 -0700462 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 public boolean setComposingText(CharSequence text, int newCursorPosition) {
464 try {
465 mIInputContext.setComposingText(text, newCursorPosition);
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700466 notifyUserActionIfNecessary();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 return true;
468 } catch (RemoteException e) {
469 return false;
470 }
471 }
472
Yohei Yukawa930328c2017-10-18 20:19:53 -0700473 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 public boolean finishComposingText() {
475 try {
476 mIInputContext.finishComposingText();
477 return true;
478 } catch (RemoteException e) {
479 return false;
480 }
481 }
482
Yohei Yukawa930328c2017-10-18 20:19:53 -0700483 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 public boolean beginBatchEdit() {
485 try {
486 mIInputContext.beginBatchEdit();
487 return true;
488 } catch (RemoteException e) {
489 return false;
490 }
491 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700492
493 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 public boolean endBatchEdit() {
495 try {
496 mIInputContext.endBatchEdit();
497 return true;
498 } catch (RemoteException e) {
499 return false;
500 }
501 }
Yohei Yukawa930328c2017-10-18 20:19:53 -0700502
503 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 public boolean sendKeyEvent(KeyEvent event) {
505 try {
506 mIInputContext.sendKeyEvent(event);
Yohei Yukawac07fd4c2018-09-11 11:37:13 -0700507 notifyUserActionIfNecessary();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 return true;
509 } catch (RemoteException e) {
510 return false;
511 }
512 }
513
Yohei Yukawa930328c2017-10-18 20:19:53 -0700514 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 public boolean clearMetaKeyStates(int states) {
516 try {
517 mIInputContext.clearMetaKeyStates(states);
518 return true;
519 } catch (RemoteException e) {
520 return false;
521 }
522 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800523
Yohei Yukawa930328c2017-10-18 20:19:53 -0700524 @AnyThread
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800525 public boolean deleteSurroundingText(int beforeLength, int afterLength) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 try {
Fabrice Di Meglio0c95dd32012-01-23 15:06:42 -0800527 mIInputContext.deleteSurroundingText(beforeLength, afterLength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 return true;
529 } catch (RemoteException e) {
530 return false;
531 }
532 }
533
Yohei Yukawa930328c2017-10-18 20:19:53 -0700534 @AnyThread
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800535 public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700536 if (isMethodMissing(MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS)) {
537 // This method is not implemented.
538 return false;
539 }
Yohei Yukawac89e22a2016-01-13 22:48:14 -0800540 try {
541 mIInputContext.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
542 return true;
543 } catch (RemoteException e) {
544 return false;
545 }
546 }
547
Yohei Yukawa930328c2017-10-18 20:19:53 -0700548 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 public boolean reportFullscreenMode(boolean enabled) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800550 // Nothing should happen when called from input method.
551 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 }
553
Yohei Yukawa930328c2017-10-18 20:19:53 -0700554 @AnyThread
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 public boolean performPrivateCommand(String action, Bundle data) {
556 try {
557 mIInputContext.performPrivateCommand(action, data);
558 return true;
559 } catch (RemoteException e) {
560 return false;
561 }
562 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900563
Yohei Yukawa930328c2017-10-18 20:19:53 -0700564 @AnyThread
Yohei Yukawad8636ea2014-09-02 22:03:30 -0700565 public boolean requestCursorUpdates(int cursorUpdateMode) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700566 if (mIsUnbindIssued.get()) {
567 return false;
568 }
569
Yohei Yukawaa277db22014-08-21 18:38:44 -0700570 boolean result = false;
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700571 if (isMethodMissing(MissingMethodFlags.REQUEST_CURSOR_UPDATES)) {
572 // This method is not implemented.
573 return false;
574 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900575 try {
576 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawaa277db22014-08-21 18:38:44 -0700577 mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900578 synchronized (callback) {
579 callback.waitForResultLocked();
580 if (callback.mHaveValue) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700581 result = callback.mRequestUpdateCursorAnchorInfoResult;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900582 }
583 }
584 callback.dispose();
585 } catch (RemoteException e) {
Yohei Yukawaa277db22014-08-21 18:38:44 -0700586 return false;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900587 }
Yohei Yukawaa277db22014-08-21 18:38:44 -0700588 return result;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900589 }
Yohei Yukawa612cce92016-02-11 17:47:33 -0800590
Yohei Yukawa930328c2017-10-18 20:19:53 -0700591 @AnyThread
Yohei Yukawa612cce92016-02-11 17:47:33 -0800592 public Handler getHandler() {
593 // Nothing should happen when called from input method.
594 return null;
595 }
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700596
Yohei Yukawa930328c2017-10-18 20:19:53 -0700597 @AnyThread
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700598 public void closeConnection() {
599 // Nothing should happen when called from input method.
600 }
601
Yohei Yukawa930328c2017-10-18 20:19:53 -0700602 @AnyThread
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700603 public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
Tarandeep Singh1d113d02017-10-13 10:51:00 -0700604 if (mIsUnbindIssued.get()) {
605 return false;
606 }
607
Yohei Yukawa152944f2016-06-10 19:04:34 -0700608 boolean result = false;
Yohei Yukawaadebb522016-06-17 10:10:39 -0700609 if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
Yohei Yukawa152944f2016-06-10 19:04:34 -0700610 // This method is not implemented.
611 return false;
612 }
613 try {
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000614 if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700615 final AbstractInputMethodService inputMethodService = mInputMethodService.get();
616 if (inputMethodService == null) {
617 // This basically should not happen, because it's the the caller of this method.
618 return false;
619 }
620 inputMethodService.exposeContent(inputContentInfo, this);
621 }
Yohei Yukawa79d1c752016-06-30 19:24:04 +0000622
Yohei Yukawa152944f2016-06-10 19:04:34 -0700623 InputContextCallback callback = InputContextCallback.getInstance();
Yohei Yukawa45700fa2016-06-23 17:12:59 -0700624 mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
Yohei Yukawa152944f2016-06-10 19:04:34 -0700625 synchronized (callback) {
626 callback.waitForResultLocked();
627 if (callback.mHaveValue) {
Yohei Yukawaadebb522016-06-17 10:10:39 -0700628 result = callback.mCommitContentResult;
Yohei Yukawa152944f2016-06-10 19:04:34 -0700629 }
630 }
631 callback.dispose();
632 } catch (RemoteException e) {
633 return false;
634 }
635 return result;
636 }
637
Yohei Yukawa930328c2017-10-18 20:19:53 -0700638 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700639 private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) {
640 return (mMissingMethods & methodFlag) == methodFlag;
641 }
642
Yohei Yukawa930328c2017-10-18 20:19:53 -0700643 @AnyThread
Yohei Yukawa19a80a12016-03-14 22:57:37 -0700644 @Override
645 public String toString() {
646 return "InputConnectionWrapper{idHash=#"
647 + Integer.toHexString(System.identityHashCode(this))
648 + " mMissingMethods="
649 + InputConnectionInspector.getMissingMethodFlagsAsString(mMissingMethods) + "}";
650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651}