blob: aedb59bfee42288f06ef0d12b4a003a2a8652019 [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
Ming-Shin Lu48bfc312020-06-15 20:06:09 +080022import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR;
23import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR;
24
Yohei Yukawa41b094f2018-09-09 23:58:45 -070025import android.annotation.DrawableRes;
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -080026import android.annotation.NonNull;
27import android.annotation.Nullable;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070028import android.annotation.RequiresFeature;
Yoshiki Iguchi00d51222015-05-29 15:36:22 +090029import android.annotation.RequiresPermission;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060030import android.annotation.SystemService;
Tarandeep Singheb570612018-01-29 16:20:32 -080031import android.annotation.TestApi;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080032import android.annotation.UserIdInt;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080033import android.app.ActivityThread;
Artur Satayevad9254c2019-12-10 17:47:54 +000034import android.compat.annotation.UnsupportedAppUsage;
Yohei Yukawafd8f7212019-01-22 19:25:44 -080035import android.content.ComponentName;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080036import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.Context;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070038import android.content.pm.PackageManager;
Yohei Yukawab4f328a2019-05-02 08:41:27 -070039import android.graphics.Matrix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.graphics.Rect;
Tarandeep Singhd8d03a82017-11-28 13:35:32 -080041import android.inputmethodservice.InputMethodService;
Yohei Yukawacb768bc2018-10-24 16:05:09 -070042import android.os.Binder;
Yohei Yukawaa086f952018-09-11 11:37:08 -070043import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.os.Bundle;
45import android.os.Handler;
46import android.os.IBinder;
47import android.os.Looper;
48import android.os.Message;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080049import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.os.RemoteException;
The Android Open Source Project4df24232009-03-05 14:34:35 -080051import android.os.ResultReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060053import android.os.ServiceManager.ServiceNotFoundException;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070054import android.os.Trace;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080055import android.os.UserHandle;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080056import android.provider.Settings;
satokf9f01002011-05-19 21:31:50 +090057import android.text.style.SuggestionSpan;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.util.Log;
Jeff Brownf9e989d2013-04-04 23:04:03 -070059import android.util.Pools.Pool;
60import android.util.Pools.SimplePool;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.util.PrintWriterPrinter;
62import android.util.Printer;
Yohei Yukawab7b79072014-03-25 11:02:00 +090063import android.util.SparseArray;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +080064import android.view.Display;
lumark3f733cc2020-01-20 12:14:04 +080065import android.view.ImeFocusController;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -080066import android.view.ImeInsetsSourceConsumer;
Jeff Brownc28867a2013-03-26 15:42:39 -070067import android.view.InputChannel;
68import android.view.InputEvent;
69import android.view.InputEventSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.view.KeyEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.view.View;
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070072import android.view.ViewRootImpl;
Yohei Yukawa22dac1c2017-02-12 16:54:16 -080073import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
Dake Guddf6c1e2018-05-10 11:41:19 -070074import android.view.autofill.AutofillManager;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070075
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -070076import com.android.internal.annotations.GuardedBy;
Yohei Yukawaa468d702018-10-21 11:42:34 -070077import com.android.internal.inputmethod.InputMethodDebug;
Yohei Yukawaeec552e2018-09-09 20:48:41 -070078import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
Yohei Yukawa35fa6d52018-10-31 11:33:32 -070079import com.android.internal.inputmethod.StartInputFlags;
Yohei Yukawac6632df2018-10-21 11:47:16 -070080import com.android.internal.inputmethod.StartInputReason;
Yohei Yukawa499e3f72018-10-21 20:15:11 -070081import com.android.internal.inputmethod.UnbindReason;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070082import com.android.internal.os.SomeArgs;
83import com.android.internal.view.IInputConnectionWrapper;
84import com.android.internal.view.IInputContext;
85import com.android.internal.view.IInputMethodClient;
86import com.android.internal.view.IInputMethodManager;
87import com.android.internal.view.IInputMethodSession;
88import com.android.internal.view.InputBindResult;
Gilles Debunned4723bb2010-09-02 15:27:32 -070089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import java.io.FileDescriptor;
91import java.io.PrintWriter;
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -070092import java.lang.reflect.Proxy;
Andreas Gampee6748ce2015-12-11 18:00:38 -080093import java.util.Arrays;
Yohei Yukawafefedc52018-12-24 19:43:17 -080094import java.util.Collections;
95import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import java.util.List;
satokf3db1af2010-11-23 13:34:33 +090097import java.util.Map;
Yohei Yukawac941fed2014-05-14 19:33:35 +090098import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import java.util.concurrent.CountDownLatch;
lumarkba400442020-01-09 01:37:05 +0800100import java.util.concurrent.ThreadFactory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import java.util.concurrent.TimeUnit;
102
103/**
104 * Central system API to the overall input method framework (IMF) architecture,
105 * which arbitrates interaction between applications and the current input method.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700106 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 * <p>Topics covered here:
108 * <ol>
109 * <li><a href="#ArchitectureOverview">Architecture Overview</a>
Ken Wakasa384f8ba2012-03-10 09:59:31 +0900110 * <li><a href="#Applications">Applications</a>
111 * <li><a href="#InputMethods">Input Methods</a>
112 * <li><a href="#Security">Security</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 * </ol>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700114 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 * <a name="ArchitectureOverview"></a>
116 * <h3>Architecture Overview</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700117 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 * <p>There are three primary parties involved in the input method
119 * framework (IMF) architecture:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700120 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 * <ul>
122 * <li> The <strong>input method manager</strong> as expressed by this class
123 * is the central point of the system that manages interaction between all
124 * other parts. It is expressed as the client-side API here which exists
125 * in each application context and communicates with a global system service
126 * that manages the interaction across all processes.
127 * <li> An <strong>input method (IME)</strong> implements a particular
128 * interaction model allowing the user to generate text. The system binds
Nick Felker8efc3ee2017-06-26 15:50:19 -0700129 * 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 -0800130 * and tells it when to hide and show its UI. Only one IME is running at a time.
131 * <li> Multiple <strong>client applications</strong> arbitrate with the input
132 * method manager for input focus and control over the state of the IME. Only
133 * one such client is ever active (working with the IME) at a time.
134 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700135 *
136 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 * <a name="Applications"></a>
138 * <h3>Applications</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700139 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 * <p>In most cases, applications that are using the standard
141 * {@link android.widget.TextView} or its subclasses will have little they need
142 * to do to work well with soft input methods. The main things you need to
143 * be aware of are:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700144 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 * <ul>
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800146 * <li> Properly set the {@link android.R.attr#inputType} in your editable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 * text views, so that the input method will have enough context to help the
148 * user in entering text into them.
149 * <li> Deal well with losing screen space when the input method is
150 * displayed. Ideally an application should handle its window being resized
151 * smaller, but it can rely on the system performing panning of the window
152 * if needed. You should set the {@link android.R.attr#windowSoftInputMode}
153 * attribute on your activity or the corresponding values on windows you
154 * create to help the system determine whether to pan or resize (it will
155 * try to determine this automatically but may get it wrong).
156 * <li> You can also control the preferred soft input state (open, closed, etc)
157 * for your window using the same {@link android.R.attr#windowSoftInputMode}
158 * attribute.
159 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700160 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 * <p>More finer-grained control is available through the APIs here to directly
162 * interact with the IMF and its IME -- either showing or hiding the input
163 * area, letting the user pick an input method, etc.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700164 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 * <p>For the rare people amongst us writing their own text editors, you
166 * will need to implement {@link android.view.View#onCreateInputConnection}
167 * to return a new instance of your own {@link InputConnection} interface
168 * allowing the IME to interact with your editor.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700169 *
170 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 * <a name="InputMethods"></a>
172 * <h3>Input Methods</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700173 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 * <p>An input method (IME) is implemented
175 * as a {@link android.app.Service}, typically deriving from
176 * {@link android.inputmethodservice.InputMethodService}. It must provide
177 * the core {@link InputMethod} interface, though this is normally handled by
178 * {@link android.inputmethodservice.InputMethodService} and implementors will
179 * only need to deal with the higher-level API there.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700180 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 * See the {@link android.inputmethodservice.InputMethodService} class for
182 * more information on implementing IMEs.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700183 *
184 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 * <a name="Security"></a>
186 * <h3>Security</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700187 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 * <p>There are a lot of security issues associated with input methods,
189 * since they essentially have freedom to completely drive the UI and monitor
190 * everything the user enters. The Android input method framework also allows
191 * arbitrary third party IMEs, so care must be taken to restrict their
192 * selection and interactions.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700193 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 * <p>Here are some key points about the security architecture behind the
195 * IMF:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700196 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 * <ul>
198 * <li> <p>Only the system is allowed to directly access an IME's
199 * {@link InputMethod} interface, via the
200 * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission. This is
201 * enforced in the system by not binding to an input method service that does
202 * not require this permission, so the system can guarantee no other untrusted
203 * clients are accessing the current input method outside of its control.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700204 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 * <li> <p>There may be many client processes of the IMF, but only one may
206 * be active at a time. The inactive clients can not interact with key
207 * parts of the IMF through the mechanisms described below.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700208 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 * <li> <p>Clients of an input method are only given access to its
210 * {@link InputMethodSession} interface. One instance of this interface is
211 * created for each client, and only calls from the session associated with
212 * the active client will be processed by the current IME. This is enforced
213 * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
214 * IMEs, but must be explicitly handled by an IME that is customizing the
215 * raw {@link InputMethodSession} implementation.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700216 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 * <li> <p>Only the active client's {@link InputConnection} will accept
218 * operations. The IMF tells each client process whether it is active, and
219 * the framework enforces that in inactive processes calls on to the current
220 * InputConnection will be ignored. This ensures that the current IME can
221 * only deliver events and text edits to the UI that the user sees as
222 * being in focus.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700223 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * <li> <p>An IME can never interact with an {@link InputConnection} while
225 * the screen is off. This is enforced by making all clients inactive while
226 * the screen is off, and prevents bad IMEs from driving the UI when the user
227 * can not be aware of its behavior.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700228 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 * <li> <p>A client application can ask that the system let the user pick a
230 * new IME, but can not programmatically switch to one itself. This avoids
231 * malicious applications from switching the user to their own IME, which
232 * remains running when the user navigates away to another application. An
233 * IME, on the other hand, <em>is</em> allowed to programmatically switch
234 * the system to another IME, since it already has full control of user
235 * input.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700236 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 * <li> <p>The user must explicitly enable a new IME in settings before
238 * they can switch to it, to confirm with the system that they know about it
239 * and want to make it available for use.</p>
240 * </ul>
241 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600242@SystemService(Context.INPUT_METHOD_SERVICE)
Jeff Sharkey98af2e42018-02-16 10:14:57 -0700243@RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244public final class InputMethodManager {
Dianne Hackborn4eba2712009-03-24 19:20:06 -0700245 static final boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 static final String TAG = "InputMethodManager";
247
Jeff Brownf9e989d2013-04-04 23:04:03 -0700248 static final String PENDING_EVENT_COUNTER = "aq:imm";
249
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -0800250 private static final int NOT_A_SUBTYPE_ID = -1;
251
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700252 /**
Yohei Yukawafefedc52018-12-24 19:43:17 -0800253 * A constant that represents Voice IME.
254 *
255 * @see InputMethodSubtype#getMode()
256 */
257 private static final String SUBTYPE_MODE_VOICE = "voice";
258
259 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700260 * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
261 * or indirectly relied on {@link #sInstance} via reflection or something like that.
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700262 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700263 * <p>Here are scenarios we know and there could be more scenarios we are not
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700264 * aware of right know.</p>
265 *
266 * <ul>
267 * <li>Apps that directly access {@link #sInstance} via reflection, which is currently
268 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
269 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
270 * {@link #sInstance} is not {@code null} when such an app is accessing it, but removing
271 * that code from {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal
272 * untested code paths in their apps, which probably happen in an early startup time of that
273 * app.</li>
274 * <li>Apps that directly access {@link #peekInstance()} via reflection, which is currently
275 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
276 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
277 * {@link #peekInstance()} returns non-{@code null} object when such an app is calling
278 * {@link #peekInstance()}, but removing that code from
279 * {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal untested code
280 * paths in their apps, which probably happen in an early startup time of that app. The good
281 * news is that unlike {@link #sInstance}'s case we can at least work around this scenario
282 * by changing the semantics of {@link #peekInstance()}, which is currently defined as
283 * "retrieve the global {@link InputMethodManager} instance, if it exists" to something that
284 * always returns non-{@code null} {@link InputMethodManager}. However, introducing such an
285 * workaround can also trigger different compatibility issues if {@link #peekInstance()} was
286 * called before {@link android.view.WindowManagerGlobal#getWindowSession()} and it expected
287 * {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li>
288 * </ul>
289 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700290 * <p>Since this is purely a compatibility hack, this method must be used only from
291 * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p>
292 *
293 * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p>
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700294 * @hide
295 */
Yohei Yukawa6c075722018-09-21 14:52:12 -0700296 public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800297 forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
Yohei Yukawa6c075722018-09-21 14:52:12 -0700298 }
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700299
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700300 private static final Object sLock = new Object();
301
Yohei Yukawa6c075722018-09-21 14:52:12 -0700302 /**
303 * @deprecated This cannot be compatible with multi-display. Please do not use this.
304 */
305 @Deprecated
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700306 @GuardedBy("sLock")
Mathew Inwooda570dee2018-08-17 14:56:00 +0100307 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -0700308 static InputMethodManager sInstance;
Dianne Hackborn7663d802012-02-24 13:08:49 -0800309
310 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800311 * Global map between display to {@link InputMethodManager}.
312 *
313 * <p>Currently this map works like a so-called leaky singleton. Once an instance is registered
314 * for the associated display ID, that instance will never be garbage collected.</p>
315 *
316 * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
317 */
318 @GuardedBy("sLock")
319 private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
320
321 /**
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700322 * Timeout in milliseconds for delivering a key to an IME.
323 */
324 static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
325
Jeff Brownf9e989d2013-04-04 23:04:03 -0700326 /** @hide */
327 public static final int DISPATCH_IN_PROGRESS = -1;
328
329 /** @hide */
330 public static final int DISPATCH_NOT_HANDLED = 0;
331
332 /** @hide */
333 public static final int DISPATCH_HANDLED = 1;
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700334
Seigo Nonaka14e13912015-05-06 21:04:13 -0700335 /** @hide */
336 public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
337 /** @hide */
338 public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
339 /** @hide */
340 public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
341
Mathew Inwooda570dee2018-08-17 14:56:00 +0100342 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 final IInputMethodManager mService;
344 final Looper mMainLooper;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 // For scheduling work on the main thread. This also serves as our
347 // global lock.
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000348 // Remark on @UnsupportedAppUsage: there were context leaks on old versions
349 // of android (b/37043700), so developers used this field to perform manual clean up.
350 // Leaks were fixed, hacks were backported to AppCompatActivity,
351 // so an access to the field is closed.
352 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 final H mH;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 // Our generic input connection if the current target does not have its own.
356 final IInputContext mIInputContext;
357
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800358 private final int mDisplayId;
359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 /**
361 * True if this input method client is active, initially false.
362 */
363 boolean mActive = false;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 /**
lumark970d9d22019-08-18 17:45:24 +0800366 * {@code true} if next {@link ImeFocusController#onPostWindowFocus} needs to
Yohei Yukawa2553e482017-12-15 15:47:33 -0800367 * restart input.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 */
lumark970d9d22019-08-18 17:45:24 +0800369 private boolean mRestartOnNextWindowFocus = true;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 /**
372 * As reported by IME through InputConnection.
373 */
374 boolean mFullscreenMode;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700377
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700378 /**
379 * This is the root view of the overall window that currently has input
380 * method focus.
381 */
lumark970d9d22019-08-18 17:45:24 +0800382 @GuardedBy("mH")
383 ViewRootImpl mCurRootView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 * This is set when we are in the process of connecting, to determine
386 * when we have actually finished.
387 */
388 boolean mServedConnecting;
389 /**
390 * This is non-null when we have connected the served view; it holds
391 * the attributes that were last retrieved from the served view and given
392 * to the input connection.
393 */
394 EditorInfo mCurrentTextBoxAttribute;
395 /**
396 * The InputConnection that was last retrieved from the served view.
397 */
Mathew Inwood8c854f82018-09-14 12:35:36 +0100398 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackbornac920872012-05-22 11:49:49 -0700399 ControlledInputConnectionWrapper mServedInputConnectionWrapper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 /**
401 * The completions that were last provided by the served view.
402 */
403 CompletionInfo[] mCompletions;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 // Cursor position on the screen.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100406 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -0700407 Rect mTmpCursorRect = new Rect();
Mathew Inwooda570dee2018-08-17 14:56:00 +0100408 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 Rect mCursorRect = new Rect();
410 int mCursorSelStart;
411 int mCursorSelEnd;
412 int mCursorCandStart;
413 int mCursorCandEnd;
Yohei Yukawa056ffe62014-05-13 14:26:09 +0900414
415 /**
416 * The instance that has previously been sent to the input method.
417 */
418 private CursorAnchorInfo mCursorAnchorInfo = null;
419
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700420 /**
421 * A special {@link Matrix} that can be provided by the system when this instance is running
422 * inside a virtual display that is managed by {@link android.app.ActivityView}.
423 *
424 * <p>If this is non-{@code null}, {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}
425 * should be adjusted with this {@link Matrix}.</p>
426 *
427 * <p>{@code null} when not used.</p>
428 */
429 private Matrix mActivityViewToScreenMatrix = null;
430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 // -----------------------------------------------------------
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 /**
434 * Sequence number of this binding, as returned by the server.
435 */
436 int mBindSequence = -1;
437 /**
438 * ID of the method we are bound to.
439 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100440 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 String mCurId;
442 /**
443 * The actual instance of the method to make calls on it.
444 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100445 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 IInputMethodSession mCurMethod;
Jeff Brownc28867a2013-03-26 15:42:39 -0700447 InputChannel mCurChannel;
448 ImeInputEventSender mCurSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449
Yohei Yukawaa277db22014-08-21 18:38:44 -0700450 private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900451
452 /**
453 * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
454 */
Yohei Yukawaa277db22014-08-21 18:38:44 -0700455 private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawab7b79072014-03-25 11:02:00 +0900456
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800457 /**
458 * When {@link ViewRootImpl#sNewInsetsMode} is set to
459 * >= {@link ViewRootImpl#NEW_INSETS_MODE_IME}, {@link ImeInsetsSourceConsumer} applies the
460 * IME visibility and listens for other state changes.
461 */
462 private ImeInsetsSourceConsumer mImeInsetsConsumer;
463
Yohei Yukawab0377bb2015-08-10 21:06:30 -0700464 final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
465 final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700466
lumark970d9d22019-08-18 17:45:24 +0800467 final DelegateImpl mDelegate = new DelegateImpl();
468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 static final int MSG_DUMP = 1;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800472 static final int MSG_BIND = 2;
473 static final int MSG_UNBIND = 3;
474 static final int MSG_SET_ACTIVE = 4;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700475 static final int MSG_SEND_INPUT_EVENT = 5;
476 static final int MSG_TIMEOUT_INPUT_EVENT = 6;
477 static final int MSG_FLUSH_INPUT_EVENT = 7;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800478 static final int MSG_REPORT_FULLSCREEN_MODE = 10;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800479 static final int MSG_REPORT_PRE_RENDERED = 15;
480 static final int MSG_APPLY_IME_VISIBILITY = 20;
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700481 static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700482
Dake Guddf6c1e2018-05-10 11:41:19 -0700483 private static boolean isAutofillUIShowing(View servedView) {
484 AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
485 return afm != null && afm.isAutofillUiShowing();
486 }
487
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800488 /**
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700489 * Returns fallback {@link InputMethodManager} if the called one is not likely to be compatible
490 * with the given {@code view}.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800491 *
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700492 * @param view {@link View} to be checked.
493 * @return {@code null} when it is unnecessary (or impossible) to use fallback
494 * {@link InputMethodManager} to which IME API calls need to be re-dispatched.
495 * Non-{@code null} {@link InputMethodManager} if this method believes it'd be safer to
496 * re-dispatch IME APIs calls on it.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800497 */
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700498 @Nullable
499 private InputMethodManager getFallbackInputMethodManagerIfNecessary(@Nullable View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800500 if (view == null) {
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700501 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800502 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700503 // As evidenced in Bug 118341760, view.getViewRootImpl().getDisplayId() is supposed to be
504 // more reliable to determine with which display the given view is interacting than
505 // view.getContext().getDisplayId() / view.getContext().getSystemService(), which can be
506 // easily messed up by app developers (or library authors) by creating inconsistent
507 // ContextWrapper objects that re-dispatch those methods to other Context such as
508 // ApplicationContext.
509 final ViewRootImpl viewRootImpl = view.getViewRootImpl();
510 if (viewRootImpl == null) {
511 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800512 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700513 final int viewRootDisplayId = viewRootImpl.getDisplayId();
514 if (viewRootDisplayId == mDisplayId) {
515 // Expected case. Good to go.
516 return null;
517 }
518 final InputMethodManager fallbackImm =
Charles Chen5299ad02019-04-18 13:09:53 +0000519 viewRootImpl.mContext.getSystemService(InputMethodManager.class);
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700520 if (fallbackImm == null) {
Michael Klimushyna9427152019-09-30 14:00:56 -0700521 Log.v(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700522 return null;
523 }
524 if (fallbackImm.mDisplayId != viewRootDisplayId) {
Michael Klimushyna9427152019-09-30 14:00:56 -0700525 Log.v(TAG, "b/117267690: Failed to get fallback IMM with expected displayId="
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700526 + viewRootDisplayId + " actual IMM#displayId=" + fallbackImm.mDisplayId
527 + " view=" + view);
528 return null;
529 }
Michael Klimushyna9427152019-09-30 14:00:56 -0700530 Log.v(TAG, "b/117267690: Display ID mismatch found."
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700531 + " ViewRootImpl displayId=" + viewRootDisplayId
532 + " InputMethodManager displayId=" + mDisplayId
533 + ". Use the right InputMethodManager instance to avoid performance overhead.",
534 new Throwable());
535 return fallbackImm;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800536 }
537
Dake Guddf6c1e2018-05-10 11:41:19 -0700538 private static boolean canStartInput(View servedView) {
539 // We can start input ether the servedView has window focus
540 // or the activity is showing autofill ui.
541 return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
542 }
543
Adrian Roosc22eec92020-06-12 18:48:10 +0200544 /**
545 * Reports whether the IME is currently perceptible or not, according to the leash applied by
546 * {@link android.view.WindowInsetsController}.
547 * @hide
548 */
549 public void reportPerceptible(IBinder windowToken, boolean perceptible) {
550 try {
551 mService.reportPerceptible(windowToken, perceptible);
552 } catch (RemoteException e) {
553 throw e.rethrowFromSystemServer();
554 }
555 }
556
lumark970d9d22019-08-18 17:45:24 +0800557 private final class DelegateImpl implements
558 ImeFocusController.InputMethodManagerDelegate {
559 /**
560 * Used by {@link ImeFocusController} to start input connection.
561 */
562 @Override
563 public boolean startInput(@StartInputReason int startInputReason, View focusedView,
564 @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
565 int windowFlags) {
lumark3f733cc2020-01-20 12:14:04 +0800566 final View servedView;
lumark970d9d22019-08-18 17:45:24 +0800567 synchronized (mH) {
568 mCurrentTextBoxAttribute = null;
569 mCompletions = null;
570 mServedConnecting = true;
lumark3f733cc2020-01-20 12:14:04 +0800571 servedView = getServedViewLocked();
572 }
573 if (servedView != null && servedView.getHandler() != null) {
574 // Make sure View checks should be on the UI thread.
575 servedView.getHandler().post(() -> {
576 if (!servedView.onCheckIsTextEditor()) {
577 // servedView has changed and it's not editable.
578 synchronized (mH) {
579 maybeCallServedViewChangedLocked(null);
580 }
581 }
582 });
lumark970d9d22019-08-18 17:45:24 +0800583 }
584 return startInputInner(startInputReason,
585 focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
586 softInputMode, windowFlags);
587 }
588
589 /**
590 * Used by {@link ImeFocusController} to finish input connection.
591 */
592 @Override
593 public void finishInput() {
594 synchronized (mH) {
595 finishInputLocked();
596 }
597 }
598
599 /**
600 * Used by {@link ImeFocusController} to hide current input method editor.
601 */
602 @Override
603 public void closeCurrentIme() {
604 closeCurrentInput();
605 }
606
607 /**
608 * For {@link ImeFocusController} to start input asynchronously when focus gain.
609 */
610 @Override
611 public void startInputAsyncOnWindowFocusGain(View focusedView,
612 @SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) {
613 final boolean forceNewFocus1 = forceNewFocus;
614 final int startInputFlags = getStartInputFlags(focusedView, 0);
615
Yohei Yukawa08e91342020-02-14 12:45:22 -0800616 final ImeFocusController controller = getFocusController();
617 if (controller == null) {
618 return;
lumark970d9d22019-08-18 17:45:24 +0800619 }
Yohei Yukawa08e91342020-02-14 12:45:22 -0800620 if (controller.checkFocus(forceNewFocus1, false)) {
621 // We need to restart input on the current focus view. This
622 // should be done in conjunction with telling the system service
623 // about the window gaining focus, to help make the transition
624 // smooth.
625 if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
626 focusedView, startInputFlags, softInputMode, windowFlags)) {
lumark3f733cc2020-01-20 12:14:04 +0800627 return;
628 }
Yohei Yukawa08e91342020-02-14 12:45:22 -0800629 }
lumark970d9d22019-08-18 17:45:24 +0800630
Yohei Yukawa08e91342020-02-14 12:45:22 -0800631 synchronized (mH) {
632 // For some reason we didn't do a startInput + windowFocusGain, so
633 // we'll just do a window focus gain and call it a day.
634 try {
Ming-Shin Lu6ecbf082020-06-01 17:42:32 +0800635 View servedView = controller.getServedView();
636 boolean nextFocusIsServedView = servedView != null && servedView == focusedView;
637 if (DEBUG) {
638 Log.v(TAG, "Reporting focus gain, without startInput"
639 + ", nextFocusIsServedView=" + nextFocusIsServedView);
640 }
Ming-Shin Lu48bfc312020-06-15 20:06:09 +0800641 final int startInputReason =
642 nextFocusIsServedView ? WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR
643 : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR;
Yohei Yukawa08e91342020-02-14 12:45:22 -0800644 mService.startInputOrWindowGainedFocus(
Ming-Shin Lu48bfc312020-06-15 20:06:09 +0800645 startInputReason, mClient,
Yohei Yukawa08e91342020-02-14 12:45:22 -0800646 focusedView.getWindowToken(), startInputFlags, softInputMode,
647 windowFlags,
Ming-Shin Lu6ecbf082020-06-01 17:42:32 +0800648 nextFocusIsServedView ? mCurrentTextBoxAttribute : null,
649 nextFocusIsServedView ? mServedInputConnectionWrapper : null,
650 0 /* missingMethodFlags */,
Yohei Yukawa08e91342020-02-14 12:45:22 -0800651 mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
652 } catch (RemoteException e) {
653 throw e.rethrowFromSystemServer();
lumark970d9d22019-08-18 17:45:24 +0800654 }
Yohei Yukawa08e91342020-02-14 12:45:22 -0800655 }
lumark970d9d22019-08-18 17:45:24 +0800656 }
657
658 /**
659 * Used by {@link ImeFocusController} to finish current composing text.
660 */
661 @Override
662 public void finishComposingText() {
663 if (mServedInputConnectionWrapper != null) {
664 mServedInputConnectionWrapper.finishComposingText();
665 }
666 }
667
668 /**
669 * Used for {@link ImeFocusController} to set the current focused root view.
670 */
671 @Override
672 public void setCurrentRootView(ViewRootImpl rootView) {
lumark970d9d22019-08-18 17:45:24 +0800673 synchronized (mH) {
Taran Singh0dbd6c42020-05-06 19:29:17 +0000674 if (mCurRootView != null) {
Ming-Shin Lu6ecbf082020-06-01 17:42:32 +0800675 // Restart the input when the next window focus state of the root view changed.
Taran Singh0dbd6c42020-05-06 19:29:17 +0000676 mRestartOnNextWindowFocus = true;
677 }
lumark970d9d22019-08-18 17:45:24 +0800678 mCurRootView = rootView;
679 }
680 }
681
682 /**
683 * Used for {@link ImeFocusController} to return if the root view from the
684 * controller is this {@link InputMethodManager} currently focused.
685 * TODO: Address event-order problem when get current root view in multi-threads.
686 */
687 @Override
688 public boolean isCurrentRootView(ViewRootImpl rootView) {
689 synchronized (mH) {
690 return mCurRootView == rootView;
691 }
692 }
693
694 /**
695 * For {@link ImeFocusController#checkFocus} if needed to force check new focus.
696 */
697 @Override
698 public boolean isRestartOnNextWindowFocus(boolean reset) {
699 final boolean result = mRestartOnNextWindowFocus;
700 if (reset) {
701 mRestartOnNextWindowFocus = false;
702 }
703 return result;
704 }
Ming-Shin Lu6ecbf082020-06-01 17:42:32 +0800705
706 /**
707 * For {@link ImeFocusController} to check if the currently served view is accepting full
708 * text edits.
709 */
710 @Override
711 public boolean isAcceptingText() {
712 synchronized (mH) {
713 return mServedInputConnectionWrapper != null
714 && mServedInputConnectionWrapper.getInputConnection() != null;
715 }
716 }
lumark970d9d22019-08-18 17:45:24 +0800717 }
718
719 /** @hide */
720 public DelegateImpl getDelegate() {
721 return mDelegate;
722 }
723
724 private View getServedViewLocked() {
725 return mCurRootView != null ? mCurRootView.getImeFocusController().getServedView() : null;
726 }
727
728 private View getNextServedViewLocked() {
729 return mCurRootView != null ? mCurRootView.getImeFocusController().getNextServedView()
730 : null;
731 }
732
733 private void setServedViewLocked(View view) {
734 if (mCurRootView != null) {
735 mCurRootView.getImeFocusController().setServedView(view);
736 }
737 }
738
739 private void setNextServedViewLocked(View view) {
740 if (mCurRootView != null) {
741 mCurRootView.getImeFocusController().setNextServedView(view);
742 }
743 }
744
lumark3f733cc2020-01-20 12:14:04 +0800745 private ImeFocusController getFocusController() {
746 synchronized (mH) {
747 if (mCurRootView != null) {
748 return mCurRootView.getImeFocusController();
749 }
750 return null;
751 }
752 }
753
lumark970d9d22019-08-18 17:45:24 +0800754 /**
755 * Returns {@code true} when the given view has been served by Input Method.
756 */
757 private boolean hasServedByInputMethodLocked(View view) {
758 final View servedView = getServedViewLocked();
759 return (servedView == view
760 || (servedView != null && servedView.checkInputConnectionProxy(view)));
761 }
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 class H extends Handler {
764 H(Looper looper) {
Jeff Brown29c0ed22013-01-14 13:50:37 -0800765 super(looper, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 @Override
769 public void handleMessage(Message msg) {
770 switch (msg.what) {
771 case MSG_DUMP: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700772 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 try {
774 doDump((FileDescriptor)args.arg1,
775 (PrintWriter)args.arg2, (String[])args.arg3);
776 } catch (RuntimeException e) {
777 ((PrintWriter)args.arg2).println("Exception: " + e);
778 }
779 synchronized (args.arg4) {
780 ((CountDownLatch)args.arg4).countDown();
781 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700782 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 return;
784 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800785 case MSG_BIND: {
786 final InputBindResult res = (InputBindResult)msg.obj;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900787 if (DEBUG) {
788 Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
789 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800790 synchronized (mH) {
791 if (mBindSequence < 0 || mBindSequence != res.sequence) {
792 Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
793 + ", given seq=" + res.sequence);
Jeff Brown4d656882013-04-03 14:39:19 -0700794 if (res.channel != null && res.channel != mCurChannel) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700795 res.channel.dispose();
796 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800797 return;
798 }
Jeff Brown4d656882013-04-03 14:39:19 -0700799
Yohei Yukawaa277db22014-08-21 18:38:44 -0700800 mRequestUpdateCursorAnchorInfoMonitorMode =
801 REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900802
Jeff Brown4d656882013-04-03 14:39:19 -0700803 setInputChannelLocked(res.channel);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800804 mCurMethod = res.method;
805 mCurId = res.id;
806 mBindSequence = res.sequence;
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700807 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800808 }
Yohei Yukawa42194222018-10-21 20:14:40 -0700809 startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800810 return;
811 }
812 case MSG_UNBIND: {
813 final int sequence = msg.arg1;
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700814 @UnbindReason
Yohei Yukawa33e81792015-11-17 21:14:42 -0800815 final int reason = msg.arg2;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900816 if (DEBUG) {
Yohei Yukawa33e81792015-11-17 21:14:42 -0800817 Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
Yohei Yukawaa468d702018-10-21 11:42:34 -0700818 " reason=" + InputMethodDebug.unbindReasonToString(reason));
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900819 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800820 final boolean startInput;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800821 synchronized (mH) {
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800822 if (mBindSequence != sequence) {
823 return;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800824 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800825 clearBindingLocked();
826 // If we were actively using the last input method, then
827 // we would like to re-connect to the next input method.
lumark970d9d22019-08-18 17:45:24 +0800828 final View servedView = getServedViewLocked();
829 if (servedView != null && servedView.isFocused()) {
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800830 mServedConnecting = true;
831 }
832 startInput = mActive;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800833 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800834 if (startInput) {
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800835 startInputInner(
Yohei Yukawa42194222018-10-21 20:14:40 -0700836 StartInputReason.UNBOUND_FROM_IMMS, null, 0, 0, 0);
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800837 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800838 return;
839 }
840 case MSG_SET_ACTIVE: {
841 final boolean active = msg.arg1 != 0;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800842 final boolean fullscreen = msg.arg2 != 0;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900843 if (DEBUG) {
844 Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
845 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800846 synchronized (mH) {
847 mActive = active;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800848 mFullscreenMode = fullscreen;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800849 if (!active) {
850 // Some other client has starting using the IME, so note
851 // that this happened and make sure our own editor's
852 // state is reset.
Yohei Yukawa2553e482017-12-15 15:47:33 -0800853 mRestartOnNextWindowFocus = true;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800854 try {
855 // Note that finishComposingText() is allowed to run
856 // even when we are not active.
857 mIInputContext.finishComposingText();
858 } catch (RemoteException e) {
859 }
Mikael Gullstrand82ae3ff2014-11-25 12:41:53 +0100860 }
Yohei Yukawa08e91342020-02-14 12:45:22 -0800861 // Check focus again in case that "onWindowFocus" is called before
862 // handling this message.
863 final View servedView = getServedViewLocked();
864 if (servedView != null && canStartInput(servedView)) {
865 if (mCurRootView != null && mCurRootView.getImeFocusController()
866 .checkFocus(mRestartOnNextWindowFocus, false)) {
867 final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
868 : StartInputReason.DEACTIVATED_BY_IMMS;
869 mDelegate.startInput(reason, null, 0, 0, 0);
870 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800871 }
872 }
873 return;
874 }
Jeff Brownf9e989d2013-04-04 23:04:03 -0700875 case MSG_SEND_INPUT_EVENT: {
876 sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
877 return;
878 }
879 case MSG_TIMEOUT_INPUT_EVENT: {
880 finishedInputEvent(msg.arg1, false, true);
881 return;
882 }
883 case MSG_FLUSH_INPUT_EVENT: {
884 finishedInputEvent(msg.arg1, false, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700885 return;
886 }
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800887 case MSG_REPORT_FULLSCREEN_MODE: {
888 final boolean fullscreen = msg.arg1 != 0;
889 InputConnection ic = null;
890 synchronized (mH) {
891 mFullscreenMode = fullscreen;
892 if (mServedInputConnectionWrapper != null) {
893 ic = mServedInputConnectionWrapper.getInputConnection();
894 }
895 }
896 if (ic != null) {
897 ic.reportFullscreenMode(fullscreen);
898 }
899 return;
Yohei Yukawa3d1e8122014-06-06 19:12:47 +0900900 }
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800901 case MSG_REPORT_PRE_RENDERED: {
902 synchronized (mH) {
903 if (mImeInsetsConsumer != null) {
904 mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
905 }
906 }
907 return;
908
909 }
910 case MSG_APPLY_IME_VISIBILITY: {
911 synchronized (mH) {
912 if (mImeInsetsConsumer != null) {
913 mImeInsetsConsumer.applyImeVisibility(msg.arg1 != 0);
914 }
915 }
916 return;
917 }
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700918 case MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX: {
919 final float[] matrixValues = (float[]) msg.obj;
920 final int bindSequence = msg.arg1;
921 synchronized (mH) {
922 if (mBindSequence != bindSequence) {
923 return;
924 }
Tarandeep Singh561a1992019-08-21 17:55:51 -0700925 if (matrixValues == null || mActivityViewToScreenMatrix == null) {
926 // Either InputBoundResult#mActivityViewToScreenMatrixValues is null
927 // OR this app is unbound from the parent ActivityView. In this case,
928 // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700929 mActivityViewToScreenMatrix = null;
930 return;
931 }
932
933 final float[] currentValues = new float[9];
934 mActivityViewToScreenMatrix.getValues(currentValues);
935 if (Arrays.equals(currentValues, matrixValues)) {
936 return;
937 }
938 mActivityViewToScreenMatrix.setValues(matrixValues);
939
940 if (mCursorAnchorInfo == null || mCurMethod == null
941 || mServedInputConnectionWrapper == null) {
942 return;
943 }
944 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode
945 & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
946 if (!isMonitoring) {
947 return;
948 }
949 // Since the host ActivityView is moved, we need to issue
950 // IMS#updateCursorAnchorInfo() again.
951 try {
952 mCurMethod.updateCursorAnchorInfo(
953 CursorAnchorInfo.createForAdditionalParentMatrix(
954 mCursorAnchorInfo, mActivityViewToScreenMatrix));
955 } catch (RemoteException e) {
956 Log.w(TAG, "IME died: " + mCurId, e);
957 }
958 }
959 return;
960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 }
962 }
963 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800964
Jean Chalardde9dbb02011-10-20 19:50:45 +0900965 private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
966 private final InputMethodManager mParentInputMethodManager;
967
968 public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
969 final InputMethodManager inputMethodManager) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 super(mainLooper, conn);
Jean Chalardde9dbb02011-10-20 19:50:45 +0900971 mParentInputMethodManager = inputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 }
973
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800974 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 public boolean isActive() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700976 return mParentInputMethodManager.mActive && !isFinished();
Dianne Hackbornac920872012-05-22 11:49:49 -0700977 }
978
979 void deactivate() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700980 if (isFinished()) {
981 // This is a small performance optimization. Still only the 1st call of
982 // reportFinish() will take effect.
983 return;
984 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700985 closeConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 }
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800987
988 @Override
989 public String toString() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700990 return "ControlledInputConnectionWrapper{"
991 + "connection=" + getInputConnection()
992 + " finished=" + isFinished()
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800993 + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
994 + "}";
995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800997
lumarkba400442020-01-09 01:37:05 +0800998 private static class ImeThreadFactory implements ThreadFactory {
999 private final String mThreadName;
1000
1001 ImeThreadFactory(String name) {
1002 mThreadName = name;
1003 }
1004
1005 @Override
1006 public Thread newThread(Runnable r) {
1007 return new Thread(r, mThreadName);
1008 }
1009 }
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
Jeff Brownc28867a2013-03-26 15:42:39 -07001012 @Override
1013 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 // No need to check for dump permission, since we only give this
1015 // interface to the system.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 CountDownLatch latch = new CountDownLatch(1);
Svetoslav Ganov758143e2012-08-06 16:40:27 -07001017 SomeArgs sargs = SomeArgs.obtain();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 sargs.arg1 = fd;
1019 sargs.arg2 = fout;
1020 sargs.arg3 = args;
1021 sargs.arg4 = latch;
1022 mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
1023 try {
1024 if (!latch.await(5, TimeUnit.SECONDS)) {
1025 fout.println("Timeout waiting for dump");
1026 }
1027 } catch (InterruptedException e) {
1028 fout.println("Interrupted waiting for dump");
1029 }
1030 }
Jeff Brownc28867a2013-03-26 15:42:39 -07001031
1032 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 public void onBindMethod(InputBindResult res) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -08001034 mH.obtainMessage(MSG_BIND, res).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 }
Jeff Brownc28867a2013-03-26 15:42:39 -07001036
1037 @Override
Yohei Yukawa499e3f72018-10-21 20:15:11 -07001038 public void onUnbindMethod(int sequence, @UnbindReason int unbindReason) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -08001039 mH.obtainMessage(MSG_UNBIND, sequence, unbindReason).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 }
Jeff Brownc28867a2013-03-26 15:42:39 -07001041
1042 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -08001043 public void setActive(boolean active, boolean fullscreen) {
1044 mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 }
Yohei Yukawab7b79072014-03-25 11:02:00 +09001046
1047 @Override
Yohei Yukawad277d692020-02-19 17:12:17 -08001048 public void scheduleStartInputIfNecessary(boolean fullscreen) {
1049 // TODO(b/149859205): See if we can optimize this by having a fused dedicated operation.
1050 mH.obtainMessage(MSG_SET_ACTIVE, 0 /* active */, fullscreen ? 1 : 0).sendToTarget();
1051 mH.obtainMessage(MSG_SET_ACTIVE, 1 /* active */, fullscreen ? 1 : 0).sendToTarget();
1052 }
1053
1054 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -08001055 public void reportFullscreenMode(boolean fullscreen) {
1056 mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
1057 .sendToTarget();
1058 }
1059
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001060 @Override
1061 public void reportPreRendered(EditorInfo info) {
1062 mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
1063 .sendToTarget();
1064 }
1065
1066 @Override
1067 public void applyImeVisibility(boolean setVisible) {
1068 mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
1069 .sendToTarget();
1070 }
1071
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001072 @Override
1073 public void updateActivityViewToScreenMatrix(int bindSequence, float[] matrixValues) {
1074 mH.obtainMessage(MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX, bindSequence, 0,
1075 matrixValues).sendToTarget();
1076 }
Jeff Brownc28867a2013-03-26 15:42:39 -07001077 };
1078
Dianne Hackborn51bf0772009-03-24 19:11:41 -07001079 final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07001080
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -07001081 /**
1082 * For layoutlib to clean up static objects inside {@link InputMethodManager}.
1083 */
1084 static void tearDownEditMode() {
1085 if (!isInEditMode()) {
1086 throw new UnsupportedOperationException(
1087 "This method must be called only from layoutlib");
1088 }
1089 synchronized (sLock) {
1090 sInstance = null;
1091 }
Jeff Sharkeya4603d3c2016-08-11 16:54:13 -06001092 }
1093
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -07001094 /**
1095 * For layoutlib to override this method to return {@code true}.
1096 *
1097 * @return {@code true} if the process is running for developer tools
1098 * @see View#isInEditMode()
1099 */
1100 private static boolean isInEditMode() {
1101 return false;
1102 }
1103
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001104 @NonNull
1105 private static InputMethodManager createInstance(int displayId, Looper looper) {
1106 return isInEditMode() ? createStubInstance(displayId, looper)
1107 : createRealInstance(displayId, looper);
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -07001108 }
1109
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001110 @NonNull
1111 private static InputMethodManager createRealInstance(int displayId, Looper looper) {
1112 final IInputMethodManager service;
1113 try {
1114 service = IInputMethodManager.Stub.asInterface(
1115 ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
1116 } catch (ServiceNotFoundException e) {
1117 throw new IllegalStateException(e);
1118 }
1119 final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
Yohei Yukawacb768bc2018-10-24 16:05:09 -07001120 // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
1121 // associate PID/UID with each IME client. This means:
1122 // A. if this method call will be handled as an IPC, there is no problem.
1123 // B. if this method call will be handled as an in-proc method call, we need to
1124 // ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
1125 // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
1126 // 1) doing so has no effect for A and 2) doing so is sufficient for B.
1127 final long identity = Binder.clearCallingIdentity();
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001128 try {
1129 service.addClient(imm.mClient, imm.mIInputContext, displayId);
1130 } catch (RemoteException e) {
1131 e.rethrowFromSystemServer();
Yohei Yukawacb768bc2018-10-24 16:05:09 -07001132 } finally {
1133 Binder.restoreCallingIdentity(identity);
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001134 }
1135 return imm;
1136 }
1137
1138 @NonNull
1139 private static InputMethodManager createStubInstance(int displayId, Looper looper) {
1140 // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
1141 final Class<IInputMethodManager> c = IInputMethodManager.class;
1142 final IInputMethodManager stubInterface =
1143 (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
1144 new Class[]{c}, (proxy, method, args) -> {
1145 final Class<?> returnType = method.getReturnType();
1146 if (returnType == boolean.class) {
1147 return false;
1148 } else if (returnType == int.class) {
1149 return 0;
1150 } else if (returnType == long.class) {
1151 return 0L;
1152 } else if (returnType == short.class) {
1153 return 0;
1154 } else if (returnType == char.class) {
1155 return 0;
1156 } else if (returnType == byte.class) {
1157 return 0;
1158 } else if (returnType == float.class) {
1159 return 0f;
1160 } else if (returnType == double.class) {
1161 return 0.0;
1162 } else {
1163 return null;
1164 }
1165 });
1166 return new InputMethodManager(stubInterface, displayId, looper);
1167 }
1168
1169 private InputMethodManager(IInputMethodManager service, int displayId, Looper looper) {
1170 mService = service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 mMainLooper = looper;
1172 mH = new H(looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001173 mDisplayId = displayId;
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001174 mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 }
1176
1177 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001178 * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
Yohei Yukawa6c075722018-09-21 14:52:12 -07001179 *
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001180 * @param context {@link Context} for which IME APIs need to work
1181 * @return {@link InputMethodManager} instance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 * @hide
1183 */
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001184 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001185 public static InputMethodManager forContext(Context context) {
1186 final int displayId = context.getDisplayId();
1187 // For better backward compatibility, we always use Looper.getMainLooper() for the default
1188 // display case.
1189 final Looper looper = displayId == Display.DEFAULT_DISPLAY
1190 ? Looper.getMainLooper() : context.getMainLooper();
1191 return forContextInternal(displayId, looper);
1192 }
1193
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001194 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001195 private static InputMethodManager forContextInternal(int displayId, Looper looper) {
1196 final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -07001197 synchronized (sLock) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001198 InputMethodManager instance = sInstanceMap.get(displayId);
1199 if (instance != null) {
1200 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 }
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -07001202 instance = createInstance(displayId, looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001203 // For backward compatibility, store the instance also to sInstance for default display.
1204 if (sInstance == null && isDefaultDisplay) {
1205 sInstance = instance;
1206 }
1207 sInstanceMap.put(displayId, instance);
1208 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -07001213 * Deprecated. Do not use.
1214 *
1215 * @return global {@link InputMethodManager} instance
Yohei Yukawa484d4af2018-09-17 16:47:08 -07001216 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
1217 * support multi-display scenario.
Yohei Yukawa6c075722018-09-21 14:52:12 -07001218 * @hide
1219 */
1220 @Deprecated
1221 @UnsupportedAppUsage
1222 public static InputMethodManager getInstance() {
1223 Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be"
1224 + " compatible with multi-display."
1225 + " Use context.getSystemService(InputMethodManager.class) instead.",
1226 new Throwable());
1227 ensureDefaultInstanceForDefaultDisplayIfNecessary();
1228 return peekInstance();
1229 }
1230
1231 /**
1232 * Deprecated. Do not use.
1233 *
1234 * @return {@link #sInstance}
1235 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
1236 * support multi-display scenario.
1237 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 */
Yohei Yukawa484d4af2018-09-17 16:47:08 -07001239 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001240 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -07001241 public static InputMethodManager peekInstance() {
Yohei Yukawa6c075722018-09-21 14:52:12 -07001242 Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be"
1243 + " compatible with multi-display."
1244 + " Use context.getSystemService(InputMethodManager.class) instead.",
1245 new Throwable());
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -07001246 synchronized (sLock) {
1247 return sInstance;
1248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001252 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 public IInputMethodClient getClient() {
1254 return mClient;
1255 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001258 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 public IInputContext getInputContext() {
1260 return mIInputContext;
1261 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001262
Yohei Yukawa629271a2019-02-05 07:50:36 -08001263 /**
1264 * Returns the list of installed input methods.
1265 *
1266 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1267 *
1268 * @return {@link List} of {@link InputMethodInfo}.
1269 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 public List<InputMethodInfo> getInputMethodList() {
1271 try {
Yohei Yukawad20eef82019-02-05 10:45:32 -08001272 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1273 // services InputMethodManagerInternal.getInputMethodListAsUser() should be used
1274 // instead.
1275 return mService.getInputMethodList(UserHandle.myUserId());
1276 } catch (RemoteException e) {
1277 throw e.rethrowFromSystemServer();
1278 }
1279 }
1280
1281 /**
1282 * Returns the list of installed input methods for the specified user.
1283 *
1284 * @param userId user ID to query
1285 * @return {@link List} of {@link InputMethodInfo}.
1286 * @hide
1287 */
1288 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1289 public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
1290 try {
1291 return mService.getInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001293 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 }
1295 }
1296
Yohei Yukawa629271a2019-02-05 07:50:36 -08001297 /**
1298 * Returns the list of enabled input methods.
1299 *
1300 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1301 *
1302 * @return {@link List} of {@link InputMethodInfo}.
1303 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 public List<InputMethodInfo> getEnabledInputMethodList() {
1305 try {
Yohei Yukawa1fb13c52019-02-05 07:55:28 -08001306 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1307 // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used
1308 // instead.
1309 return mService.getEnabledInputMethodList(UserHandle.myUserId());
1310 } catch (RemoteException e) {
1311 throw e.rethrowFromSystemServer();
1312 }
1313 }
1314
1315 /**
1316 * Returns the list of enabled input methods for the specified user.
1317 *
1318 * @param userId user ID to query
1319 * @return {@link List} of {@link InputMethodInfo}.
1320 * @hide
1321 */
1322 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1323 public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
1324 try {
1325 return mService.getEnabledInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001327 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 }
1329 }
1330
satokd4fce2b2011-04-11 12:07:13 +09001331 /**
1332 * Returns a list of enabled input method subtypes for the specified input method info.
Yohei Yukawa629271a2019-02-05 07:50:36 -08001333 *
1334 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1335 *
satokd4fce2b2011-04-11 12:07:13 +09001336 * @param imi An input method info whose subtypes list will be returned.
1337 * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly
1338 * selected subtypes. If an input method info doesn't have enabled subtypes, the framework
1339 * will implicitly enable subtypes according to the current system language.
1340 */
satok16331c82010-12-20 23:48:46 +09001341 public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
1342 boolean allowsImplicitlySelectedSubtypes) {
satok67ddf9c2010-11-17 09:45:54 +09001343 try {
Satoshi Kataokab3c21ac2013-08-07 15:43:29 +09001344 return mService.getEnabledInputMethodSubtypeList(
1345 imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
satok67ddf9c2010-11-17 09:45:54 +09001346 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001347 throw e.rethrowFromSystemServer();
satok67ddf9c2010-11-17 09:45:54 +09001348 }
1349 }
1350
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001351 /**
1352 * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
1353 * intended for IME developers who should be accessing APIs through the service. APIs in this
1354 * class are intended for app developers interacting with the IME.
1355 */
1356 @Deprecated
Yohei Yukawa41b094f2018-09-09 23:58:45 -07001357 public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001358 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 }
1360
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001361 /**
1362 * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
1363 * intended for IME developers who should be accessing APIs through the service. APIs in
1364 * this class are intended for app developers interacting with the IME.
1365 */
1366 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 public void hideStatusIcon(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001368 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 }
1370
Yohei Yukawa17ace292019-01-21 09:24:26 -08001371 /**
1372 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1373 *
1374 * @param spans will be ignored.
1375 *
1376 * @deprecated Do not use.
1377 * @hide
1378 */
1379 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001380 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001381 public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001382 Log.w(TAG, "registerSuggestionSpansForNotification() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001383 }
1384
Yohei Yukawa17ace292019-01-21 09:24:26 -08001385 /**
1386 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1387 *
1388 * @deprecated Do not use.
1389 * @hide
1390 */
1391 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001392 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001393 public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001394 Log.w(TAG, "notifySuggestionPicked() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001395 }
1396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 /**
1398 * Allows you to discover whether the attached input method is running
1399 * in fullscreen mode. Return true if it is fullscreen, entirely covering
1400 * your UI, else returns false.
1401 */
1402 public boolean isFullscreenMode() {
Yohei Yukawa1544def2016-04-26 17:13:38 -07001403 synchronized (mH) {
1404 return mFullscreenMode;
1405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
Yohei Yukawa1544def2016-04-26 17:13:38 -07001407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 /**
1409 * Return true if the given view is the currently active view for the
1410 * input method.
1411 */
1412 public boolean isActive(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001413 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001414 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1415 if (fallbackImm != null) {
1416 return fallbackImm.isActive(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001417 }
1418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 checkFocus();
1420 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001421 return hasServedByInputMethodLocked(view) && mCurrentTextBoxAttribute != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 }
1423 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 /**
1426 * Return true if any view is currently active in the input method.
1427 */
1428 public boolean isActive() {
1429 checkFocus();
1430 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001431 return getServedViewLocked() != null && mCurrentTextBoxAttribute != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 }
1433 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 /**
1436 * Return true if the currently served view is accepting full text edits.
1437 * If false, it has no input connection, so can only handle raw key events.
1438 */
1439 public boolean isAcceptingText() {
1440 checkFocus();
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001441 return mServedInputConnectionWrapper != null &&
1442 mServedInputConnectionWrapper.getInputConnection() != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 }
1444
1445 /**
1446 * Reset all of the state associated with being bound to an input method.
1447 */
1448 void clearBindingLocked() {
Dianne Hackborn6b6b3fd2014-03-24 11:27:18 -07001449 if (DEBUG) Log.v(TAG, "Clearing binding!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 clearConnectionLocked();
Jeff Brown4d656882013-04-03 14:39:19 -07001451 setInputChannelLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 mBindSequence = -1;
1453 mCurId = null;
1454 mCurMethod = null;
Jeff Brown4d656882013-04-03 14:39:19 -07001455 }
1456
1457 void setInputChannelLocked(InputChannel channel) {
1458 if (mCurChannel != channel) {
1459 if (mCurSender != null) {
1460 flushPendingEventsLocked();
1461 mCurSender.dispose();
1462 mCurSender = null;
1463 }
1464 if (mCurChannel != null) {
1465 mCurChannel.dispose();
1466 }
1467 mCurChannel = channel;
Jeff Brownc28867a2013-03-26 15:42:39 -07001468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 }
Jeff Brown4d656882013-04-03 14:39:19 -07001470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 /**
1472 * Reset all of the state associated with a served view being connected
1473 * to an input method
1474 */
1475 void clearConnectionLocked() {
1476 mCurrentTextBoxAttribute = null;
Dianne Hackbornac920872012-05-22 11:49:49 -07001477 if (mServedInputConnectionWrapper != null) {
1478 mServedInputConnectionWrapper.deactivate();
1479 mServedInputConnectionWrapper = null;
1480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 }
Yohei Yukawa0f3a99d2015-05-21 00:15:05 -07001482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 /**
1484 * Disconnect any existing input connection, clearing the served view.
1485 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001486 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 void finishInputLocked() {
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001488 mActivityViewToScreenMatrix = null;
lumark970d9d22019-08-18 17:45:24 +08001489 setNextServedViewLocked(null);
1490 if (getServedViewLocked() != null) {
1491 if (DEBUG) {
1492 Log.v(TAG, "FINISH INPUT: mServedView="
1493 + dumpViewInfo(getServedViewLocked()));
1494 }
1495 setServedViewLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 mCompletions = null;
1497 mServedConnecting = false;
1498 clearConnectionLocked();
1499 }
1500 }
Gilles Debunnec478c172011-12-19 17:29:24 -08001501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 public void displayCompletions(View view, CompletionInfo[] completions) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001503 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001504 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1505 if (fallbackImm != null) {
1506 fallbackImm.displayCompletions(view, completions);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001507 return;
1508 }
1509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 checkFocus();
1511 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001512 if (!hasServedByInputMethodLocked(view)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 return;
1514 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 mCompletions = completions;
1517 if (mCurMethod != null) {
1518 try {
1519 mCurMethod.displayCompletions(mCompletions);
1520 } catch (RemoteException e) {
1521 }
1522 }
1523 }
1524 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 public void updateExtractedText(View view, int token, ExtractedText text) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001527 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001528 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1529 if (fallbackImm != null) {
1530 fallbackImm.updateExtractedText(view, token, text);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001531 return;
1532 }
1533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 checkFocus();
1535 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001536 if (!hasServedByInputMethodLocked(view)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 return;
1538 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 if (mCurMethod != null) {
1541 try {
1542 mCurMethod.updateExtractedText(token, text);
1543 } catch (RemoteException e) {
1544 }
1545 }
1546 }
1547 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 /**
1550 * Flag for {@link #showSoftInput} to indicate that this is an implicit
1551 * request to show the input window, not as the result of a direct request
1552 * by the user. The window may not be shown in this case.
1553 */
1554 public static final int SHOW_IMPLICIT = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 /**
1557 * Flag for {@link #showSoftInput} to indicate that the user has forced
1558 * the input method open (such as by long-pressing menu) so it should
1559 * not be closed until they explicitly do so.
1560 */
1561 public static final int SHOW_FORCED = 0x0002;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001564 * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
1565 * a result receiver: explicitly request that the current input method's
1566 * soft input area be shown to the user, if needed.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001567 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001568 * @param view The currently focused view, which would like to receive
1569 * soft keyboard input.
1570 * @param flags Provides additional operating flags. Currently may be
1571 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
1572 */
1573 public boolean showSoftInput(View view, int flags) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001574 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001575 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1576 if (fallbackImm != null) {
1577 return fallbackImm.showSoftInput(view, flags);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001578 }
1579
The Android Open Source Project4df24232009-03-05 14:34:35 -08001580 return showSoftInput(view, flags, null);
1581 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001582
The Android Open Source Project4df24232009-03-05 14:34:35 -08001583 /**
1584 * Flag for the {@link ResultReceiver} result code from
1585 * {@link #showSoftInput(View, int, ResultReceiver)} and
1586 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1587 * state of the soft input window was unchanged and remains shown.
1588 */
1589 public static final int RESULT_UNCHANGED_SHOWN = 0;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001590
The Android Open Source Project4df24232009-03-05 14:34:35 -08001591 /**
1592 * Flag for the {@link ResultReceiver} result code from
1593 * {@link #showSoftInput(View, int, ResultReceiver)} and
1594 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1595 * state of the soft input window was unchanged and remains hidden.
1596 */
1597 public static final int RESULT_UNCHANGED_HIDDEN = 1;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001598
The Android Open Source Project4df24232009-03-05 14:34:35 -08001599 /**
1600 * Flag for the {@link ResultReceiver} result code from
1601 * {@link #showSoftInput(View, int, ResultReceiver)} and
1602 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1603 * state of the soft input window changed from hidden to shown.
1604 */
1605 public static final int RESULT_SHOWN = 2;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001606
The Android Open Source Project4df24232009-03-05 14:34:35 -08001607 /**
1608 * Flag for the {@link ResultReceiver} result code from
1609 * {@link #showSoftInput(View, int, ResultReceiver)} and
1610 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1611 * state of the soft input window changed from shown to hidden.
1612 */
1613 public static final int RESULT_HIDDEN = 3;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001614
The Android Open Source Project4df24232009-03-05 14:34:35 -08001615 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 * Explicitly request that the current input method's soft input area be
1617 * shown to the user, if needed. Call this if the user interacts with
1618 * your view in such a way that they have expressed they would like to
1619 * start performing input into it.
Yohei Yukawad552a522016-03-20 15:08:31 -07001620 *
1621 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1622 * this method can be a long-lived object, because it may not be
1623 * garbage-collected until all the corresponding {@link ResultReceiver}
1624 * objects transferred to different processes get garbage-collected.
1625 * Follow the general patterns to avoid memory leaks in Android.
1626 * Consider to use {@link java.lang.ref.WeakReference} so that application
1627 * logic objects such as {@link android.app.Activity} and {@link Context}
1628 * can be garbage collected regardless of the lifetime of
1629 * {@link ResultReceiver}.
1630 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 * @param view The currently focused view, which would like to receive
1632 * soft keyboard input.
1633 * @param flags Provides additional operating flags. Currently may be
1634 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001635 * @param resultReceiver If non-null, this will be called by the IME when
1636 * it has processed your request to tell you what it has done. The result
1637 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1638 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1639 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 */
Gilles Debunnead8484b2011-02-17 17:37:51 -08001641 public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001642 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001643 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1644 if (fallbackImm != null) {
1645 return fallbackImm.showSoftInput(view, flags, resultReceiver);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001646 }
1647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 checkFocus();
1649 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001650 if (!hasServedByInputMethodLocked(view)) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001651 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
1653
1654 try {
Tarandeep Singhbb0e2f72020-01-15 13:58:29 -08001655 return mService.showSoftInput(
1656 mClient, view.getWindowToken(), flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001658 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
1660 }
1661 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001662
Yohei Yukawa101ae462017-03-31 14:28:18 -07001663 /**
1664 * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
1665 * is publicly released because previous implementations of that class had relied on this method
1666 * via reflection.
1667 *
1668 * @deprecated This is a hidden API. You should never use this.
1669 * @hide
1670 */
1671 @Deprecated
Yohei Yukawa1466e4a2019-02-12 01:42:56 -08001672 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
The Android Open Source Project4df24232009-03-05 14:34:35 -08001673 public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
Tarandeep Singh7bbce8e2020-03-02 10:41:14 -08001674 synchronized (mH) {
1675 try {
1676 Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be"
1677 + " removed soon. If you are using android.support.v7.widget.SearchView,"
1678 + " please update to version 26.0 or newer version.");
1679 if (mCurRootView == null || mCurRootView.getView() == null) {
1680 Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
1681 return;
1682 }
1683 mService.showSoftInput(
1684 mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver);
1685 } catch (RemoteException e) {
1686 throw e.rethrowFromSystemServer();
1687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
1689 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001692 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
1693 * 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 -08001694 * by the user.
1695 */
1696 public static final int HIDE_IMPLICIT_ONLY = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001699 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestShowSelf(int)}
1700 * 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 -08001701 * shown with {@link #SHOW_FORCED}.
1702 */
1703 public static final int HIDE_NOT_ALWAYS = 0x0002;
Gilles Debunnec478c172011-12-19 17:29:24 -08001704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 /**
Gilles Debunne7c8c6d62011-01-24 14:48:14 -08001706 * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
The Android Open Source Project4df24232009-03-05 14:34:35 -08001707 * without a result: request to hide the soft input window from the
1708 * context of the window that is currently accepting input.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001709 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001710 * @param windowToken The token of the window that is making the request,
1711 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1712 * @param flags Provides additional operating flags. Currently may be
1713 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
1714 */
1715 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
1716 return hideSoftInputFromWindow(windowToken, flags, null);
1717 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001718
The Android Open Source Project4df24232009-03-05 14:34:35 -08001719 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 * Request to hide the soft input window from the context of the window
1721 * that is currently accepting input. This should be called as a result
1722 * of the user doing some actually than fairly explicitly requests to
1723 * have the input window hidden.
Yohei Yukawad552a522016-03-20 15:08:31 -07001724 *
1725 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1726 * this method can be a long-lived object, because it may not be
1727 * garbage-collected until all the corresponding {@link ResultReceiver}
1728 * objects transferred to different processes get garbage-collected.
1729 * Follow the general patterns to avoid memory leaks in Android.
1730 * Consider to use {@link java.lang.ref.WeakReference} so that application
1731 * logic objects such as {@link android.app.Activity} and {@link Context}
1732 * can be garbage collected regardless of the lifetime of
1733 * {@link ResultReceiver}.
1734 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 * @param windowToken The token of the window that is making the request,
1736 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1737 * @param flags Provides additional operating flags. Currently may be
1738 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001739 * @param resultReceiver If non-null, this will be called by the IME when
1740 * it has processed your request to tell you what it has done. The result
1741 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1742 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1743 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 */
The Android Open Source Project4df24232009-03-05 14:34:35 -08001745 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
1746 ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 checkFocus();
1748 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001749 final View servedView = getServedViewLocked();
1750 if (servedView == null || servedView.getWindowToken() != windowToken) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001751 return false;
1752 }
1753
1754 try {
Tarandeep Singh4fe5b652020-02-20 17:20:19 -08001755 return mService.hideSoftInput(mClient, windowToken, flags, resultReceiver);
The Android Open Source Project4df24232009-03-05 14:34:35 -08001756 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001757 throw e.rethrowFromSystemServer();
The Android Open Source Project4df24232009-03-05 14:34:35 -08001758 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001759 }
1760 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001761
The Android Open Source Project4df24232009-03-05 14:34:35 -08001762 /**
1763 * This method toggles the input method window display.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001764 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001765 * If not the input window will be displayed.
1766 * @param windowToken The token of the window that is making the request,
1767 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1768 * @param showFlags Provides additional operating flags. May be
1769 * 0 or have the {@link #SHOW_IMPLICIT},
1770 * {@link #SHOW_FORCED} bit set.
1771 * @param hideFlags Provides additional operating flags. May be
1772 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1773 * {@link #HIDE_NOT_ALWAYS} bit set.
1774 **/
1775 public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
1776 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001777 final View servedView = getServedViewLocked();
1778 if (servedView == null || servedView.getWindowToken() != windowToken) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 return;
1780 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001781 if (mCurMethod != null) {
1782 try {
1783 mCurMethod.toggleSoftInput(showFlags, hideFlags);
1784 } catch (RemoteException e) {
1785 }
1786 }
1787 }
1788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001790 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001791 * This method toggles the input method window display.
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001792 *
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001793 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001794 * If not the input window will be displayed.
1795 * @param showFlags Provides additional operating flags. May be
1796 * 0 or have the {@link #SHOW_IMPLICIT},
1797 * {@link #SHOW_FORCED} bit set.
1798 * @param hideFlags Provides additional operating flags. May be
1799 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1800 * {@link #HIDE_NOT_ALWAYS} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001801 */
1802 public void toggleSoftInput(int showFlags, int hideFlags) {
1803 if (mCurMethod != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001805 mCurMethod.toggleSoftInput(showFlags, hideFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 } catch (RemoteException e) {
1807 }
1808 }
1809 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 /**
1812 * If the input method is currently connected to the given view,
1813 * restart it with its new contents. You should call this when the text
1814 * within your view changes outside of the normal input method or key
1815 * input flow, such as when an application calls TextView.setText().
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001816 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 * @param view The view whose text has changed.
1818 */
1819 public void restartInput(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001820 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001821 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1822 if (fallbackImm != null) {
1823 fallbackImm.restartInput(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001824 return;
1825 }
1826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 checkFocus();
1828 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001829 if (!hasServedByInputMethodLocked(view)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 return;
1831 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 mServedConnecting = true;
1834 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001835
Yohei Yukawa42194222018-10-21 20:14:40 -07001836 startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001838
lumark3f733cc2020-01-20 12:14:04 +08001839 /**
1840 * Called when {@link DelegateImpl#startInput}, {@link #restartInput(View)},
1841 * {@link #MSG_BIND} or {@link #MSG_UNBIND}.
1842 * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
1843 * background thread may blocked by other methods which already inside {@code mH} lock.
1844 */
Yohei Yukawac6632df2018-10-21 11:47:16 -07001845 boolean startInputInner(@StartInputReason int startInputReason,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001846 @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
1847 @SoftInputModeFlags int softInputMode, int windowFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 final View view;
1849 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08001850 view = getServedViewLocked();
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 // Make sure we have a window token for the served view.
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001853 if (DEBUG) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001854 Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) +
Yohei Yukawaa468d702018-10-21 11:42:34 -07001855 " reason=" + InputMethodDebug.startInputReasonToString(startInputReason));
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 if (view == null) {
1858 if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
Dianne Hackborn7663d802012-02-24 13:08:49 -08001859 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 }
1861 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001862
Yohei Yukawa80498d52018-06-21 16:24:36 -07001863 if (windowGainingFocus == null) {
1864 windowGainingFocus = view.getWindowToken();
1865 if (windowGainingFocus == null) {
1866 Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
1867 return false;
1868 }
lumark970d9d22019-08-18 17:45:24 +08001869 startInputFlags = getStartInputFlags(view, startInputFlags);
Yohei Yukawa80498d52018-06-21 16:24:36 -07001870 softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
1871 windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
1872 }
1873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 // Now we need to get an input connection from the served view.
1875 // This is complicated in a couple ways: we can't be holding our lock
1876 // when calling out to the view, and we need to make sure we call into
1877 // the view on the same thread that is driving its view hierarchy.
1878 Handler vh = view.getHandler();
1879 if (vh == null) {
1880 // If the view doesn't have a handler, something has changed out
Satoshi Kataoka35739502012-10-02 19:00:26 +09001881 // from under us, so just close the current input.
1882 // If we don't close the current input, the current input method can remain on the
1883 // screen without a connection.
1884 if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
1885 closeCurrentInput();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001886 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 }
1888 if (vh.getLooper() != Looper.myLooper()) {
1889 // The view is running on a different thread than our own, so
1890 // we need to reschedule our work for over there.
1891 if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
lumark970d9d22019-08-18 17:45:24 +08001892 vh.post(() -> mDelegate.startInput(startInputReason, null, 0, 0, 0));
Dianne Hackborn7663d802012-02-24 13:08:49 -08001893 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 // Okay we are now ready to call into the served view and have it
1897 // do its stuff.
1898 // Life is good: let's hook everything up!
1899 EditorInfo tba = new EditorInfo();
Yohei Yukawa02df3282015-06-03 15:58:59 -07001900 // Note: Use Context#getOpPackageName() rather than Context#getPackageName() so that the
1901 // system can verify the consistency between the uid of this process and package name passed
1902 // from here. See comment of Context#getOpPackageName() for details.
1903 tba.packageName = view.getContext().getOpPackageName();
Feng Caoe65a97c2020-02-28 11:39:56 -08001904 tba.autofillId = view.getAutofillId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 tba.fieldId = view.getId();
1906 InputConnection ic = view.onCreateInputConnection(tba);
1907 if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
Gilles Debunnec478c172011-12-19 17:29:24 -08001908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 synchronized (mH) {
1910 // Now that we are locked again, validate that our state hasn't
1911 // changed.
lumark970d9d22019-08-18 17:45:24 +08001912 final View servedView = getServedViewLocked();
1913 if (servedView != view || !mServedConnecting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 // Something else happened, so abort.
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001915 if (DEBUG) Log.v(TAG,
1916 "Starting input: finished by someone else. view=" + dumpViewInfo(view)
lumark970d9d22019-08-18 17:45:24 +08001917 + " servedView=" + dumpViewInfo(servedView)
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001918 + " mServedConnecting=" + mServedConnecting);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001919 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 // If we already have a text box, then this view is already
1923 // connected so we want to restart it.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001924 if (mCurrentTextBoxAttribute == null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001925 startInputFlags |= StartInputFlags.INITIAL_CONNECTION;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001926 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 // Hook 'em up and let 'er rip.
1929 mCurrentTextBoxAttribute = tba;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001930 maybeCallServedViewChangedLocked(tba);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 mServedConnecting = false;
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001932 if (mServedInputConnectionWrapper != null) {
1933 mServedInputConnectionWrapper.deactivate();
1934 mServedInputConnectionWrapper = null;
1935 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001936 ControlledInputConnectionWrapper servedContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001937 final int missingMethodFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 if (ic != null) {
1939 mCursorSelStart = tba.initialSelStart;
1940 mCursorSelEnd = tba.initialSelEnd;
1941 mCursorCandStart = -1;
1942 mCursorCandEnd = -1;
1943 mCursorRect.setEmpty();
Yohei Yukawa056ffe62014-05-13 14:26:09 +09001944 mCursorAnchorInfo = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001945 final Handler icHandler;
1946 missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
1947 if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER)
1948 != 0) {
1949 // InputConnection#getHandler() is not implemented.
1950 icHandler = null;
1951 } else {
1952 icHandler = ic.getHandler();
1953 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001954 servedContext = new ControlledInputConnectionWrapper(
1955 icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 } else {
1957 servedContext = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001958 missingMethodFlags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001960 mServedInputConnectionWrapper = servedContext;
Yohei Yukawa612cce92016-02-11 17:47:33 -08001961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 try {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001963 if (DEBUG) Log.v(TAG, "START INPUT: view=" + dumpViewInfo(view) + " ic="
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001964 + ic + " tba=" + tba + " startInputFlags="
1965 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001966 final InputBindResult res = mService.startInputOrWindowGainedFocus(
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001967 startInputReason, mClient, windowGainingFocus, startInputFlags,
1968 softInputMode, windowFlags, tba, servedContext, missingMethodFlags,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001969 view.getContext().getApplicationInfo().targetSdkVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
Yohei Yukawa2553e482017-12-15 15:47:33 -08001971 if (res == null) {
1972 Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
1973 + " null. startInputReason="
Yohei Yukawaa468d702018-10-21 11:42:34 -07001974 + InputMethodDebug.startInputReasonToString(startInputReason)
Yohei Yukawa2553e482017-12-15 15:47:33 -08001975 + " editorInfo=" + tba
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001976 + " startInputFlags="
1977 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001978 return false;
1979 }
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001980 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
Yohei Yukawa2553e482017-12-15 15:47:33 -08001981 if (res.id != null) {
1982 setInputChannelLocked(res.channel);
1983 mBindSequence = res.sequence;
1984 mCurMethod = res.method;
1985 mCurId = res.id;
Yohei Yukawa2553e482017-12-15 15:47:33 -08001986 } else if (res.channel != null && res.channel != mCurChannel) {
1987 res.channel.dispose();
1988 }
1989 switch (res.result) {
1990 case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
1991 mRestartOnNextWindowFocus = true;
1992 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994 if (mCurMethod != null && mCompletions != null) {
1995 try {
1996 mCurMethod.displayCompletions(mCompletions);
1997 } catch (RemoteException e) {
1998 }
1999 }
2000 } catch (RemoteException e) {
2001 Log.w(TAG, "IME died: " + mCurId, e);
2002 }
2003 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08002004
2005 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
2007
Yohei Yukawa7029cc32020-04-09 22:38:04 -07002008 /**
2009 * An empty method only to avoid crashes of apps that call this method via reflection and do not
2010 * handle {@link NoSuchMethodException} in a graceful manner.
2011 *
2012 * @deprecated This is an empty method. No framework method must call this method.
2013 * @hide
2014 */
2015 @Deprecated
2016 @UnsupportedAppUsage(trackingBug = 37122102, maxTargetSdk = Build.VERSION_CODES.Q,
2017 publicAlternatives = "{@code androidx.activity.ComponentActivity}")
2018 public void windowDismissed(IBinder appWindowToken) {
2019 // Intentionally empty.
2020 //
2021 // It seems that some applications call this method via reflection to null clear the
2022 // following fields that used to exist in InputMethodManager:
2023 // * InputMethodManager#mCurRootView
2024 // * InputMethodManager#mServedView
2025 // * InputMethodManager#mNextServedView
2026 // so that these objects can be garbage-collected when an Activity gets dismissed.
2027 //
2028 // It is indeed true that older versions of InputMethodManager had issues that prevented
2029 // these fields from being null-cleared when it should have been, but the understanding of
2030 // the engineering team is that all known issues have already been fixed as of Android 10.
2031 //
2032 // For older devices, developers can work around the object leaks by using
2033 // androidx.activity.ComponentActivity.
2034 // See https://issuetracker.google.com/u/1/issues/37122102 for details.
2035 //
2036 // If you believe InputMethodManager is leaking objects in API 24 or any later version,
2037 // please file a bug at https://issuetracker.google.com/issues/new?component=192705.
2038 }
2039
lumark970d9d22019-08-18 17:45:24 +08002040 private int getStartInputFlags(View focusedView, int startInputFlags) {
2041 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
2042 if (focusedView.onCheckIsTextEditor()) {
2043 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 }
lumark970d9d22019-08-18 17:45:24 +08002045 return startInputFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 }
Jeff Browna175a5b2012-02-15 19:18:31 -08002047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 /**
lumark3f733cc2020-01-20 12:14:04 +08002049 * Check the next served view from {@link ImeFocusController} if needs to start input.
2050 * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
2051 * background thread may blocked by other methods which already inside {@code mH} lock.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 * @hide
2053 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002054 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 public void checkFocus() {
lumark3f733cc2020-01-20 12:14:04 +08002056 final ImeFocusController controller = getFocusController();
2057 if (controller != null) {
2058 controller.checkFocus(false /* forceNewFocus */, true /* startInput */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002061
Mathew Inwooda570dee2018-08-17 14:56:00 +01002062 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 void closeCurrentInput() {
Tarandeep Singh7bbce8e2020-03-02 10:41:14 -08002064 synchronized (mH) {
2065 if (mCurRootView == null || mCurRootView.getView() == null) {
2066 Log.w(TAG, "No current root view, ignoring closeCurrentInput()");
2067 return;
2068 }
2069 try {
2070 mService.hideSoftInput(
2071 mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null);
2072 } catch (RemoteException e) {
2073 throw e.rethrowFromSystemServer();
2074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 }
2076 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08002077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 /**
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08002079 * Register for IME state callbacks and applying visibility in
2080 * {@link android.view.ImeInsetsSourceConsumer}.
2081 * @hide
2082 */
2083 public void registerImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2084 if (imeInsetsConsumer == null) {
2085 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2086 }
2087
2088 synchronized (mH) {
2089 mImeInsetsConsumer = imeInsetsConsumer;
2090 }
2091 }
2092
2093 /**
Louis Chang3d4a7d12019-04-12 16:18:30 +08002094 * Unregister for IME state callbacks and applying visibility in
2095 * {@link android.view.ImeInsetsSourceConsumer}.
2096 * @hide
2097 */
2098 public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2099 if (imeInsetsConsumer == null) {
2100 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2101 }
2102
2103 synchronized (mH) {
2104 if (mImeInsetsConsumer == imeInsetsConsumer) {
2105 mImeInsetsConsumer = null;
2106 }
2107 }
2108 }
2109
2110 /**
Tarandeep Singh46d59f02019-01-29 18:09:15 -08002111 * Call showSoftInput with currently focused view.
2112 * @return {@code true} if IME can be shown.
2113 * @hide
2114 */
2115 public boolean requestImeShow(ResultReceiver resultReceiver) {
2116 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08002117 final View servedView = getServedViewLocked();
2118 if (servedView == null) {
Tarandeep Singh46d59f02019-01-29 18:09:15 -08002119 return false;
2120 }
lumark970d9d22019-08-18 17:45:24 +08002121 showSoftInput(servedView, 0 /* flags */, resultReceiver);
Tarandeep Singh46d59f02019-01-29 18:09:15 -08002122 return true;
2123 }
2124 }
2125
2126 /**
2127 * Notify IME directly that it is no longer visible.
2128 * @hide
2129 */
2130 public void notifyImeHidden() {
2131 synchronized (mH) {
2132 try {
2133 if (mCurMethod != null) {
2134 mCurMethod.notifyImeHidden();
2135 }
2136 } catch (RemoteException re) {
2137 }
2138 }
2139 }
2140
2141 /**
Tarandeep Singh94c9a832020-02-03 14:55:30 -08002142 * Notify IME directly to remove surface as it is no longer visible.
2143 * @hide
2144 */
2145 public void removeImeSurface() {
2146 synchronized (mH) {
2147 try {
2148 if (mCurMethod != null) {
2149 mCurMethod.removeImeSurface();
2150 }
2151 } catch (RemoteException re) {
2152 }
2153 }
2154 }
2155
2156 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 * Report the current selection range.
Jean Chalard6fd68e02014-02-20 17:48:46 +09002158 *
2159 * <p><strong>Editor authors</strong>, you need to call this method whenever
2160 * the cursor moves in your editor. Remember that in addition to doing this, your
2161 * editor needs to always supply current cursor values in
2162 * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
2163 * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
2164 * called, which happens whenever the keyboard shows up or the focus changes
2165 * to a text field, among other cases.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 */
2167 public void updateSelection(View view, int selStart, int selEnd,
2168 int candidatesStart, int candidatesEnd) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002169 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002170 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2171 if (fallbackImm != null) {
2172 fallbackImm.updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002173 return;
2174 }
2175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 checkFocus();
2177 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08002178 if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2179 || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 return;
2181 }
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
2184 || mCursorCandStart != candidatesStart
2185 || mCursorCandEnd != candidatesEnd) {
2186 if (DEBUG) Log.d(TAG, "updateSelection");
2187
2188 try {
2189 if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
Jean Chalardc743cb92013-09-12 16:28:45 +09002190 final int oldSelStart = mCursorSelStart;
2191 final int oldSelEnd = mCursorSelEnd;
2192 // Update internal values before sending updateSelection to the IME, because
2193 // if it changes the text within its onUpdateSelection handler in a way that
2194 // 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 -08002195 mCursorSelStart = selStart;
2196 mCursorSelEnd = selEnd;
2197 mCursorCandStart = candidatesStart;
2198 mCursorCandEnd = candidatesEnd;
Jean Chalardc743cb92013-09-12 16:28:45 +09002199 mCurMethod.updateSelection(oldSelStart, oldSelEnd,
2200 selStart, selEnd, candidatesStart, candidatesEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 } catch (RemoteException e) {
2202 Log.w(TAG, "IME died: " + mCurId, e);
2203 }
2204 }
2205 }
2206 }
2207
2208 /**
satok863fcd62011-06-21 17:38:02 +09002209 * Notify the event when the user tapped or clicked the text view.
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002210 *
2211 * @param view {@link View} which is being clicked.
2212 * @see InputMethodService#onViewClicked(boolean)
2213 * @deprecated The semantics of this method can never be defined well for composite {@link View}
2214 * that works as a giant "Canvas", which can host its own UI hierarchy and sub focus
2215 * state. {@link android.webkit.WebView} is a good example. Application / IME
2216 * developers should not rely on this method.
satok863fcd62011-06-21 17:38:02 +09002217 */
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002218 @Deprecated
satok863fcd62011-06-21 17:38:02 +09002219 public void viewClicked(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002220 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002221 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2222 if (fallbackImm != null) {
2223 fallbackImm.viewClicked(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002224 return;
2225 }
2226
lumark970d9d22019-08-18 17:45:24 +08002227 final View servedView;
2228 final View nextServedView;
2229 synchronized (mH) {
2230 servedView = getServedViewLocked();
2231 nextServedView = getNextServedViewLocked();
2232 }
2233 final boolean focusChanged = servedView != nextServedView;
satok863fcd62011-06-21 17:38:02 +09002234 checkFocus();
2235 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08002236 if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2237 || mCurMethod == null) {
satok863fcd62011-06-21 17:38:02 +09002238 return;
2239 }
2240 try {
2241 if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
2242 mCurMethod.viewClicked(focusChanged);
2243 } catch (RemoteException e) {
2244 Log.w(TAG, "IME died: " + mCurId, e);
2245 }
2246 }
2247 }
2248
2249 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002250 * Return true if the current input method wants to watch the location
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 * of the input editor's cursor in its window.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002252 *
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002253 * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002254 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002255 @Deprecated
2256 public boolean isWatchingCursor(View view) {
2257 return false;
Yohei Yukawa4de04792014-04-17 12:40:31 +09002258 }
2259
2260 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002261 * Return true if the current input method wants to be notified when cursor/anchor location
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002262 * is changed.
Yohei Yukawab7b79072014-03-25 11:02:00 +09002263 *
2264 * @hide
2265 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002266 @UnsupportedAppUsage
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002267 public boolean isCursorAnchorInfoEnabled() {
2268 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002269 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002270 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawaa277db22014-08-21 18:38:44 -07002271 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002272 InputConnection.CURSOR_UPDATE_MONITOR) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002273 return isImmediate || isMonitoring;
2274 }
2275 }
2276
2277 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002278 * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002279 *
2280 * @hide
2281 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002282 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -07002283 public void setUpdateCursorAnchorInfoMode(int flags) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002284 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002285 mRequestUpdateCursorAnchorInfoMonitorMode = flags;
Yohei Yukawab7b79072014-03-25 11:02:00 +09002286 }
2287 }
2288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 /**
2290 * Report the current cursor location in its window.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002291 *
2292 * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002294 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 public void updateCursor(View view, int left, int top, int right, int bottom) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002296 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002297 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2298 if (fallbackImm != null) {
2299 fallbackImm.updateCursor(view, left, top, right, bottom);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002300 return;
2301 }
2302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 checkFocus();
2304 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08002305 if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2306 || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 return;
2308 }
Yohei Yukawaa277db22014-08-21 18:38:44 -07002309
2310 mTmpCursorRect.set(left, top, right, bottom);
2311 if (!mCursorRect.equals(mTmpCursorRect)) {
2312 if (DEBUG) Log.d(TAG, "updateCursor");
2313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 try {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002315 if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
2316 mCurMethod.updateCursor(mTmpCursorRect);
2317 mCursorRect.set(mTmpCursorRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 } catch (RemoteException e) {
2319 Log.w(TAG, "IME died: " + mCurId, e);
2320 }
2321 }
2322 }
2323 }
2324
2325 /**
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002326 * Report positional change of the text insertion point and/or characters in the composition
2327 * string.
2328 */
2329 public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
2330 if (view == null || cursorAnchorInfo == null) {
2331 return;
2332 }
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002333 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002334 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2335 if (fallbackImm != null) {
2336 fallbackImm.updateCursorAnchorInfo(view, cursorAnchorInfo);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002337 return;
2338 }
2339
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002340 checkFocus();
2341 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08002342 if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2343 || mCurMethod == null) {
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002344 return;
2345 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002346 // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
2347 // not been changed from the previous call.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002348 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002349 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002350 if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
Yohei Yukawa73605912014-08-13 16:49:35 +09002351 // TODO: Consider always emitting this message once we have addressed redundant
2352 // calls of this method from android.widget.Editor.
2353 if (DEBUG) {
2354 Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
2355 + cursorAnchorInfo);
2356 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002357 return;
2358 }
2359 if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002360 try {
Yohei Yukawab4f328a2019-05-02 08:41:27 -07002361 if (mActivityViewToScreenMatrix != null) {
2362 mCurMethod.updateCursorAnchorInfo(
2363 CursorAnchorInfo.createForAdditionalParentMatrix(
2364 cursorAnchorInfo, mActivityViewToScreenMatrix));
2365 } else {
2366 mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
2367 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002368 mCursorAnchorInfo = cursorAnchorInfo;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002369 // Clear immediate bit (if any).
Yohei Yukawaa277db22014-08-21 18:38:44 -07002370 mRequestUpdateCursorAnchorInfoMonitorMode &=
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002371 ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002372 } catch (RemoteException e) {
2373 Log.w(TAG, "IME died: " + mCurId, e);
2374 }
2375 }
2376 }
2377
2378 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
2380 * InputMethodSession.appPrivateCommand()} on the current Input Method.
2381 * @param view Optional View that is sending the command, or null if
2382 * you want to send the command regardless of the view that is attached
2383 * to the input method.
2384 * @param action Name of the command to be performed. This <em>must</em>
2385 * be a scoped name, i.e. prefixed with a package name you own, so that
2386 * different developers will not create conflicting commands.
2387 * @param data Any data to include with the command.
2388 */
2389 public void sendAppPrivateCommand(View view, String action, Bundle data) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002390 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002391 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2392 if (fallbackImm != null) {
2393 fallbackImm.sendAppPrivateCommand(view, action, data);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002394 return;
2395 }
2396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 checkFocus();
2398 synchronized (mH) {
lumark970d9d22019-08-18 17:45:24 +08002399 if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2400 || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 return;
2402 }
2403 try {
2404 if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
2405 mCurMethod.appPrivateCommand(action, data);
2406 } catch (RemoteException e) {
2407 Log.w(TAG, "IME died: " + mCurId, e);
2408 }
2409 }
2410 }
satok28203512010-11-24 11:06:49 +09002411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 /**
satok28203512010-11-24 11:06:49 +09002413 * Force switch to a new input method component. This can only be called
2414 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002415 *
2416 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, the undocumented behavior that
2417 * token can be {@code null} when the caller has
2418 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} is deprecated. Instead, update
2419 * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2420 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2421 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 * @param token Supplies the identifying token given to an input method
2423 * when it was started, which allows it to perform this operation on
2424 * itself.
2425 * @param id The unique identifier for the new input method to be switched to.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002426 * @deprecated Use {@link InputMethodService#switchInputMethod(String)}
2427 * instead. This method was intended for IME developers who should be accessing APIs through
2428 * 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 -08002429 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002430 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 public void setInputMethod(IBinder token, String id) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002432 if (token == null) {
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002433 // There are still some system components that rely on this undocumented behavior
2434 // regarding null IME token with WRITE_SECURE_SETTINGS. Provide a fallback logic as a
2435 // temporary remedy.
2436 if (id == null) {
2437 return;
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002438 }
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002439 if (Process.myUid() == Process.SYSTEM_UID) {
2440 Log.w(TAG, "System process should not be calling setInputMethod() because almost "
2441 + "always it is a bug under multi-user / multi-profile environment. "
2442 + "Consider interacting with InputMethodManagerService directly via "
2443 + "LocalServices.");
2444 return;
2445 }
2446 final Context fallbackContext = ActivityThread.currentApplication();
2447 if (fallbackContext == null) {
2448 return;
2449 }
2450 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2451 != PackageManager.PERMISSION_GRANTED) {
2452 return;
2453 }
2454 final List<InputMethodInfo> imis = getEnabledInputMethodList();
2455 final int numImis = imis.size();
2456 boolean found = false;
2457 for (int i = 0; i < numImis; ++i) {
2458 final InputMethodInfo imi = imis.get(i);
2459 if (id.equals(imi.getId())) {
2460 found = true;
2461 break;
2462 }
2463 }
2464 if (!found) {
2465 Log.e(TAG, "Ignoring setInputMethod(null, " + id + ") because the specified "
2466 + "id not found in enabled IMEs.");
2467 return;
2468 }
2469 Log.w(TAG, "The undocumented behavior that setInputMethod() accepts null token "
2470 + "when the caller has WRITE_SECURE_SETTINGS is deprecated. This behavior may "
2471 + "be completely removed in a future version. Update secure settings directly "
2472 + "instead.");
2473 final ContentResolver resolver = fallbackContext.getContentResolver();
2474 Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
2475 NOT_A_SUBTYPE_ID);
2476 Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, id);
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002477 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002479 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480 }
satok28203512010-11-24 11:06:49 +09002481
2482 /**
2483 * Force switch to a new input method and subtype. This can only be called
2484 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002485 *
2486 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, {@code token} cannot be
2487 * {@code null} even with {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}. Instead,
2488 * update {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2489 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2490 *
satok28203512010-11-24 11:06:49 +09002491 * @param token Supplies the identifying token given to an input method
2492 * when it was started, which allows it to perform this operation on
2493 * itself.
2494 * @param id The unique identifier for the new input method to be switched to.
2495 * @param subtype The new subtype of the new input method to be switched to.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002496 * @deprecated Use
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002497 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002498 * instead. This method was intended for IME developers who should be accessing APIs through
2499 * the service. APIs in this class are intended for app developers interacting with the IME.
satok28203512010-11-24 11:06:49 +09002500 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002501 @Deprecated
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002502 public void setInputMethodAndSubtype(@NonNull IBinder token, String id,
2503 InputMethodSubtype subtype) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002504 if (token == null) {
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002505 Log.e(TAG, "setInputMethodAndSubtype() does not accept null token on Android Q "
2506 + "and later.");
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002507 return;
satok28203512010-11-24 11:06:49 +09002508 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002509 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype);
satok28203512010-11-24 11:06:49 +09002510 }
2511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 /**
2513 * Close/hide the input method's soft input area, so the user no longer
2514 * sees it or can interact with it. This can only be called
2515 * from the currently active input method, as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002516 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 * @param token Supplies the identifying token given to an input method
2518 * when it was started, which allows it to perform this operation on
2519 * itself.
2520 * @param flags Provides additional operating flags. Currently may be
The Android Open Source Project4df24232009-03-05 14:34:35 -08002521 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
2522 * {@link #HIDE_NOT_ALWAYS} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002523 * @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
2524 * intended for IME developers who should be accessing APIs through the service. APIs in this
2525 * class are intended for app developers interacting with the IME.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002527 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 public void hideSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002529 InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 /**
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002533 * Show the input method's soft input area, so the user
The Android Open Source Project4df24232009-03-05 14:34:35 -08002534 * sees the input method window and can interact with it.
2535 * This can only be called from the currently active input method,
2536 * as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002537 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08002538 * @param token Supplies the identifying token given to an input method
2539 * when it was started, which allows it to perform this operation on
2540 * itself.
2541 * @param flags Provides additional operating flags. Currently may be
2542 * 0 or have the {@link #SHOW_IMPLICIT} or
2543 * {@link #SHOW_FORCED} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002544 * @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
2545 * intended for IME developers who should be accessing APIs through the service. APIs in this
2546 * class are intended for app developers interacting with the IME.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002547 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002548 @Deprecated
The Android Open Source Project4df24232009-03-05 14:34:35 -08002549 public void showSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002550 InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
The Android Open Source Project4df24232009-03-05 14:34:35 -08002551 }
Jeff Brownc28867a2013-03-26 15:42:39 -07002552
The Android Open Source Project4df24232009-03-05 14:34:35 -08002553 /**
Jeff Brownf9e989d2013-04-04 23:04:03 -07002554 * Dispatches an input event to the IME.
2555 *
2556 * Returns {@link #DISPATCH_HANDLED} if the event was handled.
2557 * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
2558 * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
2559 * callback will be invoked later.
2560 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 * @hide
2562 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07002563 public int dispatchInputEvent(InputEvent event, Object token,
2564 FinishedInputEventCallback callback, Handler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002566 if (mCurMethod != null) {
Jeff Brownc28867a2013-03-26 15:42:39 -07002567 if (event instanceof KeyEvent) {
2568 KeyEvent keyEvent = (KeyEvent)event;
2569 if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
2570 && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
2571 && keyEvent.getRepeatCount() == 0) {
2572 showInputMethodPickerLocked();
Jeff Brownf9e989d2013-04-04 23:04:03 -07002573 return DISPATCH_HANDLED;
Jeff Brownc28867a2013-03-26 15:42:39 -07002574 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08002575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576
Jeff Brownc28867a2013-03-26 15:42:39 -07002577 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002578
2579 PendingEvent p = obtainPendingEventLocked(
2580 event, token, mCurId, callback, handler);
2581 if (mMainLooper.isCurrentThread()) {
2582 // Already running on the IMM thread so we can send the event immediately.
2583 return sendInputEventOnMainLooperLocked(p);
Victoria Leaseb38070c2012-08-24 13:46:02 -07002584 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002585
2586 // Post the event to the IMM thread.
2587 Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
2588 msg.setAsynchronous(true);
2589 mH.sendMessage(msg);
2590 return DISPATCH_IN_PROGRESS;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002591 }
2592 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002593 return DISPATCH_NOT_HANDLED;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002594 }
2595
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002596 /**
2597 * Provides the default implementation of {@link InputConnection#sendKeyEvent(KeyEvent)}, which
2598 * is expected to dispatch an keyboard event sent from the IME to an appropriate event target
2599 * depending on the given {@link View} and the current focus state.
2600 *
2601 * <p>CAUTION: This method is provided only for the situation where
2602 * {@link InputConnection#sendKeyEvent(KeyEvent)} needs to be implemented without relying on
2603 * {@link BaseInputConnection}. Do not use this API for anything else.</p>
2604 *
2605 * @param targetView the default target view. If {@code null} is specified, then this method
2606 * tries to find a good event target based on the current focus state.
2607 * @param event the key event to be dispatched.
2608 */
2609 public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
2610 @NonNull KeyEvent event) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002611 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002612 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
2613 if (fallbackImm != null) {
2614 fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002615 return;
2616 }
2617
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002618 synchronized (mH) {
2619 ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
2620 if (viewRootImpl == null) {
lumark970d9d22019-08-18 17:45:24 +08002621 final View servedView = getServedViewLocked();
2622 if (servedView != null) {
2623 viewRootImpl = servedView.getViewRootImpl();
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002624 }
2625 }
2626 if (viewRootImpl != null) {
2627 viewRootImpl.dispatchKeyFromIme(event);
2628 }
2629 }
2630 }
2631
Jeff Brownf9e989d2013-04-04 23:04:03 -07002632 // Must be called on the main looper
2633 void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
2634 final boolean handled;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002635 synchronized (mH) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002636 int result = sendInputEventOnMainLooperLocked(p);
2637 if (result == DISPATCH_IN_PROGRESS) {
2638 return;
2639 }
2640
2641 handled = (result == DISPATCH_HANDLED);
2642 }
2643
2644 invokeFinishedInputEventCallback(p, handled);
2645 }
2646
2647 // Must be called on the main looper
2648 int sendInputEventOnMainLooperLocked(PendingEvent p) {
2649 if (mCurChannel != null) {
2650 if (mCurSender == null) {
2651 mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
2652 }
2653
2654 final InputEvent event = p.mEvent;
2655 final int seq = event.getSequenceNumber();
2656 if (mCurSender.sendInputEvent(seq, event)) {
2657 mPendingEvents.put(seq, p);
2658 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
2659 mPendingEvents.size());
2660
gaoshang863ad2f2017-04-20 14:14:18 +08002661 Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, seq, 0, p);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002662 msg.setAsynchronous(true);
2663 mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
2664 return DISPATCH_IN_PROGRESS;
2665 }
2666
2667 Log.w(TAG, "Unable to send input event to IME: "
2668 + mCurId + " dropping: " + event);
2669 }
2670 return DISPATCH_NOT_HANDLED;
2671 }
2672
2673 void finishedInputEvent(int seq, boolean handled, boolean timeout) {
2674 final PendingEvent p;
2675 synchronized (mH) {
2676 int index = mPendingEvents.indexOfKey(seq);
2677 if (index < 0) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002678 return; // spurious, event already finished or timed out
2679 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002680
Jeff Brownf9e989d2013-04-04 23:04:03 -07002681 p = mPendingEvents.valueAt(index);
2682 mPendingEvents.removeAt(index);
2683 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002684
Jeff Brownf9e989d2013-04-04 23:04:03 -07002685 if (timeout) {
2686 Log.w(TAG, "Timeout waiting for IME to handle input event after "
2687 + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
2688 } else {
2689 mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
Jeff Brown4d656882013-04-03 14:39:19 -07002690 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002691 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002692
2693 invokeFinishedInputEventCallback(p, handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002694 }
2695
Jeff Brownf9e989d2013-04-04 23:04:03 -07002696 // Assumes the event has already been removed from the queue.
2697 void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
2698 p.mHandled = handled;
2699 if (p.mHandler.getLooper().isCurrentThread()) {
2700 // Already running on the callback handler thread so we can send the
2701 // callback immediately.
2702 p.run();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002703 } else {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002704 // Post the event to the callback handler thread.
2705 // In this case, the callback will be responsible for recycling the event.
2706 Message msg = Message.obtain(p.mHandler, p);
2707 msg.setAsynchronous(true);
2708 msg.sendToTarget();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 }
satokab751aa2010-09-14 19:17:36 +09002711
Michael Wrightef17e872013-04-01 13:15:55 -07002712 private void flushPendingEventsLocked() {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002713 mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
Jeff Brown4d656882013-04-03 14:39:19 -07002714
Jeff Brownf9e989d2013-04-04 23:04:03 -07002715 final int count = mPendingEvents.size();
2716 for (int i = 0; i < count; i++) {
2717 int seq = mPendingEvents.keyAt(i);
2718 Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
Michael Wrightef17e872013-04-01 13:15:55 -07002719 msg.setAsynchronous(true);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002720 msg.sendToTarget();
Michael Wrightef17e872013-04-01 13:15:55 -07002721 }
2722 }
2723
Jeff Brownf9e989d2013-04-04 23:04:03 -07002724 private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
2725 String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
2726 PendingEvent p = mPendingEventPool.acquire();
2727 if (p == null) {
2728 p = new PendingEvent();
2729 }
2730 p.mEvent = event;
2731 p.mToken = token;
2732 p.mInputMethodId = inputMethodId;
2733 p.mCallback = callback;
2734 p.mHandler = handler;
2735 return p;
2736 }
2737
2738 private void recyclePendingEventLocked(PendingEvent p) {
2739 p.recycle();
2740 mPendingEventPool.release(p);
2741 }
2742
Tarandeep Singh47e49fd2019-03-12 13:39:38 -07002743 /**
2744 * Show IME picker popup window.
2745 *
2746 * <p>Requires the {@link PackageManager#FEATURE_INPUT_METHODS} feature which can be detected
2747 * using {@link PackageManager#hasSystemFeature(String)}.
2748 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 public void showInputMethodPicker() {
2750 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002751 showInputMethodPickerLocked();
2752 }
2753 }
2754
Seigo Nonaka14e13912015-05-06 21:04:13 -07002755 /**
lumark0b05f9e2018-11-26 15:09:06 +08002756 * Shows the input method chooser dialog from system.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002757 *
2758 * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
lumark0b05f9e2018-11-26 15:09:06 +08002759 * @param displayId The ID of the display where the chooser dialog should be shown.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002760 * @hide
2761 */
lumark0b05f9e2018-11-26 15:09:06 +08002762 @RequiresPermission(WRITE_SECURE_SETTINGS)
2763 public void showInputMethodPickerFromSystem(boolean showAuxiliarySubtypes, int displayId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002764 final int mode = showAuxiliarySubtypes
2765 ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
2766 : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
2767 try {
lumark0b05f9e2018-11-26 15:09:06 +08002768 mService.showInputMethodPickerFromSystem(mClient, mode, displayId);
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002769 } catch (RemoteException e) {
2770 throw e.rethrowFromSystemServer();
Seigo Nonaka14e13912015-05-06 21:04:13 -07002771 }
2772 }
2773
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002774 private void showInputMethodPickerLocked() {
2775 try {
Seigo Nonaka14e13912015-05-06 21:04:13 -07002776 mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002777 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07002778 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 }
2780 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08002781
satokd4fce2b2011-04-11 12:07:13 +09002782 /**
Tarandeep Singheb570612018-01-29 16:20:32 -08002783 * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected.
2784 *
2785 * <p>When customizing the implementation of {@link #showInputMethodPicker()} API, make sure
2786 * that this test API returns when and only while and only while
2787 * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not
2788 * pass CTS.</p>
2789 *
2790 * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI.
2791 * @hide
2792 */
2793 @TestApi
2794 public boolean isInputMethodPickerShown() {
2795 try {
2796 return mService.isInputMethodPickerShownForTest();
2797 } catch (RemoteException e) {
2798 throw e.rethrowFromSystemServer();
2799 }
2800 }
2801
2802 /**
satokd4fce2b2011-04-11 12:07:13 +09002803 * Show the settings for enabling subtypes of the specified input method.
lumark970d9d22019-08-18 17:45:24 +08002804 *
satokd4fce2b2011-04-11 12:07:13 +09002805 * @param imiId An input method, whose subtypes settings will be shown. If imiId is null,
2806 * subtypes of all input methods will be shown.
2807 */
2808 public void showInputMethodAndSubtypeEnabler(String imiId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002809 try {
2810 mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
2811 } catch (RemoteException e) {
2812 throw e.rethrowFromSystemServer();
satok47a44912010-10-06 16:03:58 +09002813 }
2814 }
2815
satokd4fce2b2011-04-11 12:07:13 +09002816 /**
2817 * Returns the current input method subtype. This subtype is one of the subtypes in
2818 * the current input method. This method returns null when the current input method doesn't
2819 * have any input method subtype.
2820 */
satok04d50202010-10-25 22:20:12 +09002821 public InputMethodSubtype getCurrentInputMethodSubtype() {
Gopal Krishna Shuklafa1886f2016-06-30 11:34:21 +05302822 try {
2823 return mService.getCurrentInputMethodSubtype();
2824 } catch (RemoteException e) {
2825 throw e.rethrowFromSystemServer();
satok04d50202010-10-25 22:20:12 +09002826 }
2827 }
2828
satokd4fce2b2011-04-11 12:07:13 +09002829 /**
2830 * Switch to a new input method subtype of the current input method.
2831 * @param subtype A new input method subtype to switch.
2832 * @return true if the current subtype was successfully switched. When the specified subtype is
2833 * null, this method returns false.
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002834 * @deprecated If the calling process is an IME, use
2835 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}, which
2836 * does not require any permission as long as the caller is the current IME.
2837 * If the calling process is some privileged app that already has
2838 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission, just
2839 * directly update {@link Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE}.
satokd4fce2b2011-04-11 12:07:13 +09002840 */
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002841 @Deprecated
Yoshiki Iguchi00d51222015-05-29 15:36:22 +09002842 @RequiresPermission(WRITE_SECURE_SETTINGS)
satokb66d2872010-11-10 01:04:04 +09002843 public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002844 if (Process.myUid() == Process.SYSTEM_UID) {
2845 Log.w(TAG, "System process should not call setCurrentInputMethodSubtype() because "
2846 + "almost always it is a bug under multi-user / multi-profile environment. "
2847 + "Consider directly interacting with InputMethodManagerService "
2848 + "via LocalServices.");
2849 return false;
satokb66d2872010-11-10 01:04:04 +09002850 }
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002851 if (subtype == null) {
2852 // See the JavaDoc. This is how this method has worked.
2853 return false;
2854 }
2855 final Context fallbackContext = ActivityThread.currentApplication();
2856 if (fallbackContext == null) {
2857 return false;
2858 }
2859 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2860 != PackageManager.PERMISSION_GRANTED) {
2861 return false;
2862 }
2863 final ContentResolver contentResolver = fallbackContext.getContentResolver();
2864 final String imeId = Settings.Secure.getString(contentResolver,
2865 Settings.Secure.DEFAULT_INPUT_METHOD);
2866 if (ComponentName.unflattenFromString(imeId) == null) {
2867 // Null or invalid IME ID format.
2868 return false;
2869 }
2870 final List<InputMethodSubtype> enabledSubtypes;
2871 try {
2872 enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true);
2873 } catch (RemoteException e) {
2874 return false;
2875 }
2876 final int numSubtypes = enabledSubtypes.size();
2877 for (int i = 0; i < numSubtypes; ++i) {
2878 final InputMethodSubtype enabledSubtype = enabledSubtypes.get(i);
2879 if (enabledSubtype.equals(subtype)) {
2880 Settings.Secure.putInt(contentResolver,
2881 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, enabledSubtype.hashCode());
2882 return true;
2883 }
2884 }
2885 return false;
satokb66d2872010-11-10 01:04:04 +09002886 }
2887
satokd4fce2b2011-04-11 12:07:13 +09002888 /**
Yohei Yukawa02970512014-06-05 16:16:18 +09002889 * Notify that a user took some action with this input method.
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002890 *
2891 * @deprecated Just kept to avoid possible app compat issue.
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002892 * @hide
2893 */
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002894 @Deprecated
Yohei Yukawaa086f952018-09-11 11:37:08 -07002895 @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
Yohei Yukawa02970512014-06-05 16:16:18 +09002896 public void notifyUserAction() {
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002897 Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
2898 + " that does nothing. Leave comments in b.android.com/114740982 if your "
2899 + " application still depends on the previous behavior of this method.");
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002900 }
2901
2902 /**
satokd4fce2b2011-04-11 12:07:13 +09002903 * Returns a map of all shortcut input method info and their subtypes.
2904 */
satokf3db1af2010-11-23 13:34:33 +09002905 public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
Yohei Yukawafefedc52018-12-24 19:43:17 -08002906 final List<InputMethodInfo> enabledImes = getEnabledInputMethodList();
2907
2908 // Ensure we check system IMEs first.
2909 enabledImes.sort(Comparator.comparingInt(imi -> imi.isSystem() ? 0 : 1));
2910
2911 final int numEnabledImes = enabledImes.size();
2912 for (int imiIndex = 0; imiIndex < numEnabledImes; ++imiIndex) {
2913 final InputMethodInfo imi = enabledImes.get(imiIndex);
2914 final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(
2915 imi, true);
2916 final int subtypeCount = subtypes.size();
2917 for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
2918 final InputMethodSubtype subtype = imi.getSubtypeAt(subtypeIndex);
2919 if (SUBTYPE_MODE_VOICE.equals(subtype.getMode())) {
2920 return Collections.singletonMap(imi, Collections.singletonList(subtype));
satok4e4569d2010-11-19 18:45:53 +09002921 }
satok4e4569d2010-11-19 18:45:53 +09002922 }
satok4e4569d2010-11-19 18:45:53 +09002923 }
Yohei Yukawafefedc52018-12-24 19:43:17 -08002924 return Collections.emptyMap();
satok4e4569d2010-11-19 18:45:53 +09002925 }
satokf3db1af2010-11-23 13:34:33 +09002926
satokd4fce2b2011-04-11 12:07:13 +09002927 /**
Artur Satayevad9254c2019-12-10 17:47:54 +00002928 * This is kept due to {@link android.compat.annotation.UnsupportedAppUsage}.
Yohei Yukawab985e6e2018-09-05 17:07:52 -07002929 *
2930 * <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
2931 * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
2932 * started relying on it.</p>
2933 *
2934 * @return Something that is not well-defined.
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002935 * @hide
2936 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002937 @UnsupportedAppUsage
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002938 public int getInputMethodWindowVisibleHeight() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002939 try {
2940 return mService.getInputMethodWindowVisibleHeight();
2941 } catch (RemoteException e) {
2942 throw e.rethrowFromSystemServer();
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002943 }
2944 }
2945
2946 /**
Yohei Yukawab4f328a2019-05-02 08:41:27 -07002947 * An internal API for {@link android.app.ActivityView} to report where its embedded virtual
2948 * display is placed.
2949 *
2950 * @param childDisplayId Display ID of the embedded virtual display.
2951 * @param matrix {@link Matrix} to convert virtual display screen coordinates to
2952 * the host screen coordinates. {@code null} to clear the relationship.
2953 * @hide
2954 */
2955 public void reportActivityView(int childDisplayId, @Nullable Matrix matrix) {
2956 try {
2957 final float[] matrixValues;
2958 if (matrix == null) {
2959 matrixValues = null;
2960 } else {
2961 matrixValues = new float[9];
2962 matrix.getValues(matrixValues);
2963 }
2964 mService.reportActivityView(mClient, childDisplayId, matrixValues);
2965 } catch (RemoteException e) {
2966 throw e.rethrowFromSystemServer();
2967 }
2968 }
2969
2970 /**
satokd4fce2b2011-04-11 12:07:13 +09002971 * Force switch to the last used input method and subtype. If the last input method didn't have
2972 * any subtypes, the framework will simply switch to the last input method with no subtype
2973 * specified.
2974 * @param imeToken Supplies the identifying token given to an input method when it was started,
2975 * which allows it to perform this operation on itself.
2976 * @return true if the current input method and subtype was successfully switched to the last
2977 * used input method and subtype.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002978 * @deprecated Use {@link InputMethodService#switchToPreviousInputMethod()} instead. This method
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002979 * was intended for IME developers who should be accessing APIs through the service. APIs in
2980 * this class are intended for app developers interacting with the IME.
satokd4fce2b2011-04-11 12:07:13 +09002981 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002982 @Deprecated
satok735cf382010-11-11 20:40:09 +09002983 public boolean switchToLastInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002984 return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod();
satok735cf382010-11-11 20:40:09 +09002985 }
2986
satoke7c6998e2011-06-03 17:57:59 +09002987 /**
satok688bd472012-02-09 20:09:17 +09002988 * Force switch to the next input method and subtype. If there is no IME enabled except
2989 * current IME and subtype, do nothing.
2990 * @param imeToken Supplies the identifying token given to an input method when it was started,
2991 * which allows it to perform this operation on itself.
2992 * @param onlyCurrentIme if true, the framework will find the next subtype which
2993 * belongs to the current IME
2994 * @return true if the current input method and subtype was successfully switched to the next
2995 * input method and subtype.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002996 * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
2997 * method was intended for IME developers who should be accessing APIs through the service.
2998 * APIs in this class are intended for app developers interacting with the IME.
satok688bd472012-02-09 20:09:17 +09002999 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08003000 @Deprecated
satok688bd472012-02-09 20:09:17 +09003001 public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07003002 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
3003 .switchToNextInputMethod(onlyCurrentIme);
satok688bd472012-02-09 20:09:17 +09003004 }
3005
3006 /**
satok15ab6b02013-08-26 14:17:18 +09003007 * Returns true if the current IME needs to offer the users ways to switch to a next input
3008 * method (e.g. a globe key.).
3009 * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
3010 * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
3011 * <p> Note that the system determines the most appropriate next input method
3012 * and subtype in order to provide the consistent user experience in switching
3013 * between IMEs and subtypes.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09003014 * @param imeToken Supplies the identifying token given to an input method when it was started,
3015 * which allows it to perform this operation on itself.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08003016 * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
3017 * instead. This method was intended for IME developers who should be accessing APIs through
3018 * the service. APIs in this class are intended for app developers interacting with the IME.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09003019 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08003020 @Deprecated
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09003021 public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07003022 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
3023 .shouldOfferSwitchingToNextInputMethod();
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09003024 }
3025
3026 /**
satok91e88122011-07-18 11:11:42 +09003027 * Set additional input method subtypes. Only a process which shares the same uid with the IME
3028 * can add additional input method subtypes to the IME.
satok75917b62011-08-31 23:27:39 +09003029 * Please note that a subtype's status is stored in the system.
3030 * For example, enabled subtypes are remembered by the framework even after they are removed
3031 * by using this method. If you re-add the same subtypes again,
3032 * they will just get enabled. If you want to avoid such conflicts, for instance, you may
3033 * want to create a "different" new subtype even with the same locale and mode,
3034 * by changing its extra value. The different subtype won't get affected by the stored past
3035 * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
3036 * to the current implementation.)
Yohei Yukawa70f5c482016-01-04 19:42:36 -08003037 *
3038 * <p>NOTE: If the same subtype exists in both the manifest XML file and additional subtypes
3039 * specified by {@code subtypes}, those multiple instances are automatically merged into one
3040 * instance.</p>
3041 *
3042 * <p>CAVEAT: In API Level 23 and prior, the system may do nothing if an empty
3043 * {@link InputMethodSubtype} is specified in {@code subtypes}, which prevents you from removing
3044 * the last one entry of additional subtypes. If your IME statically defines one or more
3045 * subtypes in the manifest XML file, you may be able to work around this limitation by
3046 * specifying one of those statically defined subtypes in {@code subtypes}.</p>
3047 *
satok91e88122011-07-18 11:11:42 +09003048 * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
satoke7c6998e2011-06-03 17:57:59 +09003049 * @param subtypes subtypes will be added as additional subtypes of the current input method.
Yohei Yukawa92c15b12019-01-22 13:26:45 -08003050 * @deprecated For IMEs that have already implemented features like customizable/downloadable
3051 * keyboard layouts/languages, please start migration to other approaches. One idea
3052 * would be exposing only one unified {@link InputMethodSubtype} then implement
3053 * IME's own language switching mechanism within that unified subtype. The support
3054 * of "Additional Subtype" may be completely dropped in a future version of Android.
satoke7c6998e2011-06-03 17:57:59 +09003055 */
Yohei Yukawa92c15b12019-01-22 13:26:45 -08003056 @Deprecated
satokee5e77c2011-09-02 18:50:15 +09003057 public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07003058 try {
3059 mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
3060 } catch (RemoteException e) {
3061 throw e.rethrowFromSystemServer();
satoke7c6998e2011-06-03 17:57:59 +09003062 }
3063 }
3064
satok68f1b782011-04-11 14:26:04 +09003065 public InputMethodSubtype getLastInputMethodSubtype() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07003066 try {
3067 return mService.getLastInputMethodSubtype();
3068 } catch (RemoteException e) {
3069 throw e.rethrowFromSystemServer();
satok68f1b782011-04-11 14:26:04 +09003070 }
3071 }
3072
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08003073 private void maybeCallServedViewChangedLocked(EditorInfo tba) {
3074 if (mImeInsetsConsumer != null) {
3075 mImeInsetsConsumer.onServedEditorChanged(tba);
3076 }
3077 }
3078
Charles Chen414820e2019-04-15 15:33:26 +08003079 /**
3080 * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
3081 * @return the ID of this display which this {@link InputMethodManager} resides
3082 * @hide
3083 */
3084 @TestApi
3085 public int getDisplayId() {
3086 return mDisplayId;
3087 }
3088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
3090 final Printer p = new PrintWriterPrinter(fout);
3091 p.println("Input method client state for " + this + ":");
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07003092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 p.println(" mService=" + mService);
3094 p.println(" mMainLooper=" + mMainLooper);
3095 p.println(" mIInputContext=" + mIInputContext);
3096 p.println(" mActive=" + mActive
Yohei Yukawa2553e482017-12-15 15:47:33 -08003097 + " mRestartOnNextWindowFocus=" + mRestartOnNextWindowFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 + " mBindSequence=" + mBindSequence
3099 + " mCurId=" + mCurId);
Yohei Yukawa2bc66172017-02-08 11:13:25 -08003100 p.println(" mFullscreenMode=" + mFullscreenMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 p.println(" mCurMethod=" + mCurMethod);
Wale Ogunwale159c3d82015-05-14 12:20:53 -07003102 p.println(" mCurRootView=" + mCurRootView);
lumark970d9d22019-08-18 17:45:24 +08003103 p.println(" mServedView=" + getServedViewLocked());
3104 p.println(" mNextServedView=" + getNextServedViewLocked());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 p.println(" mServedConnecting=" + mServedConnecting);
3106 if (mCurrentTextBoxAttribute != null) {
3107 p.println(" mCurrentTextBoxAttribute:");
3108 mCurrentTextBoxAttribute.dump(p, " ");
3109 } else {
3110 p.println(" mCurrentTextBoxAttribute: null");
3111 }
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07003112 p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
Andreas Gampee6748ce2015-12-11 18:00:38 -08003113 p.println(" mCompletions=" + Arrays.toString(mCompletions));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 p.println(" mCursorRect=" + mCursorRect);
3115 p.println(" mCursorSelStart=" + mCursorSelStart
3116 + " mCursorSelEnd=" + mCursorSelEnd
3117 + " mCursorCandStart=" + mCursorCandStart
3118 + " mCursorCandEnd=" + mCursorCandEnd);
3119 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003120
3121 /**
3122 * Callback that is invoked when an input event that was dispatched to
3123 * the IME has been finished.
3124 * @hide
3125 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07003126 public interface FinishedInputEventCallback {
3127 public void onFinishedInputEvent(Object token, boolean handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003128 }
3129
Jeff Brownc28867a2013-03-26 15:42:39 -07003130 private final class ImeInputEventSender extends InputEventSender {
3131 public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
3132 super(inputChannel, looper);
3133 }
3134
3135 @Override
3136 public void onInputEventFinished(int seq, boolean handled) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07003137 finishedInputEvent(seq, handled, false);
Jeff Brownc28867a2013-03-26 15:42:39 -07003138 }
3139 }
3140
Jeff Brownf9e989d2013-04-04 23:04:03 -07003141 private final class PendingEvent implements Runnable {
3142 public InputEvent mEvent;
3143 public Object mToken;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003144 public String mInputMethodId;
Jeff Brownf9e989d2013-04-04 23:04:03 -07003145 public FinishedInputEventCallback mCallback;
3146 public Handler mHandler;
3147 public boolean mHandled;
3148
3149 public void recycle() {
3150 mEvent = null;
3151 mToken = null;
3152 mInputMethodId = null;
3153 mCallback = null;
3154 mHandler = null;
3155 mHandled = false;
3156 }
3157
3158 @Override
3159 public void run() {
3160 mCallback.onFinishedInputEvent(mToken, mHandled);
3161
3162 synchronized (mH) {
3163 recyclePendingEventLocked(this);
3164 }
3165 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003166 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003167
3168 private static String dumpViewInfo(@Nullable final View view) {
3169 if (view == null) {
3170 return "null";
3171 }
3172 final StringBuilder sb = new StringBuilder();
3173 sb.append(view);
3174 sb.append(",focus=" + view.hasFocus());
3175 sb.append(",windowFocus=" + view.hasWindowFocus());
Dake Guddf6c1e2018-05-10 11:41:19 -07003176 sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003177 sb.append(",window=" + view.getWindowToken());
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08003178 sb.append(",displayId=" + view.getContext().getDisplayId());
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07003179 sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
lumark970d9d22019-08-18 17:45:24 +08003180 sb.append(",hasImeFocus=" + view.hasImeFocus());
3181
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003182 return sb.toString();
3183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184}