blob: d302c2b082176e6253cba7218aa9ecb971042a6e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007-2008 The Android Open Source Project
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07003 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07007 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008 * http://www.apache.org/licenses/LICENSE-2.0
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07009 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.view.inputmethod;
18
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080019import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070020import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
Gilles Debunne8cbb4c62011-01-24 12:33:56 -080021
Yohei Yukawa41b094f2018-09-09 23:58:45 -070022import android.annotation.DrawableRes;
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -080023import android.annotation.NonNull;
24import android.annotation.Nullable;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070025import android.annotation.RequiresFeature;
Yoshiki Iguchi00d51222015-05-29 15:36:22 +090026import android.annotation.RequiresPermission;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060027import android.annotation.SystemService;
Tarandeep Singheb570612018-01-29 16:20:32 -080028import android.annotation.TestApi;
Mathew Inwooda570dee2018-08-17 14:56:00 +010029import android.annotation.UnsupportedAppUsage;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080030import android.annotation.UserIdInt;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080031import android.app.ActivityThread;
Yohei Yukawafd8f7212019-01-22 19:25:44 -080032import android.content.ComponentName;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080033import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.Context;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070035import android.content.pm.PackageManager;
Yohei Yukawab4f328a2019-05-02 08:41:27 -070036import android.graphics.Matrix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.graphics.Rect;
Tarandeep Singhd8d03a82017-11-28 13:35:32 -080038import android.inputmethodservice.InputMethodService;
Yohei Yukawacb768bc2018-10-24 16:05:09 -070039import android.os.Binder;
Yohei Yukawaa086f952018-09-11 11:37:08 -070040import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.os.Bundle;
42import android.os.Handler;
43import android.os.IBinder;
44import android.os.Looper;
45import android.os.Message;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080046import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.RemoteException;
The Android Open Source Project4df24232009-03-05 14:34:35 -080048import android.os.ResultReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060050import android.os.ServiceManager.ServiceNotFoundException;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070051import android.os.Trace;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080052import android.os.UserHandle;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080053import android.provider.Settings;
satokf9f01002011-05-19 21:31:50 +090054import android.text.style.SuggestionSpan;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.util.Log;
Jeff Brownf9e989d2013-04-04 23:04:03 -070056import android.util.Pools.Pool;
57import android.util.Pools.SimplePool;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.util.PrintWriterPrinter;
59import android.util.Printer;
Yohei Yukawab7b79072014-03-25 11:02:00 +090060import android.util.SparseArray;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +080061import android.view.Display;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -080062import android.view.ImeInsetsSourceConsumer;
Jeff Brownc28867a2013-03-26 15:42:39 -070063import android.view.InputChannel;
64import android.view.InputEvent;
65import android.view.InputEventSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.view.KeyEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.view.View;
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070068import android.view.ViewRootImpl;
Yohei Yukawa22dac1c2017-02-12 16:54:16 -080069import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
Dake Guddf6c1e2018-05-10 11:41:19 -070070import android.view.autofill.AutofillManager;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070071
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -070072import com.android.internal.annotations.GuardedBy;
Yohei Yukawaa468d702018-10-21 11:42:34 -070073import com.android.internal.inputmethod.InputMethodDebug;
Yohei Yukawaeec552e2018-09-09 20:48:41 -070074import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
Yohei Yukawa35fa6d52018-10-31 11:33:32 -070075import com.android.internal.inputmethod.StartInputFlags;
Yohei Yukawac6632df2018-10-21 11:47:16 -070076import com.android.internal.inputmethod.StartInputReason;
Yohei Yukawa499e3f72018-10-21 20:15:11 -070077import com.android.internal.inputmethod.UnbindReason;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070078import com.android.internal.os.SomeArgs;
79import com.android.internal.view.IInputConnectionWrapper;
80import com.android.internal.view.IInputContext;
81import com.android.internal.view.IInputMethodClient;
82import com.android.internal.view.IInputMethodManager;
83import com.android.internal.view.IInputMethodSession;
84import com.android.internal.view.InputBindResult;
Gilles Debunned4723bb2010-09-02 15:27:32 -070085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import java.io.FileDescriptor;
87import java.io.PrintWriter;
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -070088import java.lang.reflect.Proxy;
Andreas Gampee6748ce2015-12-11 18:00:38 -080089import java.util.Arrays;
Yohei Yukawafefedc52018-12-24 19:43:17 -080090import java.util.Collections;
91import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import java.util.List;
satokf3db1af2010-11-23 13:34:33 +090093import java.util.Map;
Yohei Yukawac941fed2014-05-14 19:33:35 +090094import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import java.util.concurrent.CountDownLatch;
96import java.util.concurrent.TimeUnit;
97
98/**
99 * Central system API to the overall input method framework (IMF) architecture,
100 * which arbitrates interaction between applications and the current input method.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700101 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 * <p>Topics covered here:
103 * <ol>
104 * <li><a href="#ArchitectureOverview">Architecture Overview</a>
Ken Wakasa384f8ba2012-03-10 09:59:31 +0900105 * <li><a href="#Applications">Applications</a>
106 * <li><a href="#InputMethods">Input Methods</a>
107 * <li><a href="#Security">Security</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 * </ol>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700109 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 * <a name="ArchitectureOverview"></a>
111 * <h3>Architecture Overview</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700112 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 * <p>There are three primary parties involved in the input method
114 * framework (IMF) architecture:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700115 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 * <ul>
117 * <li> The <strong>input method manager</strong> as expressed by this class
118 * is the central point of the system that manages interaction between all
119 * other parts. It is expressed as the client-side API here which exists
120 * in each application context and communicates with a global system service
121 * that manages the interaction across all processes.
122 * <li> An <strong>input method (IME)</strong> implements a particular
123 * interaction model allowing the user to generate text. The system binds
Nick Felker8efc3ee2017-06-26 15:50:19 -0700124 * to the current input method that is in use, causing it to be created and run,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 * and tells it when to hide and show its UI. Only one IME is running at a time.
126 * <li> Multiple <strong>client applications</strong> arbitrate with the input
127 * method manager for input focus and control over the state of the IME. Only
128 * one such client is ever active (working with the IME) at a time.
129 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700130 *
131 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 * <a name="Applications"></a>
133 * <h3>Applications</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700134 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 * <p>In most cases, applications that are using the standard
136 * {@link android.widget.TextView} or its subclasses will have little they need
137 * to do to work well with soft input methods. The main things you need to
138 * be aware of are:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700139 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 * <ul>
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800141 * <li> Properly set the {@link android.R.attr#inputType} in your editable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 * text views, so that the input method will have enough context to help the
143 * user in entering text into them.
144 * <li> Deal well with losing screen space when the input method is
145 * displayed. Ideally an application should handle its window being resized
146 * smaller, but it can rely on the system performing panning of the window
147 * if needed. You should set the {@link android.R.attr#windowSoftInputMode}
148 * attribute on your activity or the corresponding values on windows you
149 * create to help the system determine whether to pan or resize (it will
150 * try to determine this automatically but may get it wrong).
151 * <li> You can also control the preferred soft input state (open, closed, etc)
152 * for your window using the same {@link android.R.attr#windowSoftInputMode}
153 * attribute.
154 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700155 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 * <p>More finer-grained control is available through the APIs here to directly
157 * interact with the IMF and its IME -- either showing or hiding the input
158 * area, letting the user pick an input method, etc.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700159 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 * <p>For the rare people amongst us writing their own text editors, you
161 * will need to implement {@link android.view.View#onCreateInputConnection}
162 * to return a new instance of your own {@link InputConnection} interface
163 * allowing the IME to interact with your editor.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700164 *
165 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 * <a name="InputMethods"></a>
167 * <h3>Input Methods</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700168 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 * <p>An input method (IME) is implemented
170 * as a {@link android.app.Service}, typically deriving from
171 * {@link android.inputmethodservice.InputMethodService}. It must provide
172 * the core {@link InputMethod} interface, though this is normally handled by
173 * {@link android.inputmethodservice.InputMethodService} and implementors will
174 * only need to deal with the higher-level API there.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700175 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 * See the {@link android.inputmethodservice.InputMethodService} class for
177 * more information on implementing IMEs.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700178 *
179 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 * <a name="Security"></a>
181 * <h3>Security</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700182 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 * <p>There are a lot of security issues associated with input methods,
184 * since they essentially have freedom to completely drive the UI and monitor
185 * everything the user enters. The Android input method framework also allows
186 * arbitrary third party IMEs, so care must be taken to restrict their
187 * selection and interactions.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700188 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 * <p>Here are some key points about the security architecture behind the
190 * IMF:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700191 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 * <ul>
193 * <li> <p>Only the system is allowed to directly access an IME's
194 * {@link InputMethod} interface, via the
195 * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission. This is
196 * enforced in the system by not binding to an input method service that does
197 * not require this permission, so the system can guarantee no other untrusted
198 * clients are accessing the current input method outside of its control.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700199 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 * <li> <p>There may be many client processes of the IMF, but only one may
201 * be active at a time. The inactive clients can not interact with key
202 * parts of the IMF through the mechanisms described below.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700203 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 * <li> <p>Clients of an input method are only given access to its
205 * {@link InputMethodSession} interface. One instance of this interface is
206 * created for each client, and only calls from the session associated with
207 * the active client will be processed by the current IME. This is enforced
208 * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
209 * IMEs, but must be explicitly handled by an IME that is customizing the
210 * raw {@link InputMethodSession} implementation.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700211 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 * <li> <p>Only the active client's {@link InputConnection} will accept
213 * operations. The IMF tells each client process whether it is active, and
214 * the framework enforces that in inactive processes calls on to the current
215 * InputConnection will be ignored. This ensures that the current IME can
216 * only deliver events and text edits to the UI that the user sees as
217 * being in focus.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700218 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 * <li> <p>An IME can never interact with an {@link InputConnection} while
220 * the screen is off. This is enforced by making all clients inactive while
221 * the screen is off, and prevents bad IMEs from driving the UI when the user
222 * can not be aware of its behavior.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700223 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * <li> <p>A client application can ask that the system let the user pick a
225 * new IME, but can not programmatically switch to one itself. This avoids
226 * malicious applications from switching the user to their own IME, which
227 * remains running when the user navigates away to another application. An
228 * IME, on the other hand, <em>is</em> allowed to programmatically switch
229 * the system to another IME, since it already has full control of user
230 * input.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700231 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 * <li> <p>The user must explicitly enable a new IME in settings before
233 * they can switch to it, to confirm with the system that they know about it
234 * and want to make it available for use.</p>
235 * </ul>
236 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600237@SystemService(Context.INPUT_METHOD_SERVICE)
Jeff Sharkey98af2e42018-02-16 10:14:57 -0700238@RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239public final class InputMethodManager {
Dianne Hackborn4eba2712009-03-24 19:20:06 -0700240 static final boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 static final String TAG = "InputMethodManager";
242
Jeff Brownf9e989d2013-04-04 23:04:03 -0700243 static final String PENDING_EVENT_COUNTER = "aq:imm";
244
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -0800245 private static final int NOT_A_SUBTYPE_ID = -1;
246
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700247 /**
Yohei Yukawafefedc52018-12-24 19:43:17 -0800248 * A constant that represents Voice IME.
249 *
250 * @see InputMethodSubtype#getMode()
251 */
252 private static final String SUBTYPE_MODE_VOICE = "voice";
253
254 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700255 * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
256 * or indirectly relied on {@link #sInstance} via reflection or something like that.
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700257 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700258 * <p>Here are scenarios we know and there could be more scenarios we are not
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700259 * aware of right know.</p>
260 *
261 * <ul>
262 * <li>Apps that directly access {@link #sInstance} via reflection, which is currently
263 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
264 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
265 * {@link #sInstance} is not {@code null} when such an app is accessing it, but removing
266 * that code from {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal
267 * untested code paths in their apps, which probably happen in an early startup time of that
268 * app.</li>
269 * <li>Apps that directly access {@link #peekInstance()} via reflection, which is currently
270 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
271 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
272 * {@link #peekInstance()} returns non-{@code null} object when such an app is calling
273 * {@link #peekInstance()}, but removing that code from
274 * {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal untested code
275 * paths in their apps, which probably happen in an early startup time of that app. The good
276 * news is that unlike {@link #sInstance}'s case we can at least work around this scenario
277 * by changing the semantics of {@link #peekInstance()}, which is currently defined as
278 * "retrieve the global {@link InputMethodManager} instance, if it exists" to something that
279 * always returns non-{@code null} {@link InputMethodManager}. However, introducing such an
280 * workaround can also trigger different compatibility issues if {@link #peekInstance()} was
281 * called before {@link android.view.WindowManagerGlobal#getWindowSession()} and it expected
282 * {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li>
283 * </ul>
284 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700285 * <p>Since this is purely a compatibility hack, this method must be used only from
286 * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p>
287 *
288 * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p>
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700289 * @hide
290 */
Yohei Yukawa6c075722018-09-21 14:52:12 -0700291 public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800292 forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
Yohei Yukawa6c075722018-09-21 14:52:12 -0700293 }
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700294
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700295 private static final Object sLock = new Object();
296
Yohei Yukawa6c075722018-09-21 14:52:12 -0700297 /**
298 * @deprecated This cannot be compatible with multi-display. Please do not use this.
299 */
300 @Deprecated
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700301 @GuardedBy("sLock")
Mathew Inwooda570dee2018-08-17 14:56:00 +0100302 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -0700303 static InputMethodManager sInstance;
Dianne Hackborn7663d802012-02-24 13:08:49 -0800304
305 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800306 * Global map between display to {@link InputMethodManager}.
307 *
308 * <p>Currently this map works like a so-called leaky singleton. Once an instance is registered
309 * for the associated display ID, that instance will never be garbage collected.</p>
310 *
311 * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
312 */
313 @GuardedBy("sLock")
314 private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
315
316 /**
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700317 * Timeout in milliseconds for delivering a key to an IME.
318 */
319 static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
320
Jeff Brownf9e989d2013-04-04 23:04:03 -0700321 /** @hide */
322 public static final int DISPATCH_IN_PROGRESS = -1;
323
324 /** @hide */
325 public static final int DISPATCH_NOT_HANDLED = 0;
326
327 /** @hide */
328 public static final int DISPATCH_HANDLED = 1;
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700329
Seigo Nonaka14e13912015-05-06 21:04:13 -0700330 /** @hide */
331 public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
332 /** @hide */
333 public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
334 /** @hide */
335 public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
336
Mathew Inwooda570dee2018-08-17 14:56:00 +0100337 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 final IInputMethodManager mService;
339 final Looper mMainLooper;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 // For scheduling work on the main thread. This also serves as our
342 // global lock.
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000343 // Remark on @UnsupportedAppUsage: there were context leaks on old versions
344 // of android (b/37043700), so developers used this field to perform manual clean up.
345 // Leaks were fixed, hacks were backported to AppCompatActivity,
346 // so an access to the field is closed.
347 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 final H mH;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 // Our generic input connection if the current target does not have its own.
351 final IInputContext mIInputContext;
352
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800353 private final int mDisplayId;
354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 /**
356 * True if this input method client is active, initially false.
357 */
358 boolean mActive = false;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 /**
Yohei Yukawa2553e482017-12-15 15:47:33 -0800361 * {@code true} if next {@link #onPostWindowFocus(View, View, int, boolean, int)} needs to
362 * restart input.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 */
Yohei Yukawa2553e482017-12-15 15:47:33 -0800364 boolean mRestartOnNextWindowFocus = true;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 /**
367 * As reported by IME through InputConnection.
368 */
369 boolean mFullscreenMode;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700372
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700373 /**
374 * This is the root view of the overall window that currently has input
375 * method focus.
376 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100377 @UnsupportedAppUsage
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700378 View mCurRootView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 /**
380 * This is the view that should currently be served by an input method,
381 * regardless of the state of setting that up.
382 */
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000383 // See comment to mH field in regard to @UnsupportedAppUsage
384 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 View mServedView;
386 /**
387 * This is then next view that will be served by the input method, when
388 * we get around to updating things.
389 */
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000390 // See comment to mH field in regard to @UnsupportedAppUsage
391 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 View mNextServedView;
393 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 * This is set when we are in the process of connecting, to determine
395 * when we have actually finished.
396 */
397 boolean mServedConnecting;
398 /**
399 * This is non-null when we have connected the served view; it holds
400 * the attributes that were last retrieved from the served view and given
401 * to the input connection.
402 */
403 EditorInfo mCurrentTextBoxAttribute;
404 /**
405 * The InputConnection that was last retrieved from the served view.
406 */
Mathew Inwood8c854f82018-09-14 12:35:36 +0100407 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackbornac920872012-05-22 11:49:49 -0700408 ControlledInputConnectionWrapper mServedInputConnectionWrapper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 /**
410 * The completions that were last provided by the served view.
411 */
412 CompletionInfo[] mCompletions;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 // Cursor position on the screen.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100415 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -0700416 Rect mTmpCursorRect = new Rect();
Mathew Inwooda570dee2018-08-17 14:56:00 +0100417 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 Rect mCursorRect = new Rect();
419 int mCursorSelStart;
420 int mCursorSelEnd;
421 int mCursorCandStart;
422 int mCursorCandEnd;
Yohei Yukawa056ffe62014-05-13 14:26:09 +0900423
424 /**
425 * The instance that has previously been sent to the input method.
426 */
427 private CursorAnchorInfo mCursorAnchorInfo = null;
428
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700429 /**
430 * A special {@link Matrix} that can be provided by the system when this instance is running
431 * inside a virtual display that is managed by {@link android.app.ActivityView}.
432 *
433 * <p>If this is non-{@code null}, {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}
434 * should be adjusted with this {@link Matrix}.</p>
435 *
436 * <p>{@code null} when not used.</p>
437 */
438 private Matrix mActivityViewToScreenMatrix = null;
439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 // -----------------------------------------------------------
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 /**
443 * Sequence number of this binding, as returned by the server.
444 */
445 int mBindSequence = -1;
446 /**
447 * ID of the method we are bound to.
448 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100449 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 String mCurId;
451 /**
452 * The actual instance of the method to make calls on it.
453 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100454 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 IInputMethodSession mCurMethod;
Jeff Brownc28867a2013-03-26 15:42:39 -0700456 InputChannel mCurChannel;
457 ImeInputEventSender mCurSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458
Yohei Yukawaa277db22014-08-21 18:38:44 -0700459 private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900460
461 /**
462 * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
463 */
Yohei Yukawaa277db22014-08-21 18:38:44 -0700464 private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawab7b79072014-03-25 11:02:00 +0900465
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800466 /**
467 * When {@link ViewRootImpl#sNewInsetsMode} is set to
468 * >= {@link ViewRootImpl#NEW_INSETS_MODE_IME}, {@link ImeInsetsSourceConsumer} applies the
469 * IME visibility and listens for other state changes.
470 */
471 private ImeInsetsSourceConsumer mImeInsetsConsumer;
472
Yohei Yukawab0377bb2015-08-10 21:06:30 -0700473 final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
474 final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 static final int MSG_DUMP = 1;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800479 static final int MSG_BIND = 2;
480 static final int MSG_UNBIND = 3;
481 static final int MSG_SET_ACTIVE = 4;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700482 static final int MSG_SEND_INPUT_EVENT = 5;
483 static final int MSG_TIMEOUT_INPUT_EVENT = 6;
484 static final int MSG_FLUSH_INPUT_EVENT = 7;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800485 static final int MSG_REPORT_FULLSCREEN_MODE = 10;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800486 static final int MSG_REPORT_PRE_RENDERED = 15;
487 static final int MSG_APPLY_IME_VISIBILITY = 20;
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700488 static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700489
Dake Guddf6c1e2018-05-10 11:41:19 -0700490 private static boolean isAutofillUIShowing(View servedView) {
491 AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
492 return afm != null && afm.isAutofillUiShowing();
493 }
494
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800495 /**
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700496 * Returns fallback {@link InputMethodManager} if the called one is not likely to be compatible
497 * with the given {@code view}.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800498 *
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700499 * @param view {@link View} to be checked.
500 * @return {@code null} when it is unnecessary (or impossible) to use fallback
501 * {@link InputMethodManager} to which IME API calls need to be re-dispatched.
502 * Non-{@code null} {@link InputMethodManager} if this method believes it'd be safer to
503 * re-dispatch IME APIs calls on it.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800504 */
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700505 @Nullable
506 private InputMethodManager getFallbackInputMethodManagerIfNecessary(@Nullable View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800507 if (view == null) {
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700508 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800509 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700510 // As evidenced in Bug 118341760, view.getViewRootImpl().getDisplayId() is supposed to be
511 // more reliable to determine with which display the given view is interacting than
512 // view.getContext().getDisplayId() / view.getContext().getSystemService(), which can be
513 // easily messed up by app developers (or library authors) by creating inconsistent
514 // ContextWrapper objects that re-dispatch those methods to other Context such as
515 // ApplicationContext.
516 final ViewRootImpl viewRootImpl = view.getViewRootImpl();
517 if (viewRootImpl == null) {
518 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800519 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700520 final int viewRootDisplayId = viewRootImpl.getDisplayId();
521 if (viewRootDisplayId == mDisplayId) {
522 // Expected case. Good to go.
523 return null;
524 }
525 final InputMethodManager fallbackImm =
Charles Chen5299ad02019-04-18 13:09:53 +0000526 viewRootImpl.mContext.getSystemService(InputMethodManager.class);
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700527 if (fallbackImm == null) {
528 Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
529 return null;
530 }
531 if (fallbackImm.mDisplayId != viewRootDisplayId) {
532 Log.e(TAG, "b/117267690: Failed to get fallback IMM with expected displayId="
533 + viewRootDisplayId + " actual IMM#displayId=" + fallbackImm.mDisplayId
534 + " view=" + view);
535 return null;
536 }
537 Log.w(TAG, "b/117267690: Display ID mismatch found."
538 + " ViewRootImpl displayId=" + viewRootDisplayId
539 + " InputMethodManager displayId=" + mDisplayId
540 + ". Use the right InputMethodManager instance to avoid performance overhead.",
541 new Throwable());
542 return fallbackImm;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800543 }
544
Dake Guddf6c1e2018-05-10 11:41:19 -0700545 private static boolean canStartInput(View servedView) {
546 // We can start input ether the servedView has window focus
547 // or the activity is showing autofill ui.
548 return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
549 }
550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 class H extends Handler {
552 H(Looper looper) {
Jeff Brown29c0ed22013-01-14 13:50:37 -0800553 super(looper, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 @Override
557 public void handleMessage(Message msg) {
558 switch (msg.what) {
559 case MSG_DUMP: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700560 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 try {
562 doDump((FileDescriptor)args.arg1,
563 (PrintWriter)args.arg2, (String[])args.arg3);
564 } catch (RuntimeException e) {
565 ((PrintWriter)args.arg2).println("Exception: " + e);
566 }
567 synchronized (args.arg4) {
568 ((CountDownLatch)args.arg4).countDown();
569 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700570 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 return;
572 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800573 case MSG_BIND: {
574 final InputBindResult res = (InputBindResult)msg.obj;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900575 if (DEBUG) {
576 Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
577 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800578 synchronized (mH) {
579 if (mBindSequence < 0 || mBindSequence != res.sequence) {
580 Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
581 + ", given seq=" + res.sequence);
Jeff Brown4d656882013-04-03 14:39:19 -0700582 if (res.channel != null && res.channel != mCurChannel) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700583 res.channel.dispose();
584 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800585 return;
586 }
Jeff Brown4d656882013-04-03 14:39:19 -0700587
Yohei Yukawaa277db22014-08-21 18:38:44 -0700588 mRequestUpdateCursorAnchorInfoMonitorMode =
589 REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900590
Jeff Brown4d656882013-04-03 14:39:19 -0700591 setInputChannelLocked(res.channel);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800592 mCurMethod = res.method;
593 mCurId = res.id;
594 mBindSequence = res.sequence;
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700595 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800596 }
Yohei Yukawa42194222018-10-21 20:14:40 -0700597 startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800598 return;
599 }
600 case MSG_UNBIND: {
601 final int sequence = msg.arg1;
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700602 @UnbindReason
Yohei Yukawa33e81792015-11-17 21:14:42 -0800603 final int reason = msg.arg2;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900604 if (DEBUG) {
Yohei Yukawa33e81792015-11-17 21:14:42 -0800605 Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
Yohei Yukawaa468d702018-10-21 11:42:34 -0700606 " reason=" + InputMethodDebug.unbindReasonToString(reason));
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900607 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800608 final boolean startInput;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800609 synchronized (mH) {
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800610 if (mBindSequence != sequence) {
611 return;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800612 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800613 clearBindingLocked();
614 // If we were actively using the last input method, then
615 // we would like to re-connect to the next input method.
616 if (mServedView != null && mServedView.isFocused()) {
617 mServedConnecting = true;
618 }
619 startInput = mActive;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800620 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800621 if (startInput) {
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800622 startInputInner(
Yohei Yukawa42194222018-10-21 20:14:40 -0700623 StartInputReason.UNBOUND_FROM_IMMS, null, 0, 0, 0);
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800624 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800625 return;
626 }
627 case MSG_SET_ACTIVE: {
628 final boolean active = msg.arg1 != 0;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800629 final boolean fullscreen = msg.arg2 != 0;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900630 if (DEBUG) {
631 Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
632 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800633 synchronized (mH) {
634 mActive = active;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800635 mFullscreenMode = fullscreen;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800636 if (!active) {
637 // Some other client has starting using the IME, so note
638 // that this happened and make sure our own editor's
639 // state is reset.
Yohei Yukawa2553e482017-12-15 15:47:33 -0800640 mRestartOnNextWindowFocus = true;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800641 try {
642 // Note that finishComposingText() is allowed to run
643 // even when we are not active.
644 mIInputContext.finishComposingText();
645 } catch (RemoteException e) {
646 }
Mikael Gullstrand82ae3ff2014-11-25 12:41:53 +0100647 }
648 // Check focus again in case that "onWindowFocus" is called before
649 // handling this message.
Dake Guddf6c1e2018-05-10 11:41:19 -0700650 if (mServedView != null && canStartInput(mServedView)) {
Yohei Yukawa2553e482017-12-15 15:47:33 -0800651 if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
Yohei Yukawa42194222018-10-21 20:14:40 -0700652 final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
653 : StartInputReason.DEACTIVATED_BY_IMMS;
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800654 startInputInner(reason, null, 0, 0, 0);
satok05a6cbe2012-04-05 23:04:08 +0900655 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800656 }
657 }
658 return;
659 }
Jeff Brownf9e989d2013-04-04 23:04:03 -0700660 case MSG_SEND_INPUT_EVENT: {
661 sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
662 return;
663 }
664 case MSG_TIMEOUT_INPUT_EVENT: {
665 finishedInputEvent(msg.arg1, false, true);
666 return;
667 }
668 case MSG_FLUSH_INPUT_EVENT: {
669 finishedInputEvent(msg.arg1, false, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700670 return;
671 }
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800672 case MSG_REPORT_FULLSCREEN_MODE: {
673 final boolean fullscreen = msg.arg1 != 0;
674 InputConnection ic = null;
675 synchronized (mH) {
676 mFullscreenMode = fullscreen;
677 if (mServedInputConnectionWrapper != null) {
678 ic = mServedInputConnectionWrapper.getInputConnection();
679 }
680 }
681 if (ic != null) {
682 ic.reportFullscreenMode(fullscreen);
683 }
684 return;
Yohei Yukawa3d1e8122014-06-06 19:12:47 +0900685 }
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800686 case MSG_REPORT_PRE_RENDERED: {
687 synchronized (mH) {
688 if (mImeInsetsConsumer != null) {
689 mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
690 }
691 }
692 return;
693
694 }
695 case MSG_APPLY_IME_VISIBILITY: {
696 synchronized (mH) {
697 if (mImeInsetsConsumer != null) {
698 mImeInsetsConsumer.applyImeVisibility(msg.arg1 != 0);
699 }
700 }
701 return;
702 }
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700703 case MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX: {
704 final float[] matrixValues = (float[]) msg.obj;
705 final int bindSequence = msg.arg1;
706 synchronized (mH) {
707 if (mBindSequence != bindSequence) {
708 return;
709 }
710 if (matrixValues == null) {
711 // That this app is unbound from the parent ActivityView. In this case,
712 // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
713 mActivityViewToScreenMatrix = null;
714 return;
715 }
716
717 final float[] currentValues = new float[9];
718 mActivityViewToScreenMatrix.getValues(currentValues);
719 if (Arrays.equals(currentValues, matrixValues)) {
720 return;
721 }
722 mActivityViewToScreenMatrix.setValues(matrixValues);
723
724 if (mCursorAnchorInfo == null || mCurMethod == null
725 || mServedInputConnectionWrapper == null) {
726 return;
727 }
728 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode
729 & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
730 if (!isMonitoring) {
731 return;
732 }
733 // Since the host ActivityView is moved, we need to issue
734 // IMS#updateCursorAnchorInfo() again.
735 try {
736 mCurMethod.updateCursorAnchorInfo(
737 CursorAnchorInfo.createForAdditionalParentMatrix(
738 mCursorAnchorInfo, mActivityViewToScreenMatrix));
739 } catch (RemoteException e) {
740 Log.w(TAG, "IME died: " + mCurId, e);
741 }
742 }
743 return;
744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 }
746 }
747 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800748
Jean Chalardde9dbb02011-10-20 19:50:45 +0900749 private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
750 private final InputMethodManager mParentInputMethodManager;
751
752 public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
753 final InputMethodManager inputMethodManager) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 super(mainLooper, conn);
Jean Chalardde9dbb02011-10-20 19:50:45 +0900755 mParentInputMethodManager = inputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 }
757
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800758 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 public boolean isActive() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700760 return mParentInputMethodManager.mActive && !isFinished();
Dianne Hackbornac920872012-05-22 11:49:49 -0700761 }
762
763 void deactivate() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700764 if (isFinished()) {
765 // This is a small performance optimization. Still only the 1st call of
766 // reportFinish() will take effect.
767 return;
768 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700769 closeConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 }
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800771
772 @Override
773 public String toString() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700774 return "ControlledInputConnectionWrapper{"
775 + "connection=" + getInputConnection()
776 + " finished=" + isFinished()
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800777 + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
778 + "}";
779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
Jeff Brownc28867a2013-03-26 15:42:39 -0700783 @Override
784 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 // No need to check for dump permission, since we only give this
786 // interface to the system.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 CountDownLatch latch = new CountDownLatch(1);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700788 SomeArgs sargs = SomeArgs.obtain();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 sargs.arg1 = fd;
790 sargs.arg2 = fout;
791 sargs.arg3 = args;
792 sargs.arg4 = latch;
793 mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
794 try {
795 if (!latch.await(5, TimeUnit.SECONDS)) {
796 fout.println("Timeout waiting for dump");
797 }
798 } catch (InterruptedException e) {
799 fout.println("Interrupted waiting for dump");
800 }
801 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700802
803 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 public void onBindMethod(InputBindResult res) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800805 mH.obtainMessage(MSG_BIND, res).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700807
808 @Override
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700809 public void onUnbindMethod(int sequence, @UnbindReason int unbindReason) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800810 mH.obtainMessage(MSG_UNBIND, sequence, unbindReason).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700812
813 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800814 public void setActive(boolean active, boolean fullscreen) {
815 mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
Yohei Yukawab7b79072014-03-25 11:02:00 +0900817
818 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800819 public void reportFullscreenMode(boolean fullscreen) {
820 mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
821 .sendToTarget();
822 }
823
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800824 @Override
825 public void reportPreRendered(EditorInfo info) {
826 mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
827 .sendToTarget();
828 }
829
830 @Override
831 public void applyImeVisibility(boolean setVisible) {
832 mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
833 .sendToTarget();
834 }
835
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700836 @Override
837 public void updateActivityViewToScreenMatrix(int bindSequence, float[] matrixValues) {
838 mH.obtainMessage(MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX, bindSequence, 0,
839 matrixValues).sendToTarget();
840 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700841 };
842
Dianne Hackborn51bf0772009-03-24 19:11:41 -0700843 final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700844
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700845 /**
846 * For layoutlib to clean up static objects inside {@link InputMethodManager}.
847 */
848 static void tearDownEditMode() {
849 if (!isInEditMode()) {
850 throw new UnsupportedOperationException(
851 "This method must be called only from layoutlib");
852 }
853 synchronized (sLock) {
854 sInstance = null;
855 }
Jeff Sharkeya4603d3c2016-08-11 16:54:13 -0600856 }
857
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700858 /**
859 * For layoutlib to override this method to return {@code true}.
860 *
861 * @return {@code true} if the process is running for developer tools
862 * @see View#isInEditMode()
863 */
864 private static boolean isInEditMode() {
865 return false;
866 }
867
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700868 @NonNull
869 private static InputMethodManager createInstance(int displayId, Looper looper) {
870 return isInEditMode() ? createStubInstance(displayId, looper)
871 : createRealInstance(displayId, looper);
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700872 }
873
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700874 @NonNull
875 private static InputMethodManager createRealInstance(int displayId, Looper looper) {
876 final IInputMethodManager service;
877 try {
878 service = IInputMethodManager.Stub.asInterface(
879 ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
880 } catch (ServiceNotFoundException e) {
881 throw new IllegalStateException(e);
882 }
883 final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
Yohei Yukawacb768bc2018-10-24 16:05:09 -0700884 // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
885 // associate PID/UID with each IME client. This means:
886 // A. if this method call will be handled as an IPC, there is no problem.
887 // B. if this method call will be handled as an in-proc method call, we need to
888 // ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
889 // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
890 // 1) doing so has no effect for A and 2) doing so is sufficient for B.
891 final long identity = Binder.clearCallingIdentity();
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700892 try {
893 service.addClient(imm.mClient, imm.mIInputContext, displayId);
894 } catch (RemoteException e) {
895 e.rethrowFromSystemServer();
Yohei Yukawacb768bc2018-10-24 16:05:09 -0700896 } finally {
897 Binder.restoreCallingIdentity(identity);
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700898 }
899 return imm;
900 }
901
902 @NonNull
903 private static InputMethodManager createStubInstance(int displayId, Looper looper) {
904 // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
905 final Class<IInputMethodManager> c = IInputMethodManager.class;
906 final IInputMethodManager stubInterface =
907 (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
908 new Class[]{c}, (proxy, method, args) -> {
909 final Class<?> returnType = method.getReturnType();
910 if (returnType == boolean.class) {
911 return false;
912 } else if (returnType == int.class) {
913 return 0;
914 } else if (returnType == long.class) {
915 return 0L;
916 } else if (returnType == short.class) {
917 return 0;
918 } else if (returnType == char.class) {
919 return 0;
920 } else if (returnType == byte.class) {
921 return 0;
922 } else if (returnType == float.class) {
923 return 0f;
924 } else if (returnType == double.class) {
925 return 0.0;
926 } else {
927 return null;
928 }
929 });
930 return new InputMethodManager(stubInterface, displayId, looper);
931 }
932
933 private InputMethodManager(IInputMethodManager service, int displayId, Looper looper) {
934 mService = service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 mMainLooper = looper;
936 mH = new H(looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800937 mDisplayId = displayId;
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700938 mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 }
940
941 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800942 * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
Yohei Yukawa6c075722018-09-21 14:52:12 -0700943 *
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800944 * @param context {@link Context} for which IME APIs need to work
945 * @return {@link InputMethodManager} instance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 * @hide
947 */
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700948 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800949 public static InputMethodManager forContext(Context context) {
950 final int displayId = context.getDisplayId();
951 // For better backward compatibility, we always use Looper.getMainLooper() for the default
952 // display case.
953 final Looper looper = displayId == Display.DEFAULT_DISPLAY
954 ? Looper.getMainLooper() : context.getMainLooper();
955 return forContextInternal(displayId, looper);
956 }
957
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700958 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800959 private static InputMethodManager forContextInternal(int displayId, Looper looper) {
960 final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700961 synchronized (sLock) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800962 InputMethodManager instance = sInstanceMap.get(displayId);
963 if (instance != null) {
964 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700966 instance = createInstance(displayId, looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800967 // For backward compatibility, store the instance also to sInstance for default display.
968 if (sInstance == null && isDefaultDisplay) {
969 sInstance = instance;
970 }
971 sInstanceMap.put(displayId, instance);
972 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700977 * Deprecated. Do not use.
978 *
979 * @return global {@link InputMethodManager} instance
Yohei Yukawa484d4af2018-09-17 16:47:08 -0700980 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
981 * support multi-display scenario.
Yohei Yukawa6c075722018-09-21 14:52:12 -0700982 * @hide
983 */
984 @Deprecated
985 @UnsupportedAppUsage
986 public static InputMethodManager getInstance() {
987 Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be"
988 + " compatible with multi-display."
989 + " Use context.getSystemService(InputMethodManager.class) instead.",
990 new Throwable());
991 ensureDefaultInstanceForDefaultDisplayIfNecessary();
992 return peekInstance();
993 }
994
995 /**
996 * Deprecated. Do not use.
997 *
998 * @return {@link #sInstance}
999 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
1000 * support multi-display scenario.
1001 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 */
Yohei Yukawa484d4af2018-09-17 16:47:08 -07001003 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001004 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -07001005 public static InputMethodManager peekInstance() {
Yohei Yukawa6c075722018-09-21 14:52:12 -07001006 Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be"
1007 + " compatible with multi-display."
1008 + " Use context.getSystemService(InputMethodManager.class) instead.",
1009 new Throwable());
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -07001010 synchronized (sLock) {
1011 return sInstance;
1012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001016 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 public IInputMethodClient getClient() {
1018 return mClient;
1019 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001022 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 public IInputContext getInputContext() {
1024 return mIInputContext;
1025 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001026
Yohei Yukawa629271a2019-02-05 07:50:36 -08001027 /**
1028 * Returns the list of installed input methods.
1029 *
1030 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1031 *
1032 * @return {@link List} of {@link InputMethodInfo}.
1033 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 public List<InputMethodInfo> getInputMethodList() {
1035 try {
Yohei Yukawad20eef82019-02-05 10:45:32 -08001036 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1037 // services InputMethodManagerInternal.getInputMethodListAsUser() should be used
1038 // instead.
1039 return mService.getInputMethodList(UserHandle.myUserId());
1040 } catch (RemoteException e) {
1041 throw e.rethrowFromSystemServer();
1042 }
1043 }
1044
1045 /**
1046 * Returns the list of installed input methods for the specified user.
1047 *
1048 * @param userId user ID to query
1049 * @return {@link List} of {@link InputMethodInfo}.
1050 * @hide
1051 */
1052 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1053 public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
1054 try {
1055 return mService.getInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001057 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 }
1059 }
1060
Yohei Yukawa629271a2019-02-05 07:50:36 -08001061 /**
1062 * Returns the list of enabled input methods.
1063 *
1064 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1065 *
1066 * @return {@link List} of {@link InputMethodInfo}.
1067 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 public List<InputMethodInfo> getEnabledInputMethodList() {
1069 try {
Yohei Yukawa1fb13c52019-02-05 07:55:28 -08001070 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1071 // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used
1072 // instead.
1073 return mService.getEnabledInputMethodList(UserHandle.myUserId());
1074 } catch (RemoteException e) {
1075 throw e.rethrowFromSystemServer();
1076 }
1077 }
1078
1079 /**
1080 * Returns the list of enabled input methods for the specified user.
1081 *
1082 * @param userId user ID to query
1083 * @return {@link List} of {@link InputMethodInfo}.
1084 * @hide
1085 */
1086 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1087 public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
1088 try {
1089 return mService.getEnabledInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001091 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 }
1093 }
1094
satokd4fce2b2011-04-11 12:07:13 +09001095 /**
1096 * Returns a list of enabled input method subtypes for the specified input method info.
Yohei Yukawa629271a2019-02-05 07:50:36 -08001097 *
1098 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1099 *
satokd4fce2b2011-04-11 12:07:13 +09001100 * @param imi An input method info whose subtypes list will be returned.
1101 * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly
1102 * selected subtypes. If an input method info doesn't have enabled subtypes, the framework
1103 * will implicitly enable subtypes according to the current system language.
1104 */
satok16331c82010-12-20 23:48:46 +09001105 public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
1106 boolean allowsImplicitlySelectedSubtypes) {
satok67ddf9c2010-11-17 09:45:54 +09001107 try {
Satoshi Kataokab3c21ac2013-08-07 15:43:29 +09001108 return mService.getEnabledInputMethodSubtypeList(
1109 imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
satok67ddf9c2010-11-17 09:45:54 +09001110 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001111 throw e.rethrowFromSystemServer();
satok67ddf9c2010-11-17 09:45:54 +09001112 }
1113 }
1114
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001115 /**
1116 * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
1117 * intended for IME developers who should be accessing APIs through the service. APIs in this
1118 * class are intended for app developers interacting with the IME.
1119 */
1120 @Deprecated
Yohei Yukawa41b094f2018-09-09 23:58:45 -07001121 public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001122 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 }
1124
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001125 /**
1126 * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
1127 * intended for IME developers who should be accessing APIs through the service. APIs in
1128 * this class are intended for app developers interacting with the IME.
1129 */
1130 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 public void hideStatusIcon(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001132 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 }
1134
Yohei Yukawa17ace292019-01-21 09:24:26 -08001135 /**
1136 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1137 *
1138 * @param spans will be ignored.
1139 *
1140 * @deprecated Do not use.
1141 * @hide
1142 */
1143 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001144 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001145 public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001146 Log.w(TAG, "registerSuggestionSpansForNotification() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001147 }
1148
Yohei Yukawa17ace292019-01-21 09:24:26 -08001149 /**
1150 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1151 *
1152 * @deprecated Do not use.
1153 * @hide
1154 */
1155 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001156 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001157 public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001158 Log.w(TAG, "notifySuggestionPicked() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001159 }
1160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 /**
1162 * Allows you to discover whether the attached input method is running
1163 * in fullscreen mode. Return true if it is fullscreen, entirely covering
1164 * your UI, else returns false.
1165 */
1166 public boolean isFullscreenMode() {
Yohei Yukawa1544def2016-04-26 17:13:38 -07001167 synchronized (mH) {
1168 return mFullscreenMode;
1169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 }
Yohei Yukawa1544def2016-04-26 17:13:38 -07001171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 /**
1173 * Return true if the given view is the currently active view for the
1174 * input method.
1175 */
1176 public boolean isActive(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001177 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001178 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1179 if (fallbackImm != null) {
1180 return fallbackImm.isActive(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001181 }
1182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 checkFocus();
1184 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001185 return (mServedView == view
1186 || (mServedView != null
1187 && mServedView.checkInputConnectionProxy(view)))
1188 && mCurrentTextBoxAttribute != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 }
1190 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 /**
1193 * Return true if any view is currently active in the input method.
1194 */
1195 public boolean isActive() {
1196 checkFocus();
1197 synchronized (mH) {
1198 return mServedView != null && mCurrentTextBoxAttribute != null;
1199 }
1200 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 /**
1203 * Return true if the currently served view is accepting full text edits.
1204 * If false, it has no input connection, so can only handle raw key events.
1205 */
1206 public boolean isAcceptingText() {
1207 checkFocus();
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001208 return mServedInputConnectionWrapper != null &&
1209 mServedInputConnectionWrapper.getInputConnection() != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 }
1211
1212 /**
1213 * Reset all of the state associated with being bound to an input method.
1214 */
1215 void clearBindingLocked() {
Dianne Hackborn6b6b3fd2014-03-24 11:27:18 -07001216 if (DEBUG) Log.v(TAG, "Clearing binding!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 clearConnectionLocked();
Jeff Brown4d656882013-04-03 14:39:19 -07001218 setInputChannelLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 mBindSequence = -1;
1220 mCurId = null;
1221 mCurMethod = null;
Jeff Brown4d656882013-04-03 14:39:19 -07001222 }
1223
1224 void setInputChannelLocked(InputChannel channel) {
1225 if (mCurChannel != channel) {
1226 if (mCurSender != null) {
1227 flushPendingEventsLocked();
1228 mCurSender.dispose();
1229 mCurSender = null;
1230 }
1231 if (mCurChannel != null) {
1232 mCurChannel.dispose();
1233 }
1234 mCurChannel = channel;
Jeff Brownc28867a2013-03-26 15:42:39 -07001235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 }
Jeff Brown4d656882013-04-03 14:39:19 -07001237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 /**
1239 * Reset all of the state associated with a served view being connected
1240 * to an input method
1241 */
1242 void clearConnectionLocked() {
1243 mCurrentTextBoxAttribute = null;
Dianne Hackbornac920872012-05-22 11:49:49 -07001244 if (mServedInputConnectionWrapper != null) {
1245 mServedInputConnectionWrapper.deactivate();
1246 mServedInputConnectionWrapper = null;
1247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 }
Yohei Yukawa0f3a99d2015-05-21 00:15:05 -07001249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 /**
1251 * Disconnect any existing input connection, clearing the served view.
1252 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001253 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 void finishInputLocked() {
1255 mNextServedView = null;
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001256 mActivityViewToScreenMatrix = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 if (mServedView != null) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001258 if (DEBUG) Log.v(TAG, "FINISH INPUT: mServedView=" + dumpViewInfo(mServedView));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 mServedView = null;
1260 mCompletions = null;
1261 mServedConnecting = false;
1262 clearConnectionLocked();
1263 }
1264 }
Gilles Debunnec478c172011-12-19 17:29:24 -08001265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 public void displayCompletions(View view, CompletionInfo[] completions) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001267 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001268 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1269 if (fallbackImm != null) {
1270 fallbackImm.displayCompletions(view, completions);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001271 return;
1272 }
1273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 checkFocus();
1275 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001276 if (mServedView != view && (mServedView == null
1277 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 return;
1279 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 mCompletions = completions;
1282 if (mCurMethod != null) {
1283 try {
1284 mCurMethod.displayCompletions(mCompletions);
1285 } catch (RemoteException e) {
1286 }
1287 }
1288 }
1289 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 public void updateExtractedText(View view, int token, ExtractedText text) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001292 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001293 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1294 if (fallbackImm != null) {
1295 fallbackImm.updateExtractedText(view, token, text);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001296 return;
1297 }
1298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 checkFocus();
1300 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001301 if (mServedView != view && (mServedView == null
1302 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 return;
1304 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 if (mCurMethod != null) {
1307 try {
1308 mCurMethod.updateExtractedText(token, text);
1309 } catch (RemoteException e) {
1310 }
1311 }
1312 }
1313 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 /**
1316 * Flag for {@link #showSoftInput} to indicate that this is an implicit
1317 * request to show the input window, not as the result of a direct request
1318 * by the user. The window may not be shown in this case.
1319 */
1320 public static final int SHOW_IMPLICIT = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 /**
1323 * Flag for {@link #showSoftInput} to indicate that the user has forced
1324 * the input method open (such as by long-pressing menu) so it should
1325 * not be closed until they explicitly do so.
1326 */
1327 public static final int SHOW_FORCED = 0x0002;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001330 * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
1331 * a result receiver: explicitly request that the current input method's
1332 * soft input area be shown to the user, if needed.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001333 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001334 * @param view The currently focused view, which would like to receive
1335 * soft keyboard input.
1336 * @param flags Provides additional operating flags. Currently may be
1337 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
1338 */
1339 public boolean showSoftInput(View view, int flags) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001340 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001341 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1342 if (fallbackImm != null) {
1343 return fallbackImm.showSoftInput(view, flags);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001344 }
1345
The Android Open Source Project4df24232009-03-05 14:34:35 -08001346 return showSoftInput(view, flags, null);
1347 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001348
The Android Open Source Project4df24232009-03-05 14:34:35 -08001349 /**
1350 * Flag for the {@link ResultReceiver} result code from
1351 * {@link #showSoftInput(View, int, ResultReceiver)} and
1352 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1353 * state of the soft input window was unchanged and remains shown.
1354 */
1355 public static final int RESULT_UNCHANGED_SHOWN = 0;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001356
The Android Open Source Project4df24232009-03-05 14:34:35 -08001357 /**
1358 * Flag for the {@link ResultReceiver} result code from
1359 * {@link #showSoftInput(View, int, ResultReceiver)} and
1360 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1361 * state of the soft input window was unchanged and remains hidden.
1362 */
1363 public static final int RESULT_UNCHANGED_HIDDEN = 1;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001364
The Android Open Source Project4df24232009-03-05 14:34:35 -08001365 /**
1366 * Flag for the {@link ResultReceiver} result code from
1367 * {@link #showSoftInput(View, int, ResultReceiver)} and
1368 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1369 * state of the soft input window changed from hidden to shown.
1370 */
1371 public static final int RESULT_SHOWN = 2;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001372
The Android Open Source Project4df24232009-03-05 14:34:35 -08001373 /**
1374 * Flag for the {@link ResultReceiver} result code from
1375 * {@link #showSoftInput(View, int, ResultReceiver)} and
1376 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1377 * state of the soft input window changed from shown to hidden.
1378 */
1379 public static final int RESULT_HIDDEN = 3;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001380
The Android Open Source Project4df24232009-03-05 14:34:35 -08001381 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 * Explicitly request that the current input method's soft input area be
1383 * shown to the user, if needed. Call this if the user interacts with
1384 * your view in such a way that they have expressed they would like to
1385 * start performing input into it.
Yohei Yukawad552a522016-03-20 15:08:31 -07001386 *
1387 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1388 * this method can be a long-lived object, because it may not be
1389 * garbage-collected until all the corresponding {@link ResultReceiver}
1390 * objects transferred to different processes get garbage-collected.
1391 * Follow the general patterns to avoid memory leaks in Android.
1392 * Consider to use {@link java.lang.ref.WeakReference} so that application
1393 * logic objects such as {@link android.app.Activity} and {@link Context}
1394 * can be garbage collected regardless of the lifetime of
1395 * {@link ResultReceiver}.
1396 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 * @param view The currently focused view, which would like to receive
1398 * soft keyboard input.
1399 * @param flags Provides additional operating flags. Currently may be
1400 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001401 * @param resultReceiver If non-null, this will be called by the IME when
1402 * it has processed your request to tell you what it has done. The result
1403 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1404 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1405 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 */
Gilles Debunnead8484b2011-02-17 17:37:51 -08001407 public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001408 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001409 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1410 if (fallbackImm != null) {
1411 return fallbackImm.showSoftInput(view, flags, resultReceiver);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001412 }
1413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 checkFocus();
1415 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001416 if (mServedView != view && (mServedView == null
1417 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001418 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 }
1420
1421 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001422 return mService.showSoftInput(mClient, flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001424 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 }
1426 }
1427 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001428
Yohei Yukawa101ae462017-03-31 14:28:18 -07001429 /**
1430 * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
1431 * is publicly released because previous implementations of that class had relied on this method
1432 * via reflection.
1433 *
1434 * @deprecated This is a hidden API. You should never use this.
1435 * @hide
1436 */
1437 @Deprecated
Yohei Yukawa1466e4a2019-02-12 01:42:56 -08001438 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
The Android Open Source Project4df24232009-03-05 14:34:35 -08001439 public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 try {
Yohei Yukawa101ae462017-03-31 14:28:18 -07001441 Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
1442 + "soon. If you are using android.support.v7.widget.SearchView, please update "
1443 + "to version 26.0 or newer version.");
The Android Open Source Project4df24232009-03-05 14:34:35 -08001444 mService.showSoftInput(mClient, flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001446 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 }
1448 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001451 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
1452 * to indicate that the soft input window should only be hidden if it was not explicitly shown
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 * by the user.
1454 */
1455 public static final int HIDE_IMPLICIT_ONLY = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001458 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestShowSelf(int)}
1459 * to indicate that the soft input window should normally be hidden, unless it was originally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 * shown with {@link #SHOW_FORCED}.
1461 */
1462 public static final int HIDE_NOT_ALWAYS = 0x0002;
Gilles Debunnec478c172011-12-19 17:29:24 -08001463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 /**
Gilles Debunne7c8c6d62011-01-24 14:48:14 -08001465 * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
The Android Open Source Project4df24232009-03-05 14:34:35 -08001466 * without a result: request to hide the soft input window from the
1467 * context of the window that is currently accepting input.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001468 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001469 * @param windowToken The token of the window that is making the request,
1470 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1471 * @param flags Provides additional operating flags. Currently may be
1472 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
1473 */
1474 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
1475 return hideSoftInputFromWindow(windowToken, flags, null);
1476 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001477
The Android Open Source Project4df24232009-03-05 14:34:35 -08001478 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 * Request to hide the soft input window from the context of the window
1480 * that is currently accepting input. This should be called as a result
1481 * of the user doing some actually than fairly explicitly requests to
1482 * have the input window hidden.
Yohei Yukawad552a522016-03-20 15:08:31 -07001483 *
1484 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1485 * this method can be a long-lived object, because it may not be
1486 * garbage-collected until all the corresponding {@link ResultReceiver}
1487 * objects transferred to different processes get garbage-collected.
1488 * Follow the general patterns to avoid memory leaks in Android.
1489 * Consider to use {@link java.lang.ref.WeakReference} so that application
1490 * logic objects such as {@link android.app.Activity} and {@link Context}
1491 * can be garbage collected regardless of the lifetime of
1492 * {@link ResultReceiver}.
1493 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 * @param windowToken The token of the window that is making the request,
1495 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1496 * @param flags Provides additional operating flags. Currently may be
1497 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001498 * @param resultReceiver If non-null, this will be called by the IME when
1499 * it has processed your request to tell you what it has done. The result
1500 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1501 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1502 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 */
The Android Open Source Project4df24232009-03-05 14:34:35 -08001504 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
1505 ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 checkFocus();
1507 synchronized (mH) {
1508 if (mServedView == null || mServedView.getWindowToken() != windowToken) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001509 return false;
1510 }
1511
1512 try {
1513 return mService.hideSoftInput(mClient, flags, resultReceiver);
1514 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001515 throw e.rethrowFromSystemServer();
The Android Open Source Project4df24232009-03-05 14:34:35 -08001516 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001517 }
1518 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001519
The Android Open Source Project4df24232009-03-05 14:34:35 -08001520 /**
1521 * This method toggles the input method window display.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001522 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001523 * If not the input window will be displayed.
1524 * @param windowToken The token of the window that is making the request,
1525 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1526 * @param showFlags Provides additional operating flags. May be
1527 * 0 or have the {@link #SHOW_IMPLICIT},
1528 * {@link #SHOW_FORCED} bit set.
1529 * @param hideFlags Provides additional operating flags. May be
1530 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1531 * {@link #HIDE_NOT_ALWAYS} bit set.
1532 **/
1533 public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
1534 synchronized (mH) {
1535 if (mServedView == null || mServedView.getWindowToken() != windowToken) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 return;
1537 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001538 if (mCurMethod != null) {
1539 try {
1540 mCurMethod.toggleSoftInput(showFlags, hideFlags);
1541 } catch (RemoteException e) {
1542 }
1543 }
1544 }
1545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001547 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001548 * This method toggles the input method window display.
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001549 *
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001550 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001551 * If not the input window will be displayed.
1552 * @param showFlags Provides additional operating flags. May be
1553 * 0 or have the {@link #SHOW_IMPLICIT},
1554 * {@link #SHOW_FORCED} bit set.
1555 * @param hideFlags Provides additional operating flags. May be
1556 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1557 * {@link #HIDE_NOT_ALWAYS} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001558 */
1559 public void toggleSoftInput(int showFlags, int hideFlags) {
1560 if (mCurMethod != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001562 mCurMethod.toggleSoftInput(showFlags, hideFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 } catch (RemoteException e) {
1564 }
1565 }
1566 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 /**
1569 * If the input method is currently connected to the given view,
1570 * restart it with its new contents. You should call this when the text
1571 * within your view changes outside of the normal input method or key
1572 * input flow, such as when an application calls TextView.setText().
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001573 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 * @param view The view whose text has changed.
1575 */
1576 public void restartInput(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001577 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001578 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1579 if (fallbackImm != null) {
1580 fallbackImm.restartInput(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001581 return;
1582 }
1583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 checkFocus();
1585 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001586 if (mServedView != view && (mServedView == null
1587 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 return;
1589 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 mServedConnecting = true;
1592 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001593
Yohei Yukawa42194222018-10-21 20:14:40 -07001594 startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001596
Yohei Yukawac6632df2018-10-21 11:47:16 -07001597 boolean startInputInner(@StartInputReason int startInputReason,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001598 @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
1599 @SoftInputModeFlags int softInputMode, int windowFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 final View view;
1601 synchronized (mH) {
1602 view = mServedView;
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 // Make sure we have a window token for the served view.
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001605 if (DEBUG) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001606 Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) +
Yohei Yukawaa468d702018-10-21 11:42:34 -07001607 " reason=" + InputMethodDebug.startInputReasonToString(startInputReason));
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 if (view == null) {
1610 if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
Dianne Hackborn7663d802012-02-24 13:08:49 -08001611 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 }
1613 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001614
Yohei Yukawa80498d52018-06-21 16:24:36 -07001615 if (windowGainingFocus == null) {
1616 windowGainingFocus = view.getWindowToken();
1617 if (windowGainingFocus == null) {
1618 Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
1619 return false;
1620 }
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001621 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
Yohei Yukawa80498d52018-06-21 16:24:36 -07001622 if (view.onCheckIsTextEditor()) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001623 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
Yohei Yukawa80498d52018-06-21 16:24:36 -07001624 }
1625 softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
1626 windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
1627 }
1628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 // Now we need to get an input connection from the served view.
1630 // This is complicated in a couple ways: we can't be holding our lock
1631 // when calling out to the view, and we need to make sure we call into
1632 // the view on the same thread that is driving its view hierarchy.
1633 Handler vh = view.getHandler();
1634 if (vh == null) {
1635 // If the view doesn't have a handler, something has changed out
Satoshi Kataoka35739502012-10-02 19:00:26 +09001636 // from under us, so just close the current input.
1637 // If we don't close the current input, the current input method can remain on the
1638 // screen without a connection.
1639 if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
1640 closeCurrentInput();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001641 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 }
1643 if (vh.getLooper() != Looper.myLooper()) {
1644 // The view is running on a different thread than our own, so
1645 // we need to reschedule our work for over there.
1646 if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
Yohei Yukawa623e94b2018-01-14 16:30:59 -08001647 vh.post(() -> startInputInner(startInputReason, null, 0, 0, 0));
Dianne Hackborn7663d802012-02-24 13:08:49 -08001648 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 // Okay we are now ready to call into the served view and have it
1652 // do its stuff.
1653 // Life is good: let's hook everything up!
1654 EditorInfo tba = new EditorInfo();
Yohei Yukawa02df3282015-06-03 15:58:59 -07001655 // Note: Use Context#getOpPackageName() rather than Context#getPackageName() so that the
1656 // system can verify the consistency between the uid of this process and package name passed
1657 // from here. See comment of Context#getOpPackageName() for details.
1658 tba.packageName = view.getContext().getOpPackageName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 tba.fieldId = view.getId();
1660 InputConnection ic = view.onCreateInputConnection(tba);
1661 if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
Gilles Debunnec478c172011-12-19 17:29:24 -08001662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 synchronized (mH) {
1664 // Now that we are locked again, validate that our state hasn't
1665 // changed.
1666 if (mServedView != view || !mServedConnecting) {
1667 // Something else happened, so abort.
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001668 if (DEBUG) Log.v(TAG,
1669 "Starting input: finished by someone else. view=" + dumpViewInfo(view)
1670 + " mServedView=" + dumpViewInfo(mServedView)
1671 + " mServedConnecting=" + mServedConnecting);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001672 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 // If we already have a text box, then this view is already
1676 // connected so we want to restart it.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001677 if (mCurrentTextBoxAttribute == null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001678 startInputFlags |= StartInputFlags.INITIAL_CONNECTION;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001679 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 // Hook 'em up and let 'er rip.
1682 mCurrentTextBoxAttribute = tba;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001683 maybeCallServedViewChangedLocked(tba);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 mServedConnecting = false;
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001685 if (mServedInputConnectionWrapper != null) {
1686 mServedInputConnectionWrapper.deactivate();
1687 mServedInputConnectionWrapper = null;
1688 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001689 ControlledInputConnectionWrapper servedContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001690 final int missingMethodFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 if (ic != null) {
1692 mCursorSelStart = tba.initialSelStart;
1693 mCursorSelEnd = tba.initialSelEnd;
1694 mCursorCandStart = -1;
1695 mCursorCandEnd = -1;
1696 mCursorRect.setEmpty();
Yohei Yukawa056ffe62014-05-13 14:26:09 +09001697 mCursorAnchorInfo = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001698 final Handler icHandler;
1699 missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
1700 if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER)
1701 != 0) {
1702 // InputConnection#getHandler() is not implemented.
1703 icHandler = null;
1704 } else {
1705 icHandler = ic.getHandler();
1706 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001707 servedContext = new ControlledInputConnectionWrapper(
1708 icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 } else {
1710 servedContext = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001711 missingMethodFlags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001713 mServedInputConnectionWrapper = servedContext;
Yohei Yukawa612cce92016-02-11 17:47:33 -08001714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 try {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001716 if (DEBUG) Log.v(TAG, "START INPUT: view=" + dumpViewInfo(view) + " ic="
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001717 + ic + " tba=" + tba + " startInputFlags="
1718 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001719 final InputBindResult res = mService.startInputOrWindowGainedFocus(
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001720 startInputReason, mClient, windowGainingFocus, startInputFlags,
1721 softInputMode, windowFlags, tba, servedContext, missingMethodFlags,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001722 view.getContext().getApplicationInfo().targetSdkVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
Yohei Yukawa2553e482017-12-15 15:47:33 -08001724 if (res == null) {
1725 Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
1726 + " null. startInputReason="
Yohei Yukawaa468d702018-10-21 11:42:34 -07001727 + InputMethodDebug.startInputReasonToString(startInputReason)
Yohei Yukawa2553e482017-12-15 15:47:33 -08001728 + " editorInfo=" + tba
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001729 + " startInputFlags="
1730 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001731 return false;
1732 }
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001733 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
Yohei Yukawa2553e482017-12-15 15:47:33 -08001734 if (res.id != null) {
1735 setInputChannelLocked(res.channel);
1736 mBindSequence = res.sequence;
1737 mCurMethod = res.method;
1738 mCurId = res.id;
Yohei Yukawa2553e482017-12-15 15:47:33 -08001739 } else if (res.channel != null && res.channel != mCurChannel) {
1740 res.channel.dispose();
1741 }
1742 switch (res.result) {
1743 case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
1744 mRestartOnNextWindowFocus = true;
1745 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 }
1747 if (mCurMethod != null && mCompletions != null) {
1748 try {
1749 mCurMethod.displayCompletions(mCompletions);
1750 } catch (RemoteException e) {
1751 }
1752 }
1753 } catch (RemoteException e) {
1754 Log.w(TAG, "IME died: " + mCurId, e);
1755 }
1756 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001757
1758 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 }
1760
1761 /**
1762 * When the focused window is dismissed, this method is called to finish the
1763 * input method started before.
1764 * @hide
1765 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001766 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 public void windowDismissed(IBinder appWindowToken) {
1768 checkFocus();
1769 synchronized (mH) {
1770 if (mServedView != null &&
1771 mServedView.getWindowToken() == appWindowToken) {
1772 finishInputLocked();
1773 }
daqidff365e2018-09-19 15:51:22 +08001774 if (mCurRootView != null &&
1775 mCurRootView.getWindowToken() == appWindowToken) {
1776 mCurRootView = null;
1777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 }
1779 }
1780
1781 /**
1782 * Call this when a view receives focus.
1783 * @hide
1784 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001785 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 public void focusIn(View view) {
1787 synchronized (mH) {
1788 focusInLocked(view);
1789 }
1790 }
1791
1792 void focusInLocked(View view) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001793 if (DEBUG) Log.v(TAG, "focusIn: " + dumpViewInfo(view));
Yohei Yukawa5f059652015-05-14 22:16:41 -07001794
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07001795 if (view != null && view.isTemporarilyDetached()) {
1796 // This is a request from a view that is temporarily detached from a window.
1797 if (DEBUG) Log.v(TAG, "Temporarily detached view, ignoring");
1798 return;
1799 }
1800
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001801 if (mCurRootView != view.getRootView()) {
1802 // This is a request from a window that isn't in the window with
1803 // IME focus, so ignore it.
1804 if (DEBUG) Log.v(TAG, "Not IME target window, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 return;
1806 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 mNextServedView = view;
1809 scheduleCheckFocusLocked(view);
1810 }
1811
1812 /**
1813 * Call this when a view loses focus.
1814 * @hide
1815 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001816 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 public void focusOut(View view) {
1818 synchronized (mH) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001819 if (DEBUG) Log.v(TAG, "focusOut: view=" + dumpViewInfo(view)
1820 + " mServedView=" + dumpViewInfo(mServedView));
Yohei Yukawa0b52ed02015-05-29 11:07:02 -07001821 if (mServedView != view) {
1822 // The following code would auto-hide the IME if we end up
1823 // with no more views with focus. This can happen, however,
1824 // whenever we go into touch mode, so it ends up hiding
1825 // at times when we don't really want it to. For now it
1826 // seems better to just turn it all off.
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07001827 // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
Dake Guddf6c1e2018-05-10 11:41:19 -07001828 if (false && canStartInput(view)) {
Yohei Yukawa0b52ed02015-05-29 11:07:02 -07001829 mNextServedView = null;
1830 scheduleCheckFocusLocked(view);
1831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 }
1833 }
1834 }
1835
Yohei Yukawab13f0152015-05-29 17:09:14 -07001836 /**
1837 * Call this when a view is being detached from a {@link android.view.Window}.
1838 * @hide
1839 */
1840 public void onViewDetachedFromWindow(View view) {
1841 synchronized (mH) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001842 if (DEBUG) Log.v(TAG, "onViewDetachedFromWindow: view=" + dumpViewInfo(view)
1843 + " mServedView=" + dumpViewInfo(mServedView));
Yohei Yukawaa4f52ad2016-03-28 17:21:55 -07001844 if (mServedView == view) {
Yohei Yukawab13f0152015-05-29 17:09:14 -07001845 mNextServedView = null;
1846 scheduleCheckFocusLocked(view);
1847 }
1848 }
1849 }
1850
Gilles Debunnec478c172011-12-19 17:29:24 -08001851 static void scheduleCheckFocusLocked(View view) {
Jeff Browna175a5b2012-02-15 19:18:31 -08001852 ViewRootImpl viewRootImpl = view.getViewRootImpl();
1853 if (viewRootImpl != null) {
1854 viewRootImpl.dispatchCheckFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 }
1856 }
Jeff Browna175a5b2012-02-15 19:18:31 -08001857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 /**
1859 * @hide
1860 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001861 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 public void checkFocus() {
Yohei Yukawa241eac22016-03-28 00:28:50 -07001863 if (checkFocusNoStartInput(false)) {
Yohei Yukawa42194222018-10-21 20:14:40 -07001864 startInputInner(StartInputReason.CHECK_FOCUS, null, 0, 0, 0);
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +09001865 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001866 }
1867
Yohei Yukawa241eac22016-03-28 00:28:50 -07001868 private boolean checkFocusNoStartInput(boolean forceNewFocus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 // This is called a lot, so short-circuit before locking.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001870 if (mServedView == mNextServedView && !forceNewFocus) {
Dianne Hackborna82ba542012-02-15 18:19:55 -08001871 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 }
satok863fcd62011-06-21 17:38:02 +09001873
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001874 final ControlledInputConnectionWrapper ic;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 synchronized (mH) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001876 if (mServedView == mNextServedView && !forceNewFocus) {
Dianne Hackborna82ba542012-02-15 18:19:55 -08001877 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 }
1879 if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
1880 + " next=" + mNextServedView
satok05a6cbe2012-04-05 23:04:08 +09001881 + " forceNewFocus=" + forceNewFocus
1882 + " package="
1883 + (mServedView != null ? mServedView.getContext().getPackageName() : "<none>"));
Dianne Hackborna82ba542012-02-15 18:19:55 -08001884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 if (mNextServedView == null) {
1886 finishInputLocked();
1887 // In this case, we used to have a focused view on the window,
1888 // but no longer do. We should make sure the input method is
1889 // no longer shown, since it serves no purpose.
1890 closeCurrentInput();
Dianne Hackborna82ba542012-02-15 18:19:55 -08001891 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001893
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001894 ic = mServedInputConnectionWrapper;
Dianne Hackborna82ba542012-02-15 18:19:55 -08001895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 mServedView = mNextServedView;
1897 mCurrentTextBoxAttribute = null;
1898 mCompletions = null;
1899 mServedConnecting = true;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001900 // servedView has changed and it's not editable.
1901 if (!mServedView.onCheckIsTextEditor()) {
1902 maybeCallServedViewChangedLocked(null);
1903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001905
Yohei Yukawa241eac22016-03-28 00:28:50 -07001906 if (ic != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 ic.finishComposingText();
1908 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001909
1910 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001912
Mathew Inwooda570dee2018-08-17 14:56:00 +01001913 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 void closeCurrentInput() {
1915 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001916 mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001918 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001919 }
1920 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07001923 * Called by ViewAncestor when its window gets input focus.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 * @hide
1925 */
Yohei Yukawa22dac1c2017-02-12 16:54:16 -08001926 public void onPostWindowFocus(View rootView, View focusedView,
1927 @SoftInputModeFlags int softInputMode, boolean first, int windowFlags) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001928 boolean forceNewFocus = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 synchronized (mH) {
1930 if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
Yohei Yukawaa468d702018-10-21 11:42:34 -07001931 + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 + " first=" + first + " flags=#"
1933 + Integer.toHexString(windowFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001934 if (mRestartOnNextWindowFocus) {
1935 if (DEBUG) Log.v(TAG, "Restarting due to mRestartOnNextWindowFocus");
1936 mRestartOnNextWindowFocus = false;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001937 forceNewFocus = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 }
1939 focusInLocked(focusedView != null ? focusedView : rootView);
1940 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001941
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001942 int startInputFlags = 0;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001943 if (focusedView != null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001944 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001945 if (focusedView.onCheckIsTextEditor()) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001946 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 }
1948 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001949 if (first) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001950 startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001951 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001952
Yohei Yukawa241eac22016-03-28 00:28:50 -07001953 if (checkFocusNoStartInput(forceNewFocus)) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001954 // We need to restart input on the current focus view. This
1955 // should be done in conjunction with telling the system service
1956 // about the window gaining focus, to help make the transition
1957 // smooth.
Yohei Yukawa42194222018-10-21 20:14:40 -07001958 if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001959 startInputFlags, softInputMode, windowFlags)) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001960 return;
1961 }
1962 }
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001963
Dianne Hackborn7663d802012-02-24 13:08:49 -08001964 // For some reason we didn't do a startInput + windowFocusGain, so
1965 // we'll just do a window focus gain and call it a day.
1966 synchronized (mH) {
1967 try {
Dianne Hackbornac920872012-05-22 11:49:49 -07001968 if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001969 mService.startInputOrWindowGainedFocus(
Yohei Yukawa42194222018-10-21 20:14:40 -07001970 StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001971 rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags,
1972 null, null, 0 /* missingMethodFlags */,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001973 rootView.getContext().getApplicationInfo().targetSdkVersion);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001974 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001975 throw e.rethrowFromSystemServer();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001976 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -08001977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001978 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001979
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001980 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001981 @UnsupportedAppUsage
Yohei Yukawa5f059652015-05-14 22:16:41 -07001982 public void onPreWindowFocus(View rootView, boolean hasWindowFocus) {
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001983 synchronized (mH) {
Yohei Yukawa5f059652015-05-14 22:16:41 -07001984 if (rootView == null) {
1985 mCurRootView = null;
1986 } if (hasWindowFocus) {
1987 mCurRootView = rootView;
1988 } else if (rootView == mCurRootView) {
1989 // If the mCurRootView is losing window focus, release the strong reference to it
1990 // so as not to prevent it from being garbage-collected.
1991 mCurRootView = null;
1992 } else {
1993 if (DEBUG) {
1994 Log.v(TAG, "Ignoring onPreWindowFocus()."
1995 + " mCurRootView=" + mCurRootView + " rootView=" + rootView);
1996 }
1997 }
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001998 }
1999 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07002000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 /**
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08002002 * Register for IME state callbacks and applying visibility in
2003 * {@link android.view.ImeInsetsSourceConsumer}.
2004 * @hide
2005 */
2006 public void registerImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2007 if (imeInsetsConsumer == null) {
2008 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2009 }
2010
2011 synchronized (mH) {
2012 mImeInsetsConsumer = imeInsetsConsumer;
2013 }
2014 }
2015
2016 /**
Louis Chang3d4a7d12019-04-12 16:18:30 +08002017 * Unregister for IME state callbacks and applying visibility in
2018 * {@link android.view.ImeInsetsSourceConsumer}.
2019 * @hide
2020 */
2021 public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2022 if (imeInsetsConsumer == null) {
2023 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2024 }
2025
2026 synchronized (mH) {
2027 if (mImeInsetsConsumer == imeInsetsConsumer) {
2028 mImeInsetsConsumer = null;
2029 }
2030 }
2031 }
2032
2033 /**
Tarandeep Singh46d59f02019-01-29 18:09:15 -08002034 * Call showSoftInput with currently focused view.
2035 * @return {@code true} if IME can be shown.
2036 * @hide
2037 */
2038 public boolean requestImeShow(ResultReceiver resultReceiver) {
2039 synchronized (mH) {
2040 if (mServedView == null) {
2041 return false;
2042 }
2043 showSoftInput(mServedView, 0 /* flags */, resultReceiver);
2044 return true;
2045 }
2046 }
2047
2048 /**
2049 * Notify IME directly that it is no longer visible.
2050 * @hide
2051 */
2052 public void notifyImeHidden() {
2053 synchronized (mH) {
2054 try {
2055 if (mCurMethod != null) {
2056 mCurMethod.notifyImeHidden();
2057 }
2058 } catch (RemoteException re) {
2059 }
2060 }
2061 }
2062
2063 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 * Report the current selection range.
Jean Chalard6fd68e02014-02-20 17:48:46 +09002065 *
2066 * <p><strong>Editor authors</strong>, you need to call this method whenever
2067 * the cursor moves in your editor. Remember that in addition to doing this, your
2068 * editor needs to always supply current cursor values in
2069 * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
2070 * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
2071 * called, which happens whenever the keyboard shows up or the focus changes
2072 * to a text field, among other cases.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 */
2074 public void updateSelection(View view, int selStart, int selEnd,
2075 int candidatesStart, int candidatesEnd) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002076 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002077 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2078 if (fallbackImm != null) {
2079 fallbackImm.updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002080 return;
2081 }
2082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 checkFocus();
2084 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002085 if ((mServedView != view && (mServedView == null
2086 || !mServedView.checkInputConnectionProxy(view)))
2087 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 return;
2089 }
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
2092 || mCursorCandStart != candidatesStart
2093 || mCursorCandEnd != candidatesEnd) {
2094 if (DEBUG) Log.d(TAG, "updateSelection");
2095
2096 try {
2097 if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
Jean Chalardc743cb92013-09-12 16:28:45 +09002098 final int oldSelStart = mCursorSelStart;
2099 final int oldSelEnd = mCursorSelEnd;
2100 // Update internal values before sending updateSelection to the IME, because
2101 // if it changes the text within its onUpdateSelection handler in a way that
2102 // does not move the cursor we don't want to call it again with the same values.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 mCursorSelStart = selStart;
2104 mCursorSelEnd = selEnd;
2105 mCursorCandStart = candidatesStart;
2106 mCursorCandEnd = candidatesEnd;
Jean Chalardc743cb92013-09-12 16:28:45 +09002107 mCurMethod.updateSelection(oldSelStart, oldSelEnd,
2108 selStart, selEnd, candidatesStart, candidatesEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 } catch (RemoteException e) {
2110 Log.w(TAG, "IME died: " + mCurId, e);
2111 }
2112 }
2113 }
2114 }
2115
2116 /**
satok863fcd62011-06-21 17:38:02 +09002117 * Notify the event when the user tapped or clicked the text view.
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002118 *
2119 * @param view {@link View} which is being clicked.
2120 * @see InputMethodService#onViewClicked(boolean)
2121 * @deprecated The semantics of this method can never be defined well for composite {@link View}
2122 * that works as a giant "Canvas", which can host its own UI hierarchy and sub focus
2123 * state. {@link android.webkit.WebView} is a good example. Application / IME
2124 * developers should not rely on this method.
satok863fcd62011-06-21 17:38:02 +09002125 */
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002126 @Deprecated
satok863fcd62011-06-21 17:38:02 +09002127 public void viewClicked(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002128 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002129 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2130 if (fallbackImm != null) {
2131 fallbackImm.viewClicked(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002132 return;
2133 }
2134
satok863fcd62011-06-21 17:38:02 +09002135 final boolean focusChanged = mServedView != mNextServedView;
2136 checkFocus();
2137 synchronized (mH) {
2138 if ((mServedView != view && (mServedView == null
2139 || !mServedView.checkInputConnectionProxy(view)))
2140 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2141 return;
2142 }
2143 try {
2144 if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
2145 mCurMethod.viewClicked(focusChanged);
2146 } catch (RemoteException e) {
2147 Log.w(TAG, "IME died: " + mCurId, e);
2148 }
2149 }
2150 }
2151
2152 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002153 * Return true if the current input method wants to watch the location
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 * of the input editor's cursor in its window.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002155 *
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002156 * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002157 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002158 @Deprecated
2159 public boolean isWatchingCursor(View view) {
2160 return false;
Yohei Yukawa4de04792014-04-17 12:40:31 +09002161 }
2162
2163 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002164 * Return true if the current input method wants to be notified when cursor/anchor location
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002165 * is changed.
Yohei Yukawab7b79072014-03-25 11:02:00 +09002166 *
2167 * @hide
2168 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002169 @UnsupportedAppUsage
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002170 public boolean isCursorAnchorInfoEnabled() {
2171 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002172 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002173 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawaa277db22014-08-21 18:38:44 -07002174 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002175 InputConnection.CURSOR_UPDATE_MONITOR) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002176 return isImmediate || isMonitoring;
2177 }
2178 }
2179
2180 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002181 * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002182 *
2183 * @hide
2184 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002185 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -07002186 public void setUpdateCursorAnchorInfoMode(int flags) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002187 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002188 mRequestUpdateCursorAnchorInfoMonitorMode = flags;
Yohei Yukawab7b79072014-03-25 11:02:00 +09002189 }
2190 }
2191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 /**
2193 * Report the current cursor location in its window.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002194 *
2195 * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002197 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 public void updateCursor(View view, int left, int top, int right, int bottom) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002199 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002200 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2201 if (fallbackImm != null) {
2202 fallbackImm.updateCursor(view, left, top, right, bottom);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002203 return;
2204 }
2205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 checkFocus();
2207 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002208 if ((mServedView != view && (mServedView == null
2209 || !mServedView.checkInputConnectionProxy(view)))
2210 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 return;
2212 }
Yohei Yukawaa277db22014-08-21 18:38:44 -07002213
2214 mTmpCursorRect.set(left, top, right, bottom);
2215 if (!mCursorRect.equals(mTmpCursorRect)) {
2216 if (DEBUG) Log.d(TAG, "updateCursor");
2217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 try {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002219 if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
2220 mCurMethod.updateCursor(mTmpCursorRect);
2221 mCursorRect.set(mTmpCursorRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 } catch (RemoteException e) {
2223 Log.w(TAG, "IME died: " + mCurId, e);
2224 }
2225 }
2226 }
2227 }
2228
2229 /**
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002230 * Report positional change of the text insertion point and/or characters in the composition
2231 * string.
2232 */
2233 public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
2234 if (view == null || cursorAnchorInfo == null) {
2235 return;
2236 }
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002237 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002238 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2239 if (fallbackImm != null) {
2240 fallbackImm.updateCursorAnchorInfo(view, cursorAnchorInfo);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002241 return;
2242 }
2243
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002244 checkFocus();
2245 synchronized (mH) {
2246 if ((mServedView != view &&
2247 (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
2248 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2249 return;
2250 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002251 // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
2252 // not been changed from the previous call.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002253 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002254 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002255 if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
Yohei Yukawa73605912014-08-13 16:49:35 +09002256 // TODO: Consider always emitting this message once we have addressed redundant
2257 // calls of this method from android.widget.Editor.
2258 if (DEBUG) {
2259 Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
2260 + cursorAnchorInfo);
2261 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002262 return;
2263 }
2264 if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002265 try {
Yohei Yukawab4f328a2019-05-02 08:41:27 -07002266 if (mActivityViewToScreenMatrix != null) {
2267 mCurMethod.updateCursorAnchorInfo(
2268 CursorAnchorInfo.createForAdditionalParentMatrix(
2269 cursorAnchorInfo, mActivityViewToScreenMatrix));
2270 } else {
2271 mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
2272 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002273 mCursorAnchorInfo = cursorAnchorInfo;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002274 // Clear immediate bit (if any).
Yohei Yukawaa277db22014-08-21 18:38:44 -07002275 mRequestUpdateCursorAnchorInfoMonitorMode &=
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002276 ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002277 } catch (RemoteException e) {
2278 Log.w(TAG, "IME died: " + mCurId, e);
2279 }
2280 }
2281 }
2282
2283 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
2285 * InputMethodSession.appPrivateCommand()} on the current Input Method.
2286 * @param view Optional View that is sending the command, or null if
2287 * you want to send the command regardless of the view that is attached
2288 * to the input method.
2289 * @param action Name of the command to be performed. This <em>must</em>
2290 * be a scoped name, i.e. prefixed with a package name you own, so that
2291 * different developers will not create conflicting commands.
2292 * @param data Any data to include with the command.
2293 */
2294 public void sendAppPrivateCommand(View view, String action, Bundle data) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002295 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002296 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2297 if (fallbackImm != null) {
2298 fallbackImm.sendAppPrivateCommand(view, action, data);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002299 return;
2300 }
2301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 checkFocus();
2303 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002304 if ((mServedView != view && (mServedView == null
2305 || !mServedView.checkInputConnectionProxy(view)))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2307 return;
2308 }
2309 try {
2310 if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
2311 mCurMethod.appPrivateCommand(action, data);
2312 } catch (RemoteException e) {
2313 Log.w(TAG, "IME died: " + mCurId, e);
2314 }
2315 }
2316 }
satok28203512010-11-24 11:06:49 +09002317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 /**
satok28203512010-11-24 11:06:49 +09002319 * Force switch to a new input method component. This can only be called
2320 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002321 *
2322 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, the undocumented behavior that
2323 * token can be {@code null} when the caller has
2324 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} is deprecated. Instead, update
2325 * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2326 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2327 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 * @param token Supplies the identifying token given to an input method
2329 * when it was started, which allows it to perform this operation on
2330 * itself.
2331 * @param id The unique identifier for the new input method to be switched to.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002332 * @deprecated Use {@link InputMethodService#switchInputMethod(String)}
2333 * instead. This method was intended for IME developers who should be accessing APIs through
2334 * the service. APIs in this class are intended for app developers interacting with the IME.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002336 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 public void setInputMethod(IBinder token, String id) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002338 if (token == null) {
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002339 // There are still some system components that rely on this undocumented behavior
2340 // regarding null IME token with WRITE_SECURE_SETTINGS. Provide a fallback logic as a
2341 // temporary remedy.
2342 if (id == null) {
2343 return;
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002344 }
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002345 if (Process.myUid() == Process.SYSTEM_UID) {
2346 Log.w(TAG, "System process should not be calling setInputMethod() because almost "
2347 + "always it is a bug under multi-user / multi-profile environment. "
2348 + "Consider interacting with InputMethodManagerService directly via "
2349 + "LocalServices.");
2350 return;
2351 }
2352 final Context fallbackContext = ActivityThread.currentApplication();
2353 if (fallbackContext == null) {
2354 return;
2355 }
2356 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2357 != PackageManager.PERMISSION_GRANTED) {
2358 return;
2359 }
2360 final List<InputMethodInfo> imis = getEnabledInputMethodList();
2361 final int numImis = imis.size();
2362 boolean found = false;
2363 for (int i = 0; i < numImis; ++i) {
2364 final InputMethodInfo imi = imis.get(i);
2365 if (id.equals(imi.getId())) {
2366 found = true;
2367 break;
2368 }
2369 }
2370 if (!found) {
2371 Log.e(TAG, "Ignoring setInputMethod(null, " + id + ") because the specified "
2372 + "id not found in enabled IMEs.");
2373 return;
2374 }
2375 Log.w(TAG, "The undocumented behavior that setInputMethod() accepts null token "
2376 + "when the caller has WRITE_SECURE_SETTINGS is deprecated. This behavior may "
2377 + "be completely removed in a future version. Update secure settings directly "
2378 + "instead.");
2379 final ContentResolver resolver = fallbackContext.getContentResolver();
2380 Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
2381 NOT_A_SUBTYPE_ID);
2382 Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, id);
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002383 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002385 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 }
satok28203512010-11-24 11:06:49 +09002387
2388 /**
2389 * Force switch to a new input method and subtype. This can only be called
2390 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002391 *
2392 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, {@code token} cannot be
2393 * {@code null} even with {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}. Instead,
2394 * update {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2395 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2396 *
satok28203512010-11-24 11:06:49 +09002397 * @param token Supplies the identifying token given to an input method
2398 * when it was started, which allows it to perform this operation on
2399 * itself.
2400 * @param id The unique identifier for the new input method to be switched to.
2401 * @param subtype The new subtype of the new input method to be switched to.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002402 * @deprecated Use
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002403 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002404 * instead. This method was intended for IME developers who should be accessing APIs through
2405 * the service. APIs in this class are intended for app developers interacting with the IME.
satok28203512010-11-24 11:06:49 +09002406 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002407 @Deprecated
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002408 public void setInputMethodAndSubtype(@NonNull IBinder token, String id,
2409 InputMethodSubtype subtype) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002410 if (token == null) {
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002411 Log.e(TAG, "setInputMethodAndSubtype() does not accept null token on Android Q "
2412 + "and later.");
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002413 return;
satok28203512010-11-24 11:06:49 +09002414 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002415 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype);
satok28203512010-11-24 11:06:49 +09002416 }
2417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 /**
2419 * Close/hide the input method's soft input area, so the user no longer
2420 * sees it or can interact with it. This can only be called
2421 * from the currently active input method, as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002422 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002423 * @param token Supplies the identifying token given to an input method
2424 * when it was started, which allows it to perform this operation on
2425 * itself.
2426 * @param flags Provides additional operating flags. Currently may be
The Android Open Source Project4df24232009-03-05 14:34:35 -08002427 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
2428 * {@link #HIDE_NOT_ALWAYS} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002429 * @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
2430 * intended for IME developers who should be accessing APIs through the service. APIs in this
2431 * class are intended for app developers interacting with the IME.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002432 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002433 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434 public void hideSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002435 InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002438 /**
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002439 * Show the input method's soft input area, so the user
The Android Open Source Project4df24232009-03-05 14:34:35 -08002440 * sees the input method window and can interact with it.
2441 * This can only be called from the currently active input method,
2442 * as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002443 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08002444 * @param token Supplies the identifying token given to an input method
2445 * when it was started, which allows it to perform this operation on
2446 * itself.
2447 * @param flags Provides additional operating flags. Currently may be
2448 * 0 or have the {@link #SHOW_IMPLICIT} or
2449 * {@link #SHOW_FORCED} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002450 * @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
2451 * intended for IME developers who should be accessing APIs through the service. APIs in this
2452 * class are intended for app developers interacting with the IME.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002453 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002454 @Deprecated
The Android Open Source Project4df24232009-03-05 14:34:35 -08002455 public void showSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002456 InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
The Android Open Source Project4df24232009-03-05 14:34:35 -08002457 }
Jeff Brownc28867a2013-03-26 15:42:39 -07002458
The Android Open Source Project4df24232009-03-05 14:34:35 -08002459 /**
Jeff Brownf9e989d2013-04-04 23:04:03 -07002460 * Dispatches an input event to the IME.
2461 *
2462 * Returns {@link #DISPATCH_HANDLED} if the event was handled.
2463 * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
2464 * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
2465 * callback will be invoked later.
2466 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 * @hide
2468 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07002469 public int dispatchInputEvent(InputEvent event, Object token,
2470 FinishedInputEventCallback callback, Handler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002472 if (mCurMethod != null) {
Jeff Brownc28867a2013-03-26 15:42:39 -07002473 if (event instanceof KeyEvent) {
2474 KeyEvent keyEvent = (KeyEvent)event;
2475 if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
2476 && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
2477 && keyEvent.getRepeatCount() == 0) {
2478 showInputMethodPickerLocked();
Jeff Brownf9e989d2013-04-04 23:04:03 -07002479 return DISPATCH_HANDLED;
Jeff Brownc28867a2013-03-26 15:42:39 -07002480 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08002481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482
Jeff Brownc28867a2013-03-26 15:42:39 -07002483 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002484
2485 PendingEvent p = obtainPendingEventLocked(
2486 event, token, mCurId, callback, handler);
2487 if (mMainLooper.isCurrentThread()) {
2488 // Already running on the IMM thread so we can send the event immediately.
2489 return sendInputEventOnMainLooperLocked(p);
Victoria Leaseb38070c2012-08-24 13:46:02 -07002490 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002491
2492 // Post the event to the IMM thread.
2493 Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
2494 msg.setAsynchronous(true);
2495 mH.sendMessage(msg);
2496 return DISPATCH_IN_PROGRESS;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002497 }
2498 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002499 return DISPATCH_NOT_HANDLED;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002500 }
2501
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002502 /**
2503 * Provides the default implementation of {@link InputConnection#sendKeyEvent(KeyEvent)}, which
2504 * is expected to dispatch an keyboard event sent from the IME to an appropriate event target
2505 * depending on the given {@link View} and the current focus state.
2506 *
2507 * <p>CAUTION: This method is provided only for the situation where
2508 * {@link InputConnection#sendKeyEvent(KeyEvent)} needs to be implemented without relying on
2509 * {@link BaseInputConnection}. Do not use this API for anything else.</p>
2510 *
2511 * @param targetView the default target view. If {@code null} is specified, then this method
2512 * tries to find a good event target based on the current focus state.
2513 * @param event the key event to be dispatched.
2514 */
2515 public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
2516 @NonNull KeyEvent event) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002517 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002518 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
2519 if (fallbackImm != null) {
2520 fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002521 return;
2522 }
2523
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002524 synchronized (mH) {
2525 ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
2526 if (viewRootImpl == null) {
2527 if (mServedView != null) {
2528 viewRootImpl = mServedView.getViewRootImpl();
2529 }
2530 }
2531 if (viewRootImpl != null) {
2532 viewRootImpl.dispatchKeyFromIme(event);
2533 }
2534 }
2535 }
2536
Jeff Brownf9e989d2013-04-04 23:04:03 -07002537 // Must be called on the main looper
2538 void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
2539 final boolean handled;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002540 synchronized (mH) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002541 int result = sendInputEventOnMainLooperLocked(p);
2542 if (result == DISPATCH_IN_PROGRESS) {
2543 return;
2544 }
2545
2546 handled = (result == DISPATCH_HANDLED);
2547 }
2548
2549 invokeFinishedInputEventCallback(p, handled);
2550 }
2551
2552 // Must be called on the main looper
2553 int sendInputEventOnMainLooperLocked(PendingEvent p) {
2554 if (mCurChannel != null) {
2555 if (mCurSender == null) {
2556 mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
2557 }
2558
2559 final InputEvent event = p.mEvent;
2560 final int seq = event.getSequenceNumber();
2561 if (mCurSender.sendInputEvent(seq, event)) {
2562 mPendingEvents.put(seq, p);
2563 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
2564 mPendingEvents.size());
2565
gaoshang863ad2f2017-04-20 14:14:18 +08002566 Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, seq, 0, p);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002567 msg.setAsynchronous(true);
2568 mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
2569 return DISPATCH_IN_PROGRESS;
2570 }
2571
2572 Log.w(TAG, "Unable to send input event to IME: "
2573 + mCurId + " dropping: " + event);
2574 }
2575 return DISPATCH_NOT_HANDLED;
2576 }
2577
2578 void finishedInputEvent(int seq, boolean handled, boolean timeout) {
2579 final PendingEvent p;
2580 synchronized (mH) {
2581 int index = mPendingEvents.indexOfKey(seq);
2582 if (index < 0) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002583 return; // spurious, event already finished or timed out
2584 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002585
Jeff Brownf9e989d2013-04-04 23:04:03 -07002586 p = mPendingEvents.valueAt(index);
2587 mPendingEvents.removeAt(index);
2588 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002589
Jeff Brownf9e989d2013-04-04 23:04:03 -07002590 if (timeout) {
2591 Log.w(TAG, "Timeout waiting for IME to handle input event after "
2592 + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
2593 } else {
2594 mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
Jeff Brown4d656882013-04-03 14:39:19 -07002595 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002596 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002597
2598 invokeFinishedInputEventCallback(p, handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002599 }
2600
Jeff Brownf9e989d2013-04-04 23:04:03 -07002601 // Assumes the event has already been removed from the queue.
2602 void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
2603 p.mHandled = handled;
2604 if (p.mHandler.getLooper().isCurrentThread()) {
2605 // Already running on the callback handler thread so we can send the
2606 // callback immediately.
2607 p.run();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002608 } else {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002609 // Post the event to the callback handler thread.
2610 // In this case, the callback will be responsible for recycling the event.
2611 Message msg = Message.obtain(p.mHandler, p);
2612 msg.setAsynchronous(true);
2613 msg.sendToTarget();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 }
satokab751aa2010-09-14 19:17:36 +09002616
Michael Wrightef17e872013-04-01 13:15:55 -07002617 private void flushPendingEventsLocked() {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002618 mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
Jeff Brown4d656882013-04-03 14:39:19 -07002619
Jeff Brownf9e989d2013-04-04 23:04:03 -07002620 final int count = mPendingEvents.size();
2621 for (int i = 0; i < count; i++) {
2622 int seq = mPendingEvents.keyAt(i);
2623 Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
Michael Wrightef17e872013-04-01 13:15:55 -07002624 msg.setAsynchronous(true);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002625 msg.sendToTarget();
Michael Wrightef17e872013-04-01 13:15:55 -07002626 }
2627 }
2628
Jeff Brownf9e989d2013-04-04 23:04:03 -07002629 private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
2630 String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
2631 PendingEvent p = mPendingEventPool.acquire();
2632 if (p == null) {
2633 p = new PendingEvent();
2634 }
2635 p.mEvent = event;
2636 p.mToken = token;
2637 p.mInputMethodId = inputMethodId;
2638 p.mCallback = callback;
2639 p.mHandler = handler;
2640 return p;
2641 }
2642
2643 private void recyclePendingEventLocked(PendingEvent p) {
2644 p.recycle();
2645 mPendingEventPool.release(p);
2646 }
2647
Tarandeep Singh47e49fd2019-03-12 13:39:38 -07002648 /**
2649 * Show IME picker popup window.
2650 *
2651 * <p>Requires the {@link PackageManager#FEATURE_INPUT_METHODS} feature which can be detected
2652 * using {@link PackageManager#hasSystemFeature(String)}.
2653 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 public void showInputMethodPicker() {
2655 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002656 showInputMethodPickerLocked();
2657 }
2658 }
2659
Seigo Nonaka14e13912015-05-06 21:04:13 -07002660 /**
lumark0b05f9e2018-11-26 15:09:06 +08002661 * Shows the input method chooser dialog from system.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002662 *
2663 * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
lumark0b05f9e2018-11-26 15:09:06 +08002664 * @param displayId The ID of the display where the chooser dialog should be shown.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002665 * @hide
2666 */
lumark0b05f9e2018-11-26 15:09:06 +08002667 @RequiresPermission(WRITE_SECURE_SETTINGS)
2668 public void showInputMethodPickerFromSystem(boolean showAuxiliarySubtypes, int displayId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002669 final int mode = showAuxiliarySubtypes
2670 ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
2671 : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
2672 try {
lumark0b05f9e2018-11-26 15:09:06 +08002673 mService.showInputMethodPickerFromSystem(mClient, mode, displayId);
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002674 } catch (RemoteException e) {
2675 throw e.rethrowFromSystemServer();
Seigo Nonaka14e13912015-05-06 21:04:13 -07002676 }
2677 }
2678
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002679 private void showInputMethodPickerLocked() {
2680 try {
Seigo Nonaka14e13912015-05-06 21:04:13 -07002681 mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002682 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07002683 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 }
2685 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08002686
satokd4fce2b2011-04-11 12:07:13 +09002687 /**
Tarandeep Singheb570612018-01-29 16:20:32 -08002688 * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected.
2689 *
2690 * <p>When customizing the implementation of {@link #showInputMethodPicker()} API, make sure
2691 * that this test API returns when and only while and only while
2692 * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not
2693 * pass CTS.</p>
2694 *
2695 * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI.
2696 * @hide
2697 */
2698 @TestApi
2699 public boolean isInputMethodPickerShown() {
2700 try {
2701 return mService.isInputMethodPickerShownForTest();
2702 } catch (RemoteException e) {
2703 throw e.rethrowFromSystemServer();
2704 }
2705 }
2706
2707 /**
satokd4fce2b2011-04-11 12:07:13 +09002708 * Show the settings for enabling subtypes of the specified input method.
2709 * @param imiId An input method, whose subtypes settings will be shown. If imiId is null,
2710 * subtypes of all input methods will be shown.
2711 */
2712 public void showInputMethodAndSubtypeEnabler(String imiId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002713 try {
2714 mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
2715 } catch (RemoteException e) {
2716 throw e.rethrowFromSystemServer();
satok47a44912010-10-06 16:03:58 +09002717 }
2718 }
2719
satokd4fce2b2011-04-11 12:07:13 +09002720 /**
2721 * Returns the current input method subtype. This subtype is one of the subtypes in
2722 * the current input method. This method returns null when the current input method doesn't
2723 * have any input method subtype.
2724 */
satok04d50202010-10-25 22:20:12 +09002725 public InputMethodSubtype getCurrentInputMethodSubtype() {
Gopal Krishna Shuklafa1886f2016-06-30 11:34:21 +05302726 try {
2727 return mService.getCurrentInputMethodSubtype();
2728 } catch (RemoteException e) {
2729 throw e.rethrowFromSystemServer();
satok04d50202010-10-25 22:20:12 +09002730 }
2731 }
2732
satokd4fce2b2011-04-11 12:07:13 +09002733 /**
2734 * Switch to a new input method subtype of the current input method.
2735 * @param subtype A new input method subtype to switch.
2736 * @return true if the current subtype was successfully switched. When the specified subtype is
2737 * null, this method returns false.
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002738 * @deprecated If the calling process is an IME, use
2739 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}, which
2740 * does not require any permission as long as the caller is the current IME.
2741 * If the calling process is some privileged app that already has
2742 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission, just
2743 * directly update {@link Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE}.
satokd4fce2b2011-04-11 12:07:13 +09002744 */
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002745 @Deprecated
Yoshiki Iguchi00d51222015-05-29 15:36:22 +09002746 @RequiresPermission(WRITE_SECURE_SETTINGS)
satokb66d2872010-11-10 01:04:04 +09002747 public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002748 if (Process.myUid() == Process.SYSTEM_UID) {
2749 Log.w(TAG, "System process should not call setCurrentInputMethodSubtype() because "
2750 + "almost always it is a bug under multi-user / multi-profile environment. "
2751 + "Consider directly interacting with InputMethodManagerService "
2752 + "via LocalServices.");
2753 return false;
satokb66d2872010-11-10 01:04:04 +09002754 }
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002755 if (subtype == null) {
2756 // See the JavaDoc. This is how this method has worked.
2757 return false;
2758 }
2759 final Context fallbackContext = ActivityThread.currentApplication();
2760 if (fallbackContext == null) {
2761 return false;
2762 }
2763 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2764 != PackageManager.PERMISSION_GRANTED) {
2765 return false;
2766 }
2767 final ContentResolver contentResolver = fallbackContext.getContentResolver();
2768 final String imeId = Settings.Secure.getString(contentResolver,
2769 Settings.Secure.DEFAULT_INPUT_METHOD);
2770 if (ComponentName.unflattenFromString(imeId) == null) {
2771 // Null or invalid IME ID format.
2772 return false;
2773 }
2774 final List<InputMethodSubtype> enabledSubtypes;
2775 try {
2776 enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true);
2777 } catch (RemoteException e) {
2778 return false;
2779 }
2780 final int numSubtypes = enabledSubtypes.size();
2781 for (int i = 0; i < numSubtypes; ++i) {
2782 final InputMethodSubtype enabledSubtype = enabledSubtypes.get(i);
2783 if (enabledSubtype.equals(subtype)) {
2784 Settings.Secure.putInt(contentResolver,
2785 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, enabledSubtype.hashCode());
2786 return true;
2787 }
2788 }
2789 return false;
satokb66d2872010-11-10 01:04:04 +09002790 }
2791
satokd4fce2b2011-04-11 12:07:13 +09002792 /**
Yohei Yukawa02970512014-06-05 16:16:18 +09002793 * Notify that a user took some action with this input method.
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002794 *
2795 * @deprecated Just kept to avoid possible app compat issue.
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002796 * @hide
2797 */
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002798 @Deprecated
Yohei Yukawaa086f952018-09-11 11:37:08 -07002799 @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
Yohei Yukawa02970512014-06-05 16:16:18 +09002800 public void notifyUserAction() {
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002801 Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
2802 + " that does nothing. Leave comments in b.android.com/114740982 if your "
2803 + " application still depends on the previous behavior of this method.");
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002804 }
2805
2806 /**
satokd4fce2b2011-04-11 12:07:13 +09002807 * Returns a map of all shortcut input method info and their subtypes.
2808 */
satokf3db1af2010-11-23 13:34:33 +09002809 public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
Yohei Yukawafefedc52018-12-24 19:43:17 -08002810 final List<InputMethodInfo> enabledImes = getEnabledInputMethodList();
2811
2812 // Ensure we check system IMEs first.
2813 enabledImes.sort(Comparator.comparingInt(imi -> imi.isSystem() ? 0 : 1));
2814
2815 final int numEnabledImes = enabledImes.size();
2816 for (int imiIndex = 0; imiIndex < numEnabledImes; ++imiIndex) {
2817 final InputMethodInfo imi = enabledImes.get(imiIndex);
2818 final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(
2819 imi, true);
2820 final int subtypeCount = subtypes.size();
2821 for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
2822 final InputMethodSubtype subtype = imi.getSubtypeAt(subtypeIndex);
2823 if (SUBTYPE_MODE_VOICE.equals(subtype.getMode())) {
2824 return Collections.singletonMap(imi, Collections.singletonList(subtype));
satok4e4569d2010-11-19 18:45:53 +09002825 }
satok4e4569d2010-11-19 18:45:53 +09002826 }
satok4e4569d2010-11-19 18:45:53 +09002827 }
Yohei Yukawafefedc52018-12-24 19:43:17 -08002828 return Collections.emptyMap();
satok4e4569d2010-11-19 18:45:53 +09002829 }
satokf3db1af2010-11-23 13:34:33 +09002830
satokd4fce2b2011-04-11 12:07:13 +09002831 /**
Yohei Yukawab985e6e2018-09-05 17:07:52 -07002832 * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
2833 *
2834 * <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
2835 * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
2836 * started relying on it.</p>
2837 *
2838 * @return Something that is not well-defined.
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002839 * @hide
2840 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002841 @UnsupportedAppUsage
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002842 public int getInputMethodWindowVisibleHeight() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002843 try {
2844 return mService.getInputMethodWindowVisibleHeight();
2845 } catch (RemoteException e) {
2846 throw e.rethrowFromSystemServer();
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002847 }
2848 }
2849
2850 /**
Yohei Yukawab4f328a2019-05-02 08:41:27 -07002851 * An internal API for {@link android.app.ActivityView} to report where its embedded virtual
2852 * display is placed.
2853 *
2854 * @param childDisplayId Display ID of the embedded virtual display.
2855 * @param matrix {@link Matrix} to convert virtual display screen coordinates to
2856 * the host screen coordinates. {@code null} to clear the relationship.
2857 * @hide
2858 */
2859 public void reportActivityView(int childDisplayId, @Nullable Matrix matrix) {
2860 try {
2861 final float[] matrixValues;
2862 if (matrix == null) {
2863 matrixValues = null;
2864 } else {
2865 matrixValues = new float[9];
2866 matrix.getValues(matrixValues);
2867 }
2868 mService.reportActivityView(mClient, childDisplayId, matrixValues);
2869 } catch (RemoteException e) {
2870 throw e.rethrowFromSystemServer();
2871 }
2872 }
2873
2874 /**
satokd4fce2b2011-04-11 12:07:13 +09002875 * Force switch to the last used input method and subtype. If the last input method didn't have
2876 * any subtypes, the framework will simply switch to the last input method with no subtype
2877 * specified.
2878 * @param imeToken Supplies the identifying token given to an input method when it was started,
2879 * which allows it to perform this operation on itself.
2880 * @return true if the current input method and subtype was successfully switched to the last
2881 * used input method and subtype.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002882 * @deprecated Use {@link InputMethodService#switchToPreviousInputMethod()} instead. This method
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002883 * was intended for IME developers who should be accessing APIs through the service. APIs in
2884 * this class are intended for app developers interacting with the IME.
satokd4fce2b2011-04-11 12:07:13 +09002885 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002886 @Deprecated
satok735cf382010-11-11 20:40:09 +09002887 public boolean switchToLastInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002888 return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod();
satok735cf382010-11-11 20:40:09 +09002889 }
2890
satoke7c6998e2011-06-03 17:57:59 +09002891 /**
satok688bd472012-02-09 20:09:17 +09002892 * Force switch to the next input method and subtype. If there is no IME enabled except
2893 * current IME and subtype, do nothing.
2894 * @param imeToken Supplies the identifying token given to an input method when it was started,
2895 * which allows it to perform this operation on itself.
2896 * @param onlyCurrentIme if true, the framework will find the next subtype which
2897 * belongs to the current IME
2898 * @return true if the current input method and subtype was successfully switched to the next
2899 * input method and subtype.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002900 * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
2901 * method was intended for IME developers who should be accessing APIs through the service.
2902 * APIs in this class are intended for app developers interacting with the IME.
satok688bd472012-02-09 20:09:17 +09002903 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002904 @Deprecated
satok688bd472012-02-09 20:09:17 +09002905 public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002906 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
2907 .switchToNextInputMethod(onlyCurrentIme);
satok688bd472012-02-09 20:09:17 +09002908 }
2909
2910 /**
satok15ab6b02013-08-26 14:17:18 +09002911 * Returns true if the current IME needs to offer the users ways to switch to a next input
2912 * method (e.g. a globe key.).
2913 * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
2914 * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
2915 * <p> Note that the system determines the most appropriate next input method
2916 * and subtype in order to provide the consistent user experience in switching
2917 * between IMEs and subtypes.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002918 * @param imeToken Supplies the identifying token given to an input method when it was started,
2919 * which allows it to perform this operation on itself.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002920 * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
2921 * instead. This method was intended for IME developers who should be accessing APIs through
2922 * the service. APIs in this class are intended for app developers interacting with the IME.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002923 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002924 @Deprecated
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002925 public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002926 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
2927 .shouldOfferSwitchingToNextInputMethod();
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002928 }
2929
2930 /**
satok91e88122011-07-18 11:11:42 +09002931 * Set additional input method subtypes. Only a process which shares the same uid with the IME
2932 * can add additional input method subtypes to the IME.
satok75917b62011-08-31 23:27:39 +09002933 * Please note that a subtype's status is stored in the system.
2934 * For example, enabled subtypes are remembered by the framework even after they are removed
2935 * by using this method. If you re-add the same subtypes again,
2936 * they will just get enabled. If you want to avoid such conflicts, for instance, you may
2937 * want to create a "different" new subtype even with the same locale and mode,
2938 * by changing its extra value. The different subtype won't get affected by the stored past
2939 * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
2940 * to the current implementation.)
Yohei Yukawa70f5c482016-01-04 19:42:36 -08002941 *
2942 * <p>NOTE: If the same subtype exists in both the manifest XML file and additional subtypes
2943 * specified by {@code subtypes}, those multiple instances are automatically merged into one
2944 * instance.</p>
2945 *
2946 * <p>CAVEAT: In API Level 23 and prior, the system may do nothing if an empty
2947 * {@link InputMethodSubtype} is specified in {@code subtypes}, which prevents you from removing
2948 * the last one entry of additional subtypes. If your IME statically defines one or more
2949 * subtypes in the manifest XML file, you may be able to work around this limitation by
2950 * specifying one of those statically defined subtypes in {@code subtypes}.</p>
2951 *
satok91e88122011-07-18 11:11:42 +09002952 * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
satoke7c6998e2011-06-03 17:57:59 +09002953 * @param subtypes subtypes will be added as additional subtypes of the current input method.
Yohei Yukawa92c15b12019-01-22 13:26:45 -08002954 * @deprecated For IMEs that have already implemented features like customizable/downloadable
2955 * keyboard layouts/languages, please start migration to other approaches. One idea
2956 * would be exposing only one unified {@link InputMethodSubtype} then implement
2957 * IME's own language switching mechanism within that unified subtype. The support
2958 * of "Additional Subtype" may be completely dropped in a future version of Android.
satoke7c6998e2011-06-03 17:57:59 +09002959 */
Yohei Yukawa92c15b12019-01-22 13:26:45 -08002960 @Deprecated
satokee5e77c2011-09-02 18:50:15 +09002961 public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002962 try {
2963 mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
2964 } catch (RemoteException e) {
2965 throw e.rethrowFromSystemServer();
satoke7c6998e2011-06-03 17:57:59 +09002966 }
2967 }
2968
satok68f1b782011-04-11 14:26:04 +09002969 public InputMethodSubtype getLastInputMethodSubtype() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002970 try {
2971 return mService.getLastInputMethodSubtype();
2972 } catch (RemoteException e) {
2973 throw e.rethrowFromSystemServer();
satok68f1b782011-04-11 14:26:04 +09002974 }
2975 }
2976
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08002977 private void maybeCallServedViewChangedLocked(EditorInfo tba) {
2978 if (mImeInsetsConsumer != null) {
2979 mImeInsetsConsumer.onServedEditorChanged(tba);
2980 }
2981 }
2982
Charles Chen414820e2019-04-15 15:33:26 +08002983 /**
2984 * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
2985 * @return the ID of this display which this {@link InputMethodManager} resides
2986 * @hide
2987 */
2988 @TestApi
2989 public int getDisplayId() {
2990 return mDisplayId;
2991 }
2992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
2994 final Printer p = new PrintWriterPrinter(fout);
2995 p.println("Input method client state for " + this + ":");
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 p.println(" mService=" + mService);
2998 p.println(" mMainLooper=" + mMainLooper);
2999 p.println(" mIInputContext=" + mIInputContext);
3000 p.println(" mActive=" + mActive
Yohei Yukawa2553e482017-12-15 15:47:33 -08003001 + " mRestartOnNextWindowFocus=" + mRestartOnNextWindowFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 + " mBindSequence=" + mBindSequence
3003 + " mCurId=" + mCurId);
Yohei Yukawa2bc66172017-02-08 11:13:25 -08003004 p.println(" mFullscreenMode=" + mFullscreenMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 p.println(" mCurMethod=" + mCurMethod);
Wale Ogunwale159c3d82015-05-14 12:20:53 -07003006 p.println(" mCurRootView=" + mCurRootView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003007 p.println(" mServedView=" + mServedView);
Dianne Hackborn7663d802012-02-24 13:08:49 -08003008 p.println(" mNextServedView=" + mNextServedView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 p.println(" mServedConnecting=" + mServedConnecting);
3010 if (mCurrentTextBoxAttribute != null) {
3011 p.println(" mCurrentTextBoxAttribute:");
3012 mCurrentTextBoxAttribute.dump(p, " ");
3013 } else {
3014 p.println(" mCurrentTextBoxAttribute: null");
3015 }
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07003016 p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
Andreas Gampee6748ce2015-12-11 18:00:38 -08003017 p.println(" mCompletions=" + Arrays.toString(mCompletions));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 p.println(" mCursorRect=" + mCursorRect);
3019 p.println(" mCursorSelStart=" + mCursorSelStart
3020 + " mCursorSelEnd=" + mCursorSelEnd
3021 + " mCursorCandStart=" + mCursorCandStart
3022 + " mCursorCandEnd=" + mCursorCandEnd);
3023 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003024
3025 /**
3026 * Callback that is invoked when an input event that was dispatched to
3027 * the IME has been finished.
3028 * @hide
3029 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07003030 public interface FinishedInputEventCallback {
3031 public void onFinishedInputEvent(Object token, boolean handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003032 }
3033
Jeff Brownc28867a2013-03-26 15:42:39 -07003034 private final class ImeInputEventSender extends InputEventSender {
3035 public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
3036 super(inputChannel, looper);
3037 }
3038
3039 @Override
3040 public void onInputEventFinished(int seq, boolean handled) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07003041 finishedInputEvent(seq, handled, false);
Jeff Brownc28867a2013-03-26 15:42:39 -07003042 }
3043 }
3044
Jeff Brownf9e989d2013-04-04 23:04:03 -07003045 private final class PendingEvent implements Runnable {
3046 public InputEvent mEvent;
3047 public Object mToken;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003048 public String mInputMethodId;
Jeff Brownf9e989d2013-04-04 23:04:03 -07003049 public FinishedInputEventCallback mCallback;
3050 public Handler mHandler;
3051 public boolean mHandled;
3052
3053 public void recycle() {
3054 mEvent = null;
3055 mToken = null;
3056 mInputMethodId = null;
3057 mCallback = null;
3058 mHandler = null;
3059 mHandled = false;
3060 }
3061
3062 @Override
3063 public void run() {
3064 mCallback.onFinishedInputEvent(mToken, mHandled);
3065
3066 synchronized (mH) {
3067 recyclePendingEventLocked(this);
3068 }
3069 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003070 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003071
3072 private static String dumpViewInfo(@Nullable final View view) {
3073 if (view == null) {
3074 return "null";
3075 }
3076 final StringBuilder sb = new StringBuilder();
3077 sb.append(view);
3078 sb.append(",focus=" + view.hasFocus());
3079 sb.append(",windowFocus=" + view.hasWindowFocus());
Dake Guddf6c1e2018-05-10 11:41:19 -07003080 sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003081 sb.append(",window=" + view.getWindowToken());
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08003082 sb.append(",displayId=" + view.getContext().getDisplayId());
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07003083 sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003084 return sb.toString();
3085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086}