blob: 032af1c5c7b583b7b49aa4a6ca2d54158caf7670 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007-2008 The Android Open Source Project
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07003 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07007 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008 * http://www.apache.org/licenses/LICENSE-2.0
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07009 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.view.inputmethod;
18
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080019import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070020import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
Gilles Debunne8cbb4c62011-01-24 12:33:56 -080021
Yohei Yukawa41b094f2018-09-09 23:58:45 -070022import android.annotation.DrawableRes;
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -080023import android.annotation.NonNull;
24import android.annotation.Nullable;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070025import android.annotation.RequiresFeature;
Yoshiki Iguchi00d51222015-05-29 15:36:22 +090026import android.annotation.RequiresPermission;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060027import android.annotation.SystemService;
Tarandeep Singheb570612018-01-29 16:20:32 -080028import android.annotation.TestApi;
Mathew Inwooda570dee2018-08-17 14:56:00 +010029import android.annotation.UnsupportedAppUsage;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080030import android.annotation.UserIdInt;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080031import android.app.ActivityThread;
Yohei Yukawafd8f7212019-01-22 19:25:44 -080032import android.content.ComponentName;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080033import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.Context;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070035import android.content.pm.PackageManager;
Yohei Yukawab4f328a2019-05-02 08:41:27 -070036import android.graphics.Matrix;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.graphics.Rect;
Tarandeep Singhd8d03a82017-11-28 13:35:32 -080038import android.inputmethodservice.InputMethodService;
Yohei Yukawacb768bc2018-10-24 16:05:09 -070039import android.os.Binder;
Yohei Yukawaa086f952018-09-11 11:37:08 -070040import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.os.Bundle;
42import android.os.Handler;
43import android.os.IBinder;
44import android.os.Looper;
45import android.os.Message;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080046import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.RemoteException;
The Android Open Source Project4df24232009-03-05 14:34:35 -080048import android.os.ResultReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060050import android.os.ServiceManager.ServiceNotFoundException;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070051import android.os.Trace;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080052import android.os.UserHandle;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080053import android.provider.Settings;
satokf9f01002011-05-19 21:31:50 +090054import android.text.style.SuggestionSpan;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.util.Log;
Jeff Brownf9e989d2013-04-04 23:04:03 -070056import android.util.Pools.Pool;
57import android.util.Pools.SimplePool;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.util.PrintWriterPrinter;
59import android.util.Printer;
Yohei Yukawab7b79072014-03-25 11:02:00 +090060import android.util.SparseArray;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +080061import android.view.Display;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -080062import android.view.ImeInsetsSourceConsumer;
Jeff Brownc28867a2013-03-26 15:42:39 -070063import android.view.InputChannel;
64import android.view.InputEvent;
65import android.view.InputEventSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.view.KeyEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.view.View;
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070068import android.view.ViewRootImpl;
Yohei Yukawa22dac1c2017-02-12 16:54:16 -080069import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
Dake Guddf6c1e2018-05-10 11:41:19 -070070import android.view.autofill.AutofillManager;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070071
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -070072import com.android.internal.annotations.GuardedBy;
Yohei Yukawaa468d702018-10-21 11:42:34 -070073import com.android.internal.inputmethod.InputMethodDebug;
Yohei Yukawaeec552e2018-09-09 20:48:41 -070074import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
Yohei Yukawa35fa6d52018-10-31 11:33:32 -070075import com.android.internal.inputmethod.StartInputFlags;
Yohei Yukawac6632df2018-10-21 11:47:16 -070076import com.android.internal.inputmethod.StartInputReason;
Yohei Yukawa499e3f72018-10-21 20:15:11 -070077import com.android.internal.inputmethod.UnbindReason;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070078import com.android.internal.os.SomeArgs;
79import com.android.internal.view.IInputConnectionWrapper;
80import com.android.internal.view.IInputContext;
81import com.android.internal.view.IInputMethodClient;
82import com.android.internal.view.IInputMethodManager;
83import com.android.internal.view.IInputMethodSession;
84import com.android.internal.view.InputBindResult;
Gilles Debunned4723bb2010-09-02 15:27:32 -070085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import java.io.FileDescriptor;
87import java.io.PrintWriter;
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -070088import java.lang.reflect.Proxy;
Andreas Gampee6748ce2015-12-11 18:00:38 -080089import java.util.Arrays;
Yohei Yukawafefedc52018-12-24 19:43:17 -080090import java.util.Collections;
91import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import java.util.List;
satokf3db1af2010-11-23 13:34:33 +090093import java.util.Map;
Yohei Yukawac941fed2014-05-14 19:33:35 +090094import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import java.util.concurrent.CountDownLatch;
96import java.util.concurrent.TimeUnit;
97
98/**
99 * Central system API to the overall input method framework (IMF) architecture,
100 * which arbitrates interaction between applications and the current input method.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700101 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 * <p>Topics covered here:
103 * <ol>
104 * <li><a href="#ArchitectureOverview">Architecture Overview</a>
Ken Wakasa384f8ba2012-03-10 09:59:31 +0900105 * <li><a href="#Applications">Applications</a>
106 * <li><a href="#InputMethods">Input Methods</a>
107 * <li><a href="#Security">Security</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 * </ol>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700109 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 * <a name="ArchitectureOverview"></a>
111 * <h3>Architecture Overview</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700112 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 * <p>There are three primary parties involved in the input method
114 * framework (IMF) architecture:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700115 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 * <ul>
117 * <li> The <strong>input method manager</strong> as expressed by this class
118 * is the central point of the system that manages interaction between all
119 * other parts. It is expressed as the client-side API here which exists
120 * in each application context and communicates with a global system service
121 * that manages the interaction across all processes.
122 * <li> An <strong>input method (IME)</strong> implements a particular
123 * interaction model allowing the user to generate text. The system binds
Nick Felker8efc3ee2017-06-26 15:50:19 -0700124 * to the current input method that is in use, causing it to be created and run,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 * and tells it when to hide and show its UI. Only one IME is running at a time.
126 * <li> Multiple <strong>client applications</strong> arbitrate with the input
127 * method manager for input focus and control over the state of the IME. Only
128 * one such client is ever active (working with the IME) at a time.
129 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700130 *
131 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 * <a name="Applications"></a>
133 * <h3>Applications</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700134 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 * <p>In most cases, applications that are using the standard
136 * {@link android.widget.TextView} or its subclasses will have little they need
137 * to do to work well with soft input methods. The main things you need to
138 * be aware of are:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700139 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 * <ul>
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800141 * <li> Properly set the {@link android.R.attr#inputType} in your editable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 * text views, so that the input method will have enough context to help the
143 * user in entering text into them.
144 * <li> Deal well with losing screen space when the input method is
145 * displayed. Ideally an application should handle its window being resized
146 * smaller, but it can rely on the system performing panning of the window
147 * if needed. You should set the {@link android.R.attr#windowSoftInputMode}
148 * attribute on your activity or the corresponding values on windows you
149 * create to help the system determine whether to pan or resize (it will
150 * try to determine this automatically but may get it wrong).
151 * <li> You can also control the preferred soft input state (open, closed, etc)
152 * for your window using the same {@link android.R.attr#windowSoftInputMode}
153 * attribute.
154 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700155 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 * <p>More finer-grained control is available through the APIs here to directly
157 * interact with the IMF and its IME -- either showing or hiding the input
158 * area, letting the user pick an input method, etc.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700159 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 * <p>For the rare people amongst us writing their own text editors, you
161 * will need to implement {@link android.view.View#onCreateInputConnection}
162 * to return a new instance of your own {@link InputConnection} interface
163 * allowing the IME to interact with your editor.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700164 *
165 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 * <a name="InputMethods"></a>
167 * <h3>Input Methods</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700168 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 * <p>An input method (IME) is implemented
170 * as a {@link android.app.Service}, typically deriving from
171 * {@link android.inputmethodservice.InputMethodService}. It must provide
172 * the core {@link InputMethod} interface, though this is normally handled by
173 * {@link android.inputmethodservice.InputMethodService} and implementors will
174 * only need to deal with the higher-level API there.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700175 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 * See the {@link android.inputmethodservice.InputMethodService} class for
177 * more information on implementing IMEs.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700178 *
179 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 * <a name="Security"></a>
181 * <h3>Security</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700182 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 * <p>There are a lot of security issues associated with input methods,
184 * since they essentially have freedom to completely drive the UI and monitor
185 * everything the user enters. The Android input method framework also allows
186 * arbitrary third party IMEs, so care must be taken to restrict their
187 * selection and interactions.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700188 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 * <p>Here are some key points about the security architecture behind the
190 * IMF:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700191 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 * <ul>
193 * <li> <p>Only the system is allowed to directly access an IME's
194 * {@link InputMethod} interface, via the
195 * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission. This is
196 * enforced in the system by not binding to an input method service that does
197 * not require this permission, so the system can guarantee no other untrusted
198 * clients are accessing the current input method outside of its control.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700199 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 * <li> <p>There may be many client processes of the IMF, but only one may
201 * be active at a time. The inactive clients can not interact with key
202 * parts of the IMF through the mechanisms described below.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700203 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 * <li> <p>Clients of an input method are only given access to its
205 * {@link InputMethodSession} interface. One instance of this interface is
206 * created for each client, and only calls from the session associated with
207 * the active client will be processed by the current IME. This is enforced
208 * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
209 * IMEs, but must be explicitly handled by an IME that is customizing the
210 * raw {@link InputMethodSession} implementation.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700211 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 * <li> <p>Only the active client's {@link InputConnection} will accept
213 * operations. The IMF tells each client process whether it is active, and
214 * the framework enforces that in inactive processes calls on to the current
215 * InputConnection will be ignored. This ensures that the current IME can
216 * only deliver events and text edits to the UI that the user sees as
217 * being in focus.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700218 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 * <li> <p>An IME can never interact with an {@link InputConnection} while
220 * the screen is off. This is enforced by making all clients inactive while
221 * the screen is off, and prevents bad IMEs from driving the UI when the user
222 * can not be aware of its behavior.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700223 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * <li> <p>A client application can ask that the system let the user pick a
225 * new IME, but can not programmatically switch to one itself. This avoids
226 * malicious applications from switching the user to their own IME, which
227 * remains running when the user navigates away to another application. An
228 * IME, on the other hand, <em>is</em> allowed to programmatically switch
229 * the system to another IME, since it already has full control of user
230 * input.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700231 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 * <li> <p>The user must explicitly enable a new IME in settings before
233 * they can switch to it, to confirm with the system that they know about it
234 * and want to make it available for use.</p>
235 * </ul>
236 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600237@SystemService(Context.INPUT_METHOD_SERVICE)
Jeff Sharkey98af2e42018-02-16 10:14:57 -0700238@RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239public final class InputMethodManager {
Dianne Hackborn4eba2712009-03-24 19:20:06 -0700240 static final boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 static final String TAG = "InputMethodManager";
242
Jeff Brownf9e989d2013-04-04 23:04:03 -0700243 static final String PENDING_EVENT_COUNTER = "aq:imm";
244
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -0800245 private static final int NOT_A_SUBTYPE_ID = -1;
246
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700247 /**
Yohei Yukawafefedc52018-12-24 19:43:17 -0800248 * A constant that represents Voice IME.
249 *
250 * @see InputMethodSubtype#getMode()
251 */
252 private static final String SUBTYPE_MODE_VOICE = "voice";
253
254 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700255 * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
256 * or indirectly relied on {@link #sInstance} via reflection or something like that.
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700257 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700258 * <p>Here are scenarios we know and there could be more scenarios we are not
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700259 * aware of right know.</p>
260 *
261 * <ul>
262 * <li>Apps that directly access {@link #sInstance} via reflection, which is currently
263 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
264 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
265 * {@link #sInstance} is not {@code null} when such an app is accessing it, but removing
266 * that code from {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal
267 * untested code paths in their apps, which probably happen in an early startup time of that
268 * app.</li>
269 * <li>Apps that directly access {@link #peekInstance()} via reflection, which is currently
270 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
271 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
272 * {@link #peekInstance()} returns non-{@code null} object when such an app is calling
273 * {@link #peekInstance()}, but removing that code from
274 * {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal untested code
275 * paths in their apps, which probably happen in an early startup time of that app. The good
276 * news is that unlike {@link #sInstance}'s case we can at least work around this scenario
277 * by changing the semantics of {@link #peekInstance()}, which is currently defined as
278 * "retrieve the global {@link InputMethodManager} instance, if it exists" to something that
279 * always returns non-{@code null} {@link InputMethodManager}. However, introducing such an
280 * workaround can also trigger different compatibility issues if {@link #peekInstance()} was
281 * called before {@link android.view.WindowManagerGlobal#getWindowSession()} and it expected
282 * {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li>
283 * </ul>
284 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700285 * <p>Since this is purely a compatibility hack, this method must be used only from
286 * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p>
287 *
288 * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p>
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700289 * @hide
290 */
Yohei Yukawa6c075722018-09-21 14:52:12 -0700291 public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800292 forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
Yohei Yukawa6c075722018-09-21 14:52:12 -0700293 }
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700294
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700295 private static final Object sLock = new Object();
296
Yohei Yukawa6c075722018-09-21 14:52:12 -0700297 /**
298 * @deprecated This cannot be compatible with multi-display. Please do not use this.
299 */
300 @Deprecated
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700301 @GuardedBy("sLock")
Mathew Inwooda570dee2018-08-17 14:56:00 +0100302 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -0700303 static InputMethodManager sInstance;
Dianne Hackborn7663d802012-02-24 13:08:49 -0800304
305 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800306 * Global map between display to {@link InputMethodManager}.
307 *
308 * <p>Currently this map works like a so-called leaky singleton. Once an instance is registered
309 * for the associated display ID, that instance will never be garbage collected.</p>
310 *
311 * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
312 */
313 @GuardedBy("sLock")
314 private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
315
316 /**
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700317 * Timeout in milliseconds for delivering a key to an IME.
318 */
319 static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
320
Jeff Brownf9e989d2013-04-04 23:04:03 -0700321 /** @hide */
322 public static final int DISPATCH_IN_PROGRESS = -1;
323
324 /** @hide */
325 public static final int DISPATCH_NOT_HANDLED = 0;
326
327 /** @hide */
328 public static final int DISPATCH_HANDLED = 1;
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700329
Seigo Nonaka14e13912015-05-06 21:04:13 -0700330 /** @hide */
331 public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
332 /** @hide */
333 public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
334 /** @hide */
335 public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
336
Mathew Inwooda570dee2018-08-17 14:56:00 +0100337 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 final IInputMethodManager mService;
339 final Looper mMainLooper;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 // For scheduling work on the main thread. This also serves as our
342 // global lock.
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000343 // Remark on @UnsupportedAppUsage: there were context leaks on old versions
344 // of android (b/37043700), so developers used this field to perform manual clean up.
345 // Leaks were fixed, hacks were backported to AppCompatActivity,
346 // so an access to the field is closed.
347 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 final H mH;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 // Our generic input connection if the current target does not have its own.
351 final IInputContext mIInputContext;
352
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800353 private final int mDisplayId;
354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 /**
356 * True if this input method client is active, initially false.
357 */
358 boolean mActive = false;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 /**
Yohei Yukawa2553e482017-12-15 15:47:33 -0800361 * {@code true} if next {@link #onPostWindowFocus(View, View, int, boolean, int)} needs to
362 * restart input.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 */
Yohei Yukawa2553e482017-12-15 15:47:33 -0800364 boolean mRestartOnNextWindowFocus = true;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 /**
367 * As reported by IME through InputConnection.
368 */
369 boolean mFullscreenMode;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700372
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700373 /**
374 * This is the root view of the overall window that currently has input
375 * method focus.
376 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100377 @UnsupportedAppUsage
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700378 View mCurRootView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 /**
380 * This is the view that should currently be served by an input method,
381 * regardless of the state of setting that up.
382 */
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000383 // See comment to mH field in regard to @UnsupportedAppUsage
384 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 View mServedView;
386 /**
387 * This is then next view that will be served by the input method, when
388 * we get around to updating things.
389 */
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000390 // See comment to mH field in regard to @UnsupportedAppUsage
391 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 View mNextServedView;
393 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 * This is set when we are in the process of connecting, to determine
395 * when we have actually finished.
396 */
397 boolean mServedConnecting;
398 /**
399 * This is non-null when we have connected the served view; it holds
400 * the attributes that were last retrieved from the served view and given
401 * to the input connection.
402 */
403 EditorInfo mCurrentTextBoxAttribute;
404 /**
405 * The InputConnection that was last retrieved from the served view.
406 */
Mathew Inwood8c854f82018-09-14 12:35:36 +0100407 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackbornac920872012-05-22 11:49:49 -0700408 ControlledInputConnectionWrapper mServedInputConnectionWrapper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 /**
410 * The completions that were last provided by the served view.
411 */
412 CompletionInfo[] mCompletions;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 // Cursor position on the screen.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100415 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -0700416 Rect mTmpCursorRect = new Rect();
Mathew Inwooda570dee2018-08-17 14:56:00 +0100417 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 Rect mCursorRect = new Rect();
419 int mCursorSelStart;
420 int mCursorSelEnd;
421 int mCursorCandStart;
422 int mCursorCandEnd;
Yohei Yukawa056ffe62014-05-13 14:26:09 +0900423
424 /**
425 * The instance that has previously been sent to the input method.
426 */
427 private CursorAnchorInfo mCursorAnchorInfo = null;
428
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700429 /**
430 * A special {@link Matrix} that can be provided by the system when this instance is running
431 * inside a virtual display that is managed by {@link android.app.ActivityView}.
432 *
433 * <p>If this is non-{@code null}, {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}
434 * should be adjusted with this {@link Matrix}.</p>
435 *
436 * <p>{@code null} when not used.</p>
437 */
438 private Matrix mActivityViewToScreenMatrix = null;
439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 // -----------------------------------------------------------
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 /**
443 * Sequence number of this binding, as returned by the server.
444 */
445 int mBindSequence = -1;
446 /**
447 * ID of the method we are bound to.
448 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100449 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 String mCurId;
451 /**
452 * The actual instance of the method to make calls on it.
453 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100454 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 IInputMethodSession mCurMethod;
Jeff Brownc28867a2013-03-26 15:42:39 -0700456 InputChannel mCurChannel;
457 ImeInputEventSender mCurSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458
Yohei Yukawaa277db22014-08-21 18:38:44 -0700459 private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900460
461 /**
462 * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
463 */
Yohei Yukawaa277db22014-08-21 18:38:44 -0700464 private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawab7b79072014-03-25 11:02:00 +0900465
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800466 /**
467 * When {@link ViewRootImpl#sNewInsetsMode} is set to
468 * >= {@link ViewRootImpl#NEW_INSETS_MODE_IME}, {@link ImeInsetsSourceConsumer} applies the
469 * IME visibility and listens for other state changes.
470 */
471 private ImeInsetsSourceConsumer mImeInsetsConsumer;
472
Yohei Yukawab0377bb2015-08-10 21:06:30 -0700473 final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
474 final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 static final int MSG_DUMP = 1;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800479 static final int MSG_BIND = 2;
480 static final int MSG_UNBIND = 3;
481 static final int MSG_SET_ACTIVE = 4;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700482 static final int MSG_SEND_INPUT_EVENT = 5;
483 static final int MSG_TIMEOUT_INPUT_EVENT = 6;
484 static final int MSG_FLUSH_INPUT_EVENT = 7;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800485 static final int MSG_REPORT_FULLSCREEN_MODE = 10;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800486 static final int MSG_REPORT_PRE_RENDERED = 15;
487 static final int MSG_APPLY_IME_VISIBILITY = 20;
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700488 static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700489
Dake Guddf6c1e2018-05-10 11:41:19 -0700490 private static boolean isAutofillUIShowing(View servedView) {
491 AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
492 return afm != null && afm.isAutofillUiShowing();
493 }
494
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800495 /**
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700496 * Returns fallback {@link InputMethodManager} if the called one is not likely to be compatible
497 * with the given {@code view}.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800498 *
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700499 * @param view {@link View} to be checked.
500 * @return {@code null} when it is unnecessary (or impossible) to use fallback
501 * {@link InputMethodManager} to which IME API calls need to be re-dispatched.
502 * Non-{@code null} {@link InputMethodManager} if this method believes it'd be safer to
503 * re-dispatch IME APIs calls on it.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800504 */
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700505 @Nullable
506 private InputMethodManager getFallbackInputMethodManagerIfNecessary(@Nullable View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800507 if (view == null) {
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700508 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800509 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700510 // As evidenced in Bug 118341760, view.getViewRootImpl().getDisplayId() is supposed to be
511 // more reliable to determine with which display the given view is interacting than
512 // view.getContext().getDisplayId() / view.getContext().getSystemService(), which can be
513 // easily messed up by app developers (or library authors) by creating inconsistent
514 // ContextWrapper objects that re-dispatch those methods to other Context such as
515 // ApplicationContext.
516 final ViewRootImpl viewRootImpl = view.getViewRootImpl();
517 if (viewRootImpl == null) {
518 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800519 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700520 final int viewRootDisplayId = viewRootImpl.getDisplayId();
521 if (viewRootDisplayId == mDisplayId) {
522 // Expected case. Good to go.
523 return null;
524 }
525 final InputMethodManager fallbackImm =
Charles Chen5299ad02019-04-18 13:09:53 +0000526 viewRootImpl.mContext.getSystemService(InputMethodManager.class);
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700527 if (fallbackImm == null) {
528 Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
529 return null;
530 }
531 if (fallbackImm.mDisplayId != viewRootDisplayId) {
532 Log.e(TAG, "b/117267690: Failed to get fallback IMM with expected displayId="
533 + viewRootDisplayId + " actual IMM#displayId=" + fallbackImm.mDisplayId
534 + " view=" + view);
535 return null;
536 }
537 Log.w(TAG, "b/117267690: Display ID mismatch found."
538 + " ViewRootImpl displayId=" + viewRootDisplayId
539 + " InputMethodManager displayId=" + mDisplayId
540 + ". Use the right InputMethodManager instance to avoid performance overhead.",
541 new Throwable());
542 return fallbackImm;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800543 }
544
Dake Guddf6c1e2018-05-10 11:41:19 -0700545 private static boolean canStartInput(View servedView) {
546 // We can start input ether the servedView has window focus
547 // or the activity is showing autofill ui.
548 return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
549 }
550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 class H extends Handler {
552 H(Looper looper) {
Jeff Brown29c0ed22013-01-14 13:50:37 -0800553 super(looper, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 @Override
557 public void handleMessage(Message msg) {
558 switch (msg.what) {
559 case MSG_DUMP: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700560 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 try {
562 doDump((FileDescriptor)args.arg1,
563 (PrintWriter)args.arg2, (String[])args.arg3);
564 } catch (RuntimeException e) {
565 ((PrintWriter)args.arg2).println("Exception: " + e);
566 }
567 synchronized (args.arg4) {
568 ((CountDownLatch)args.arg4).countDown();
569 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700570 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 return;
572 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800573 case MSG_BIND: {
574 final InputBindResult res = (InputBindResult)msg.obj;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900575 if (DEBUG) {
576 Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
577 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800578 synchronized (mH) {
579 if (mBindSequence < 0 || mBindSequence != res.sequence) {
580 Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
581 + ", given seq=" + res.sequence);
Jeff Brown4d656882013-04-03 14:39:19 -0700582 if (res.channel != null && res.channel != mCurChannel) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700583 res.channel.dispose();
584 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800585 return;
586 }
Jeff Brown4d656882013-04-03 14:39:19 -0700587
Yohei Yukawaa277db22014-08-21 18:38:44 -0700588 mRequestUpdateCursorAnchorInfoMonitorMode =
589 REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900590
Jeff Brown4d656882013-04-03 14:39:19 -0700591 setInputChannelLocked(res.channel);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800592 mCurMethod = res.method;
593 mCurId = res.id;
594 mBindSequence = res.sequence;
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700595 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800596 }
Yohei Yukawa42194222018-10-21 20:14:40 -0700597 startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800598 return;
599 }
600 case MSG_UNBIND: {
601 final int sequence = msg.arg1;
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700602 @UnbindReason
Yohei Yukawa33e81792015-11-17 21:14:42 -0800603 final int reason = msg.arg2;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900604 if (DEBUG) {
Yohei Yukawa33e81792015-11-17 21:14:42 -0800605 Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
Yohei Yukawaa468d702018-10-21 11:42:34 -0700606 " reason=" + InputMethodDebug.unbindReasonToString(reason));
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900607 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800608 final boolean startInput;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800609 synchronized (mH) {
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800610 if (mBindSequence != sequence) {
611 return;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800612 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800613 clearBindingLocked();
614 // If we were actively using the last input method, then
615 // we would like to re-connect to the next input method.
616 if (mServedView != null && mServedView.isFocused()) {
617 mServedConnecting = true;
618 }
619 startInput = mActive;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800620 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800621 if (startInput) {
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800622 startInputInner(
Yohei Yukawa42194222018-10-21 20:14:40 -0700623 StartInputReason.UNBOUND_FROM_IMMS, null, 0, 0, 0);
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800624 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800625 return;
626 }
627 case MSG_SET_ACTIVE: {
628 final boolean active = msg.arg1 != 0;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800629 final boolean fullscreen = msg.arg2 != 0;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900630 if (DEBUG) {
631 Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
632 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800633 synchronized (mH) {
634 mActive = active;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800635 mFullscreenMode = fullscreen;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800636 if (!active) {
637 // Some other client has starting using the IME, so note
638 // that this happened and make sure our own editor's
639 // state is reset.
Yohei Yukawa2553e482017-12-15 15:47:33 -0800640 mRestartOnNextWindowFocus = true;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800641 try {
642 // Note that finishComposingText() is allowed to run
643 // even when we are not active.
644 mIInputContext.finishComposingText();
645 } catch (RemoteException e) {
646 }
Mikael Gullstrand82ae3ff2014-11-25 12:41:53 +0100647 }
648 // Check focus again in case that "onWindowFocus" is called before
649 // handling this message.
Dake Guddf6c1e2018-05-10 11:41:19 -0700650 if (mServedView != null && canStartInput(mServedView)) {
Yohei Yukawa2553e482017-12-15 15:47:33 -0800651 if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
Yohei Yukawa42194222018-10-21 20:14:40 -0700652 final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
653 : StartInputReason.DEACTIVATED_BY_IMMS;
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800654 startInputInner(reason, null, 0, 0, 0);
satok05a6cbe2012-04-05 23:04:08 +0900655 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800656 }
657 }
658 return;
659 }
Jeff Brownf9e989d2013-04-04 23:04:03 -0700660 case MSG_SEND_INPUT_EVENT: {
661 sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
662 return;
663 }
664 case MSG_TIMEOUT_INPUT_EVENT: {
665 finishedInputEvent(msg.arg1, false, true);
666 return;
667 }
668 case MSG_FLUSH_INPUT_EVENT: {
669 finishedInputEvent(msg.arg1, false, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700670 return;
671 }
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800672 case MSG_REPORT_FULLSCREEN_MODE: {
673 final boolean fullscreen = msg.arg1 != 0;
674 InputConnection ic = null;
675 synchronized (mH) {
676 mFullscreenMode = fullscreen;
677 if (mServedInputConnectionWrapper != null) {
678 ic = mServedInputConnectionWrapper.getInputConnection();
679 }
680 }
681 if (ic != null) {
682 ic.reportFullscreenMode(fullscreen);
683 }
684 return;
Yohei Yukawa3d1e8122014-06-06 19:12:47 +0900685 }
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800686 case MSG_REPORT_PRE_RENDERED: {
687 synchronized (mH) {
688 if (mImeInsetsConsumer != null) {
689 mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
690 }
691 }
692 return;
693
694 }
695 case MSG_APPLY_IME_VISIBILITY: {
696 synchronized (mH) {
697 if (mImeInsetsConsumer != null) {
698 mImeInsetsConsumer.applyImeVisibility(msg.arg1 != 0);
699 }
700 }
701 return;
702 }
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700703 case MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX: {
704 final float[] matrixValues = (float[]) msg.obj;
705 final int bindSequence = msg.arg1;
706 synchronized (mH) {
707 if (mBindSequence != bindSequence) {
708 return;
709 }
Tarandeep Singh561a1992019-08-21 17:55:51 -0700710 if (matrixValues == null || mActivityViewToScreenMatrix == null) {
711 // Either InputBoundResult#mActivityViewToScreenMatrixValues is null
712 // OR this app is unbound from the parent ActivityView. In this case,
713 // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700714 mActivityViewToScreenMatrix = null;
715 return;
716 }
717
718 final float[] currentValues = new float[9];
719 mActivityViewToScreenMatrix.getValues(currentValues);
720 if (Arrays.equals(currentValues, matrixValues)) {
721 return;
722 }
723 mActivityViewToScreenMatrix.setValues(matrixValues);
724
725 if (mCursorAnchorInfo == null || mCurMethod == null
726 || mServedInputConnectionWrapper == null) {
727 return;
728 }
729 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode
730 & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
731 if (!isMonitoring) {
732 return;
733 }
734 // Since the host ActivityView is moved, we need to issue
735 // IMS#updateCursorAnchorInfo() again.
736 try {
737 mCurMethod.updateCursorAnchorInfo(
738 CursorAnchorInfo.createForAdditionalParentMatrix(
739 mCursorAnchorInfo, mActivityViewToScreenMatrix));
740 } catch (RemoteException e) {
741 Log.w(TAG, "IME died: " + mCurId, e);
742 }
743 }
744 return;
745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 }
747 }
748 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800749
Jean Chalardde9dbb02011-10-20 19:50:45 +0900750 private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
751 private final InputMethodManager mParentInputMethodManager;
752
753 public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
754 final InputMethodManager inputMethodManager) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 super(mainLooper, conn);
Jean Chalardde9dbb02011-10-20 19:50:45 +0900756 mParentInputMethodManager = inputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 }
758
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800759 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 public boolean isActive() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700761 return mParentInputMethodManager.mActive && !isFinished();
Dianne Hackbornac920872012-05-22 11:49:49 -0700762 }
763
764 void deactivate() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700765 if (isFinished()) {
766 // This is a small performance optimization. Still only the 1st call of
767 // reportFinish() will take effect.
768 return;
769 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700770 closeConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 }
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800772
773 @Override
774 public String toString() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700775 return "ControlledInputConnectionWrapper{"
776 + "connection=" + getInputConnection()
777 + " finished=" + isFinished()
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800778 + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
779 + "}";
780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
Jeff Brownc28867a2013-03-26 15:42:39 -0700784 @Override
785 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 // No need to check for dump permission, since we only give this
787 // interface to the system.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 CountDownLatch latch = new CountDownLatch(1);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700789 SomeArgs sargs = SomeArgs.obtain();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 sargs.arg1 = fd;
791 sargs.arg2 = fout;
792 sargs.arg3 = args;
793 sargs.arg4 = latch;
794 mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
795 try {
796 if (!latch.await(5, TimeUnit.SECONDS)) {
797 fout.println("Timeout waiting for dump");
798 }
799 } catch (InterruptedException e) {
800 fout.println("Interrupted waiting for dump");
801 }
802 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700803
804 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 public void onBindMethod(InputBindResult res) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800806 mH.obtainMessage(MSG_BIND, res).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700808
809 @Override
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700810 public void onUnbindMethod(int sequence, @UnbindReason int unbindReason) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800811 mH.obtainMessage(MSG_UNBIND, sequence, unbindReason).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700813
814 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800815 public void setActive(boolean active, boolean fullscreen) {
816 mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 }
Yohei Yukawab7b79072014-03-25 11:02:00 +0900818
819 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800820 public void reportFullscreenMode(boolean fullscreen) {
821 mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
822 .sendToTarget();
823 }
824
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800825 @Override
826 public void reportPreRendered(EditorInfo info) {
827 mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
828 .sendToTarget();
829 }
830
831 @Override
832 public void applyImeVisibility(boolean setVisible) {
833 mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
834 .sendToTarget();
835 }
836
Yohei Yukawab4f328a2019-05-02 08:41:27 -0700837 @Override
838 public void updateActivityViewToScreenMatrix(int bindSequence, float[] matrixValues) {
839 mH.obtainMessage(MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX, bindSequence, 0,
840 matrixValues).sendToTarget();
841 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700842 };
843
Dianne Hackborn51bf0772009-03-24 19:11:41 -0700844 final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700845
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700846 /**
847 * For layoutlib to clean up static objects inside {@link InputMethodManager}.
848 */
849 static void tearDownEditMode() {
850 if (!isInEditMode()) {
851 throw new UnsupportedOperationException(
852 "This method must be called only from layoutlib");
853 }
854 synchronized (sLock) {
855 sInstance = null;
856 }
Jeff Sharkeya4603d3c2016-08-11 16:54:13 -0600857 }
858
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700859 /**
860 * For layoutlib to override this method to return {@code true}.
861 *
862 * @return {@code true} if the process is running for developer tools
863 * @see View#isInEditMode()
864 */
865 private static boolean isInEditMode() {
866 return false;
867 }
868
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700869 @NonNull
870 private static InputMethodManager createInstance(int displayId, Looper looper) {
871 return isInEditMode() ? createStubInstance(displayId, looper)
872 : createRealInstance(displayId, looper);
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700873 }
874
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700875 @NonNull
876 private static InputMethodManager createRealInstance(int displayId, Looper looper) {
877 final IInputMethodManager service;
878 try {
879 service = IInputMethodManager.Stub.asInterface(
880 ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
881 } catch (ServiceNotFoundException e) {
882 throw new IllegalStateException(e);
883 }
884 final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
Yohei Yukawacb768bc2018-10-24 16:05:09 -0700885 // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
886 // associate PID/UID with each IME client. This means:
887 // A. if this method call will be handled as an IPC, there is no problem.
888 // B. if this method call will be handled as an in-proc method call, we need to
889 // ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
890 // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
891 // 1) doing so has no effect for A and 2) doing so is sufficient for B.
892 final long identity = Binder.clearCallingIdentity();
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700893 try {
894 service.addClient(imm.mClient, imm.mIInputContext, displayId);
895 } catch (RemoteException e) {
896 e.rethrowFromSystemServer();
Yohei Yukawacb768bc2018-10-24 16:05:09 -0700897 } finally {
898 Binder.restoreCallingIdentity(identity);
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700899 }
900 return imm;
901 }
902
903 @NonNull
904 private static InputMethodManager createStubInstance(int displayId, Looper looper) {
905 // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
906 final Class<IInputMethodManager> c = IInputMethodManager.class;
907 final IInputMethodManager stubInterface =
908 (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
909 new Class[]{c}, (proxy, method, args) -> {
910 final Class<?> returnType = method.getReturnType();
911 if (returnType == boolean.class) {
912 return false;
913 } else if (returnType == int.class) {
914 return 0;
915 } else if (returnType == long.class) {
916 return 0L;
917 } else if (returnType == short.class) {
918 return 0;
919 } else if (returnType == char.class) {
920 return 0;
921 } else if (returnType == byte.class) {
922 return 0;
923 } else if (returnType == float.class) {
924 return 0f;
925 } else if (returnType == double.class) {
926 return 0.0;
927 } else {
928 return null;
929 }
930 });
931 return new InputMethodManager(stubInterface, displayId, looper);
932 }
933
934 private InputMethodManager(IInputMethodManager service, int displayId, Looper looper) {
935 mService = service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 mMainLooper = looper;
937 mH = new H(looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800938 mDisplayId = displayId;
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700939 mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 }
941
942 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800943 * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
Yohei Yukawa6c075722018-09-21 14:52:12 -0700944 *
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800945 * @param context {@link Context} for which IME APIs need to work
946 * @return {@link InputMethodManager} instance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 * @hide
948 */
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700949 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800950 public static InputMethodManager forContext(Context context) {
951 final int displayId = context.getDisplayId();
952 // For better backward compatibility, we always use Looper.getMainLooper() for the default
953 // display case.
954 final Looper looper = displayId == Display.DEFAULT_DISPLAY
955 ? Looper.getMainLooper() : context.getMainLooper();
956 return forContextInternal(displayId, looper);
957 }
958
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700959 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800960 private static InputMethodManager forContextInternal(int displayId, Looper looper) {
961 final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700962 synchronized (sLock) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800963 InputMethodManager instance = sInstanceMap.get(displayId);
964 if (instance != null) {
965 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 }
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700967 instance = createInstance(displayId, looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800968 // For backward compatibility, store the instance also to sInstance for default display.
969 if (sInstance == null && isDefaultDisplay) {
970 sInstance = instance;
971 }
972 sInstanceMap.put(displayId, instance);
973 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700978 * Deprecated. Do not use.
979 *
980 * @return global {@link InputMethodManager} instance
Yohei Yukawa484d4af2018-09-17 16:47:08 -0700981 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
982 * support multi-display scenario.
Yohei Yukawa6c075722018-09-21 14:52:12 -0700983 * @hide
984 */
985 @Deprecated
986 @UnsupportedAppUsage
987 public static InputMethodManager getInstance() {
988 Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be"
989 + " compatible with multi-display."
990 + " Use context.getSystemService(InputMethodManager.class) instead.",
991 new Throwable());
992 ensureDefaultInstanceForDefaultDisplayIfNecessary();
993 return peekInstance();
994 }
995
996 /**
997 * Deprecated. Do not use.
998 *
999 * @return {@link #sInstance}
1000 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
1001 * support multi-display scenario.
1002 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 */
Yohei Yukawa484d4af2018-09-17 16:47:08 -07001004 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001005 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -07001006 public static InputMethodManager peekInstance() {
Yohei Yukawa6c075722018-09-21 14:52:12 -07001007 Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be"
1008 + " compatible with multi-display."
1009 + " Use context.getSystemService(InputMethodManager.class) instead.",
1010 new Throwable());
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -07001011 synchronized (sLock) {
1012 return sInstance;
1013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001017 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 public IInputMethodClient getClient() {
1019 return mClient;
1020 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001023 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 public IInputContext getInputContext() {
1025 return mIInputContext;
1026 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001027
Yohei Yukawa629271a2019-02-05 07:50:36 -08001028 /**
1029 * Returns the list of installed input methods.
1030 *
1031 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1032 *
1033 * @return {@link List} of {@link InputMethodInfo}.
1034 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 public List<InputMethodInfo> getInputMethodList() {
1036 try {
Yohei Yukawad20eef82019-02-05 10:45:32 -08001037 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1038 // services InputMethodManagerInternal.getInputMethodListAsUser() should be used
1039 // instead.
1040 return mService.getInputMethodList(UserHandle.myUserId());
1041 } catch (RemoteException e) {
1042 throw e.rethrowFromSystemServer();
1043 }
1044 }
1045
1046 /**
1047 * Returns the list of installed input methods for the specified user.
1048 *
1049 * @param userId user ID to query
1050 * @return {@link List} of {@link InputMethodInfo}.
1051 * @hide
1052 */
1053 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1054 public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
1055 try {
1056 return mService.getInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001058 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 }
1060 }
1061
Yohei Yukawa629271a2019-02-05 07:50:36 -08001062 /**
1063 * Returns the list of enabled input methods.
1064 *
1065 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1066 *
1067 * @return {@link List} of {@link InputMethodInfo}.
1068 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 public List<InputMethodInfo> getEnabledInputMethodList() {
1070 try {
Yohei Yukawa1fb13c52019-02-05 07:55:28 -08001071 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1072 // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used
1073 // instead.
1074 return mService.getEnabledInputMethodList(UserHandle.myUserId());
1075 } catch (RemoteException e) {
1076 throw e.rethrowFromSystemServer();
1077 }
1078 }
1079
1080 /**
1081 * Returns the list of enabled input methods for the specified user.
1082 *
1083 * @param userId user ID to query
1084 * @return {@link List} of {@link InputMethodInfo}.
1085 * @hide
1086 */
1087 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1088 public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
1089 try {
1090 return mService.getEnabledInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001092 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 }
1094 }
1095
satokd4fce2b2011-04-11 12:07:13 +09001096 /**
1097 * Returns a list of enabled input method subtypes for the specified input method info.
Yohei Yukawa629271a2019-02-05 07:50:36 -08001098 *
1099 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1100 *
satokd4fce2b2011-04-11 12:07:13 +09001101 * @param imi An input method info whose subtypes list will be returned.
1102 * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly
1103 * selected subtypes. If an input method info doesn't have enabled subtypes, the framework
1104 * will implicitly enable subtypes according to the current system language.
1105 */
satok16331c82010-12-20 23:48:46 +09001106 public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
1107 boolean allowsImplicitlySelectedSubtypes) {
satok67ddf9c2010-11-17 09:45:54 +09001108 try {
Satoshi Kataokab3c21ac2013-08-07 15:43:29 +09001109 return mService.getEnabledInputMethodSubtypeList(
1110 imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
satok67ddf9c2010-11-17 09:45:54 +09001111 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001112 throw e.rethrowFromSystemServer();
satok67ddf9c2010-11-17 09:45:54 +09001113 }
1114 }
1115
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001116 /**
1117 * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
1118 * intended for IME developers who should be accessing APIs through the service. APIs in this
1119 * class are intended for app developers interacting with the IME.
1120 */
1121 @Deprecated
Yohei Yukawa41b094f2018-09-09 23:58:45 -07001122 public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001123 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 }
1125
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001126 /**
1127 * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
1128 * intended for IME developers who should be accessing APIs through the service. APIs in
1129 * this class are intended for app developers interacting with the IME.
1130 */
1131 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 public void hideStatusIcon(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001133 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 }
1135
Yohei Yukawa17ace292019-01-21 09:24:26 -08001136 /**
1137 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1138 *
1139 * @param spans will be ignored.
1140 *
1141 * @deprecated Do not use.
1142 * @hide
1143 */
1144 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001145 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001146 public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001147 Log.w(TAG, "registerSuggestionSpansForNotification() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001148 }
1149
Yohei Yukawa17ace292019-01-21 09:24:26 -08001150 /**
1151 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1152 *
1153 * @deprecated Do not use.
1154 * @hide
1155 */
1156 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001157 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001158 public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001159 Log.w(TAG, "notifySuggestionPicked() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001160 }
1161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 /**
1163 * Allows you to discover whether the attached input method is running
1164 * in fullscreen mode. Return true if it is fullscreen, entirely covering
1165 * your UI, else returns false.
1166 */
1167 public boolean isFullscreenMode() {
Yohei Yukawa1544def2016-04-26 17:13:38 -07001168 synchronized (mH) {
1169 return mFullscreenMode;
1170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 }
Yohei Yukawa1544def2016-04-26 17:13:38 -07001172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 /**
1174 * Return true if the given view is the currently active view for the
1175 * input method.
1176 */
1177 public boolean isActive(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001178 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001179 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1180 if (fallbackImm != null) {
1181 return fallbackImm.isActive(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001182 }
1183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 checkFocus();
1185 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001186 return (mServedView == view
1187 || (mServedView != null
1188 && mServedView.checkInputConnectionProxy(view)))
1189 && mCurrentTextBoxAttribute != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 }
1191 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 /**
1194 * Return true if any view is currently active in the input method.
1195 */
1196 public boolean isActive() {
1197 checkFocus();
1198 synchronized (mH) {
1199 return mServedView != null && mCurrentTextBoxAttribute != null;
1200 }
1201 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 /**
1204 * Return true if the currently served view is accepting full text edits.
1205 * If false, it has no input connection, so can only handle raw key events.
1206 */
1207 public boolean isAcceptingText() {
1208 checkFocus();
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001209 return mServedInputConnectionWrapper != null &&
1210 mServedInputConnectionWrapper.getInputConnection() != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 }
1212
1213 /**
1214 * Reset all of the state associated with being bound to an input method.
1215 */
1216 void clearBindingLocked() {
Dianne Hackborn6b6b3fd2014-03-24 11:27:18 -07001217 if (DEBUG) Log.v(TAG, "Clearing binding!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 clearConnectionLocked();
Jeff Brown4d656882013-04-03 14:39:19 -07001219 setInputChannelLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 mBindSequence = -1;
1221 mCurId = null;
1222 mCurMethod = null;
Jeff Brown4d656882013-04-03 14:39:19 -07001223 }
1224
1225 void setInputChannelLocked(InputChannel channel) {
1226 if (mCurChannel != channel) {
1227 if (mCurSender != null) {
1228 flushPendingEventsLocked();
1229 mCurSender.dispose();
1230 mCurSender = null;
1231 }
1232 if (mCurChannel != null) {
1233 mCurChannel.dispose();
1234 }
1235 mCurChannel = channel;
Jeff Brownc28867a2013-03-26 15:42:39 -07001236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 }
Jeff Brown4d656882013-04-03 14:39:19 -07001238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 /**
1240 * Reset all of the state associated with a served view being connected
1241 * to an input method
1242 */
1243 void clearConnectionLocked() {
1244 mCurrentTextBoxAttribute = null;
Dianne Hackbornac920872012-05-22 11:49:49 -07001245 if (mServedInputConnectionWrapper != null) {
1246 mServedInputConnectionWrapper.deactivate();
1247 mServedInputConnectionWrapper = null;
1248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 }
Yohei Yukawa0f3a99d2015-05-21 00:15:05 -07001250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 /**
1252 * Disconnect any existing input connection, clearing the served view.
1253 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001254 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 void finishInputLocked() {
1256 mNextServedView = null;
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001257 mActivityViewToScreenMatrix = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 if (mServedView != null) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001259 if (DEBUG) Log.v(TAG, "FINISH INPUT: mServedView=" + dumpViewInfo(mServedView));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 mServedView = null;
1261 mCompletions = null;
1262 mServedConnecting = false;
1263 clearConnectionLocked();
1264 }
1265 }
Gilles Debunnec478c172011-12-19 17:29:24 -08001266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 public void displayCompletions(View view, CompletionInfo[] completions) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001268 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001269 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1270 if (fallbackImm != null) {
1271 fallbackImm.displayCompletions(view, completions);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001272 return;
1273 }
1274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 checkFocus();
1276 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001277 if (mServedView != view && (mServedView == null
1278 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 return;
1280 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 mCompletions = completions;
1283 if (mCurMethod != null) {
1284 try {
1285 mCurMethod.displayCompletions(mCompletions);
1286 } catch (RemoteException e) {
1287 }
1288 }
1289 }
1290 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 public void updateExtractedText(View view, int token, ExtractedText text) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001293 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001294 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1295 if (fallbackImm != null) {
1296 fallbackImm.updateExtractedText(view, token, text);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001297 return;
1298 }
1299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001300 checkFocus();
1301 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001302 if (mServedView != view && (mServedView == null
1303 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 return;
1305 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307 if (mCurMethod != null) {
1308 try {
1309 mCurMethod.updateExtractedText(token, text);
1310 } catch (RemoteException e) {
1311 }
1312 }
1313 }
1314 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 /**
1317 * Flag for {@link #showSoftInput} to indicate that this is an implicit
1318 * request to show the input window, not as the result of a direct request
1319 * by the user. The window may not be shown in this case.
1320 */
1321 public static final int SHOW_IMPLICIT = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 /**
1324 * Flag for {@link #showSoftInput} to indicate that the user has forced
1325 * the input method open (such as by long-pressing menu) so it should
1326 * not be closed until they explicitly do so.
1327 */
1328 public static final int SHOW_FORCED = 0x0002;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001331 * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
1332 * a result receiver: explicitly request that the current input method's
1333 * soft input area be shown to the user, if needed.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001334 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001335 * @param view The currently focused view, which would like to receive
1336 * soft keyboard input.
1337 * @param flags Provides additional operating flags. Currently may be
1338 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
1339 */
1340 public boolean showSoftInput(View view, int flags) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001341 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001342 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1343 if (fallbackImm != null) {
1344 return fallbackImm.showSoftInput(view, flags);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001345 }
1346
The Android Open Source Project4df24232009-03-05 14:34:35 -08001347 return showSoftInput(view, flags, null);
1348 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001349
The Android Open Source Project4df24232009-03-05 14:34:35 -08001350 /**
1351 * Flag for the {@link ResultReceiver} result code from
1352 * {@link #showSoftInput(View, int, ResultReceiver)} and
1353 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1354 * state of the soft input window was unchanged and remains shown.
1355 */
1356 public static final int RESULT_UNCHANGED_SHOWN = 0;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001357
The Android Open Source Project4df24232009-03-05 14:34:35 -08001358 /**
1359 * Flag for the {@link ResultReceiver} result code from
1360 * {@link #showSoftInput(View, int, ResultReceiver)} and
1361 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1362 * state of the soft input window was unchanged and remains hidden.
1363 */
1364 public static final int RESULT_UNCHANGED_HIDDEN = 1;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001365
The Android Open Source Project4df24232009-03-05 14:34:35 -08001366 /**
1367 * Flag for the {@link ResultReceiver} result code from
1368 * {@link #showSoftInput(View, int, ResultReceiver)} and
1369 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1370 * state of the soft input window changed from hidden to shown.
1371 */
1372 public static final int RESULT_SHOWN = 2;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001373
The Android Open Source Project4df24232009-03-05 14:34:35 -08001374 /**
1375 * Flag for the {@link ResultReceiver} result code from
1376 * {@link #showSoftInput(View, int, ResultReceiver)} and
1377 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1378 * state of the soft input window changed from shown to hidden.
1379 */
1380 public static final int RESULT_HIDDEN = 3;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001381
The Android Open Source Project4df24232009-03-05 14:34:35 -08001382 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 * Explicitly request that the current input method's soft input area be
1384 * shown to the user, if needed. Call this if the user interacts with
1385 * your view in such a way that they have expressed they would like to
1386 * start performing input into it.
Yohei Yukawad552a522016-03-20 15:08:31 -07001387 *
1388 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1389 * this method can be a long-lived object, because it may not be
1390 * garbage-collected until all the corresponding {@link ResultReceiver}
1391 * objects transferred to different processes get garbage-collected.
1392 * Follow the general patterns to avoid memory leaks in Android.
1393 * Consider to use {@link java.lang.ref.WeakReference} so that application
1394 * logic objects such as {@link android.app.Activity} and {@link Context}
1395 * can be garbage collected regardless of the lifetime of
1396 * {@link ResultReceiver}.
1397 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 * @param view The currently focused view, which would like to receive
1399 * soft keyboard input.
1400 * @param flags Provides additional operating flags. Currently may be
1401 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001402 * @param resultReceiver If non-null, this will be called by the IME when
1403 * it has processed your request to tell you what it has done. The result
1404 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1405 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1406 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 */
Gilles Debunnead8484b2011-02-17 17:37:51 -08001408 public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001409 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001410 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1411 if (fallbackImm != null) {
1412 return fallbackImm.showSoftInput(view, flags, resultReceiver);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001413 }
1414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 checkFocus();
1416 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001417 if (mServedView != view && (mServedView == null
1418 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001419 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
1421
1422 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001423 return mService.showSoftInput(mClient, flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001425 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
1427 }
1428 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001429
Yohei Yukawa101ae462017-03-31 14:28:18 -07001430 /**
1431 * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
1432 * is publicly released because previous implementations of that class had relied on this method
1433 * via reflection.
1434 *
1435 * @deprecated This is a hidden API. You should never use this.
1436 * @hide
1437 */
1438 @Deprecated
Yohei Yukawa1466e4a2019-02-12 01:42:56 -08001439 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
The Android Open Source Project4df24232009-03-05 14:34:35 -08001440 public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 try {
Yohei Yukawa101ae462017-03-31 14:28:18 -07001442 Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
1443 + "soon. If you are using android.support.v7.widget.SearchView, please update "
1444 + "to version 26.0 or newer version.");
The Android Open Source Project4df24232009-03-05 14:34:35 -08001445 mService.showSoftInput(mClient, flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001447 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 }
1449 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001452 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
1453 * 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 -08001454 * by the user.
1455 */
1456 public static final int HIDE_IMPLICIT_ONLY = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001459 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestShowSelf(int)}
1460 * 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 -08001461 * shown with {@link #SHOW_FORCED}.
1462 */
1463 public static final int HIDE_NOT_ALWAYS = 0x0002;
Gilles Debunnec478c172011-12-19 17:29:24 -08001464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 /**
Gilles Debunne7c8c6d62011-01-24 14:48:14 -08001466 * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
The Android Open Source Project4df24232009-03-05 14:34:35 -08001467 * without a result: request to hide the soft input window from the
1468 * context of the window that is currently accepting input.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001469 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001470 * @param windowToken The token of the window that is making the request,
1471 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1472 * @param flags Provides additional operating flags. Currently may be
1473 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
1474 */
1475 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
1476 return hideSoftInputFromWindow(windowToken, flags, null);
1477 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001478
The Android Open Source Project4df24232009-03-05 14:34:35 -08001479 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 * Request to hide the soft input window from the context of the window
1481 * that is currently accepting input. This should be called as a result
1482 * of the user doing some actually than fairly explicitly requests to
1483 * have the input window hidden.
Yohei Yukawad552a522016-03-20 15:08:31 -07001484 *
1485 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1486 * this method can be a long-lived object, because it may not be
1487 * garbage-collected until all the corresponding {@link ResultReceiver}
1488 * objects transferred to different processes get garbage-collected.
1489 * Follow the general patterns to avoid memory leaks in Android.
1490 * Consider to use {@link java.lang.ref.WeakReference} so that application
1491 * logic objects such as {@link android.app.Activity} and {@link Context}
1492 * can be garbage collected regardless of the lifetime of
1493 * {@link ResultReceiver}.
1494 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 * @param windowToken The token of the window that is making the request,
1496 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1497 * @param flags Provides additional operating flags. Currently may be
1498 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001499 * @param resultReceiver If non-null, this will be called by the IME when
1500 * it has processed your request to tell you what it has done. The result
1501 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1502 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1503 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 */
The Android Open Source Project4df24232009-03-05 14:34:35 -08001505 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
1506 ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 checkFocus();
1508 synchronized (mH) {
1509 if (mServedView == null || mServedView.getWindowToken() != windowToken) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001510 return false;
1511 }
1512
1513 try {
1514 return mService.hideSoftInput(mClient, flags, resultReceiver);
1515 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001516 throw e.rethrowFromSystemServer();
The Android Open Source Project4df24232009-03-05 14:34:35 -08001517 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001518 }
1519 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001520
The Android Open Source Project4df24232009-03-05 14:34:35 -08001521 /**
1522 * This method toggles the input method window display.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001523 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001524 * If not the input window will be displayed.
1525 * @param windowToken The token of the window that is making the request,
1526 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1527 * @param showFlags Provides additional operating flags. May be
1528 * 0 or have the {@link #SHOW_IMPLICIT},
1529 * {@link #SHOW_FORCED} bit set.
1530 * @param hideFlags Provides additional operating flags. May be
1531 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1532 * {@link #HIDE_NOT_ALWAYS} bit set.
1533 **/
1534 public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
1535 synchronized (mH) {
1536 if (mServedView == null || mServedView.getWindowToken() != windowToken) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 return;
1538 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001539 if (mCurMethod != null) {
1540 try {
1541 mCurMethod.toggleSoftInput(showFlags, hideFlags);
1542 } catch (RemoteException e) {
1543 }
1544 }
1545 }
1546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001548 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001549 * This method toggles the input method window display.
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001550 *
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001551 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001552 * If not the input window will be displayed.
1553 * @param showFlags Provides additional operating flags. May be
1554 * 0 or have the {@link #SHOW_IMPLICIT},
1555 * {@link #SHOW_FORCED} bit set.
1556 * @param hideFlags Provides additional operating flags. May be
1557 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1558 * {@link #HIDE_NOT_ALWAYS} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001559 */
1560 public void toggleSoftInput(int showFlags, int hideFlags) {
1561 if (mCurMethod != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001563 mCurMethod.toggleSoftInput(showFlags, hideFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 } catch (RemoteException e) {
1565 }
1566 }
1567 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 /**
1570 * If the input method is currently connected to the given view,
1571 * restart it with its new contents. You should call this when the text
1572 * within your view changes outside of the normal input method or key
1573 * input flow, such as when an application calls TextView.setText().
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001574 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 * @param view The view whose text has changed.
1576 */
1577 public void restartInput(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001578 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001579 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1580 if (fallbackImm != null) {
1581 fallbackImm.restartInput(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001582 return;
1583 }
1584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 checkFocus();
1586 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001587 if (mServedView != view && (mServedView == null
1588 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 return;
1590 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 mServedConnecting = true;
1593 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001594
Yohei Yukawa42194222018-10-21 20:14:40 -07001595 startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001597
Yohei Yukawac6632df2018-10-21 11:47:16 -07001598 boolean startInputInner(@StartInputReason int startInputReason,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001599 @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
1600 @SoftInputModeFlags int softInputMode, int windowFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 final View view;
1602 synchronized (mH) {
1603 view = mServedView;
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 // Make sure we have a window token for the served view.
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001606 if (DEBUG) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001607 Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) +
Yohei Yukawaa468d702018-10-21 11:42:34 -07001608 " reason=" + InputMethodDebug.startInputReasonToString(startInputReason));
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 if (view == null) {
1611 if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
Dianne Hackborn7663d802012-02-24 13:08:49 -08001612 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 }
1614 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001615
Yohei Yukawa80498d52018-06-21 16:24:36 -07001616 if (windowGainingFocus == null) {
1617 windowGainingFocus = view.getWindowToken();
1618 if (windowGainingFocus == null) {
1619 Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
1620 return false;
1621 }
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001622 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
Yohei Yukawa80498d52018-06-21 16:24:36 -07001623 if (view.onCheckIsTextEditor()) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001624 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
Yohei Yukawa80498d52018-06-21 16:24:36 -07001625 }
1626 softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
1627 windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
1628 }
1629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 // Now we need to get an input connection from the served view.
1631 // This is complicated in a couple ways: we can't be holding our lock
1632 // when calling out to the view, and we need to make sure we call into
1633 // the view on the same thread that is driving its view hierarchy.
1634 Handler vh = view.getHandler();
1635 if (vh == null) {
1636 // If the view doesn't have a handler, something has changed out
Satoshi Kataoka35739502012-10-02 19:00:26 +09001637 // from under us, so just close the current input.
1638 // If we don't close the current input, the current input method can remain on the
1639 // screen without a connection.
1640 if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
1641 closeCurrentInput();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001642 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 }
1644 if (vh.getLooper() != Looper.myLooper()) {
1645 // The view is running on a different thread than our own, so
1646 // we need to reschedule our work for over there.
1647 if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
Yohei Yukawa623e94b2018-01-14 16:30:59 -08001648 vh.post(() -> startInputInner(startInputReason, null, 0, 0, 0));
Dianne Hackborn7663d802012-02-24 13:08:49 -08001649 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 // Okay we are now ready to call into the served view and have it
1653 // do its stuff.
1654 // Life is good: let's hook everything up!
1655 EditorInfo tba = new EditorInfo();
Yohei Yukawa02df3282015-06-03 15:58:59 -07001656 // Note: Use Context#getOpPackageName() rather than Context#getPackageName() so that the
1657 // system can verify the consistency between the uid of this process and package name passed
1658 // from here. See comment of Context#getOpPackageName() for details.
1659 tba.packageName = view.getContext().getOpPackageName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 tba.fieldId = view.getId();
1661 InputConnection ic = view.onCreateInputConnection(tba);
1662 if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
Gilles Debunnec478c172011-12-19 17:29:24 -08001663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 synchronized (mH) {
1665 // Now that we are locked again, validate that our state hasn't
1666 // changed.
1667 if (mServedView != view || !mServedConnecting) {
1668 // Something else happened, so abort.
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001669 if (DEBUG) Log.v(TAG,
1670 "Starting input: finished by someone else. view=" + dumpViewInfo(view)
1671 + " mServedView=" + dumpViewInfo(mServedView)
1672 + " mServedConnecting=" + mServedConnecting);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001673 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 // If we already have a text box, then this view is already
1677 // connected so we want to restart it.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001678 if (mCurrentTextBoxAttribute == null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001679 startInputFlags |= StartInputFlags.INITIAL_CONNECTION;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001680 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 // Hook 'em up and let 'er rip.
1683 mCurrentTextBoxAttribute = tba;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001684 maybeCallServedViewChangedLocked(tba);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 mServedConnecting = false;
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001686 if (mServedInputConnectionWrapper != null) {
1687 mServedInputConnectionWrapper.deactivate();
1688 mServedInputConnectionWrapper = null;
1689 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001690 ControlledInputConnectionWrapper servedContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001691 final int missingMethodFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 if (ic != null) {
1693 mCursorSelStart = tba.initialSelStart;
1694 mCursorSelEnd = tba.initialSelEnd;
1695 mCursorCandStart = -1;
1696 mCursorCandEnd = -1;
1697 mCursorRect.setEmpty();
Yohei Yukawa056ffe62014-05-13 14:26:09 +09001698 mCursorAnchorInfo = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001699 final Handler icHandler;
1700 missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
1701 if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER)
1702 != 0) {
1703 // InputConnection#getHandler() is not implemented.
1704 icHandler = null;
1705 } else {
1706 icHandler = ic.getHandler();
1707 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001708 servedContext = new ControlledInputConnectionWrapper(
1709 icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 } else {
1711 servedContext = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001712 missingMethodFlags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001714 mServedInputConnectionWrapper = servedContext;
Yohei Yukawa612cce92016-02-11 17:47:33 -08001715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 try {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001717 if (DEBUG) Log.v(TAG, "START INPUT: view=" + dumpViewInfo(view) + " ic="
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001718 + ic + " tba=" + tba + " startInputFlags="
1719 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001720 final InputBindResult res = mService.startInputOrWindowGainedFocus(
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001721 startInputReason, mClient, windowGainingFocus, startInputFlags,
1722 softInputMode, windowFlags, tba, servedContext, missingMethodFlags,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001723 view.getContext().getApplicationInfo().targetSdkVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
Yohei Yukawa2553e482017-12-15 15:47:33 -08001725 if (res == null) {
1726 Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
1727 + " null. startInputReason="
Yohei Yukawaa468d702018-10-21 11:42:34 -07001728 + InputMethodDebug.startInputReasonToString(startInputReason)
Yohei Yukawa2553e482017-12-15 15:47:33 -08001729 + " editorInfo=" + tba
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001730 + " startInputFlags="
1731 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001732 return false;
1733 }
Yohei Yukawab4f328a2019-05-02 08:41:27 -07001734 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
Yohei Yukawa2553e482017-12-15 15:47:33 -08001735 if (res.id != null) {
1736 setInputChannelLocked(res.channel);
1737 mBindSequence = res.sequence;
1738 mCurMethod = res.method;
1739 mCurId = res.id;
Yohei Yukawa2553e482017-12-15 15:47:33 -08001740 } else if (res.channel != null && res.channel != mCurChannel) {
1741 res.channel.dispose();
1742 }
1743 switch (res.result) {
1744 case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
1745 mRestartOnNextWindowFocus = true;
1746 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 }
1748 if (mCurMethod != null && mCompletions != null) {
1749 try {
1750 mCurMethod.displayCompletions(mCompletions);
1751 } catch (RemoteException e) {
1752 }
1753 }
1754 } catch (RemoteException e) {
1755 Log.w(TAG, "IME died: " + mCurId, e);
1756 }
1757 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001758
1759 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
1761
1762 /**
1763 * When the focused window is dismissed, this method is called to finish the
1764 * input method started before.
1765 * @hide
1766 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001767 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 public void windowDismissed(IBinder appWindowToken) {
1769 checkFocus();
1770 synchronized (mH) {
1771 if (mServedView != null &&
1772 mServedView.getWindowToken() == appWindowToken) {
1773 finishInputLocked();
1774 }
daqidff365e2018-09-19 15:51:22 +08001775 if (mCurRootView != null &&
1776 mCurRootView.getWindowToken() == appWindowToken) {
1777 mCurRootView = null;
1778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 }
1780 }
1781
1782 /**
1783 * Call this when a view receives focus.
1784 * @hide
1785 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001786 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 public void focusIn(View view) {
1788 synchronized (mH) {
1789 focusInLocked(view);
1790 }
1791 }
1792
1793 void focusInLocked(View view) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001794 if (DEBUG) Log.v(TAG, "focusIn: " + dumpViewInfo(view));
Yohei Yukawa5f059652015-05-14 22:16:41 -07001795
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07001796 if (view != null && view.isTemporarilyDetached()) {
1797 // This is a request from a view that is temporarily detached from a window.
1798 if (DEBUG) Log.v(TAG, "Temporarily detached view, ignoring");
1799 return;
1800 }
1801
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001802 if (mCurRootView != view.getRootView()) {
1803 // This is a request from a window that isn't in the window with
1804 // IME focus, so ignore it.
1805 if (DEBUG) Log.v(TAG, "Not IME target window, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 return;
1807 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 mNextServedView = view;
1810 scheduleCheckFocusLocked(view);
1811 }
1812
1813 /**
1814 * Call this when a view loses focus.
1815 * @hide
1816 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001817 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 public void focusOut(View view) {
1819 synchronized (mH) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001820 if (DEBUG) Log.v(TAG, "focusOut: view=" + dumpViewInfo(view)
1821 + " mServedView=" + dumpViewInfo(mServedView));
Yohei Yukawa0b52ed02015-05-29 11:07:02 -07001822 if (mServedView != view) {
1823 // The following code would auto-hide the IME if we end up
1824 // with no more views with focus. This can happen, however,
1825 // whenever we go into touch mode, so it ends up hiding
1826 // at times when we don't really want it to. For now it
1827 // seems better to just turn it all off.
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07001828 // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
Dake Guddf6c1e2018-05-10 11:41:19 -07001829 if (false && canStartInput(view)) {
Yohei Yukawa0b52ed02015-05-29 11:07:02 -07001830 mNextServedView = null;
1831 scheduleCheckFocusLocked(view);
1832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 }
1834 }
1835 }
1836
Yohei Yukawab13f0152015-05-29 17:09:14 -07001837 /**
1838 * Call this when a view is being detached from a {@link android.view.Window}.
1839 * @hide
1840 */
1841 public void onViewDetachedFromWindow(View view) {
1842 synchronized (mH) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001843 if (DEBUG) Log.v(TAG, "onViewDetachedFromWindow: view=" + dumpViewInfo(view)
1844 + " mServedView=" + dumpViewInfo(mServedView));
Yohei Yukawaa4f52ad2016-03-28 17:21:55 -07001845 if (mServedView == view) {
Yohei Yukawab13f0152015-05-29 17:09:14 -07001846 mNextServedView = null;
1847 scheduleCheckFocusLocked(view);
1848 }
1849 }
1850 }
1851
Gilles Debunnec478c172011-12-19 17:29:24 -08001852 static void scheduleCheckFocusLocked(View view) {
Jeff Browna175a5b2012-02-15 19:18:31 -08001853 ViewRootImpl viewRootImpl = view.getViewRootImpl();
1854 if (viewRootImpl != null) {
1855 viewRootImpl.dispatchCheckFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857 }
Jeff Browna175a5b2012-02-15 19:18:31 -08001858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 /**
1860 * @hide
1861 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001862 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 public void checkFocus() {
Yohei Yukawa241eac22016-03-28 00:28:50 -07001864 if (checkFocusNoStartInput(false)) {
Yohei Yukawa42194222018-10-21 20:14:40 -07001865 startInputInner(StartInputReason.CHECK_FOCUS, null, 0, 0, 0);
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +09001866 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001867 }
1868
Yohei Yukawa241eac22016-03-28 00:28:50 -07001869 private boolean checkFocusNoStartInput(boolean forceNewFocus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 // This is called a lot, so short-circuit before locking.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001871 if (mServedView == mNextServedView && !forceNewFocus) {
Dianne Hackborna82ba542012-02-15 18:19:55 -08001872 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 }
satok863fcd62011-06-21 17:38:02 +09001874
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001875 final ControlledInputConnectionWrapper ic;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 synchronized (mH) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001877 if (mServedView == mNextServedView && !forceNewFocus) {
Dianne Hackborna82ba542012-02-15 18:19:55 -08001878 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 }
1880 if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
1881 + " next=" + mNextServedView
satok05a6cbe2012-04-05 23:04:08 +09001882 + " forceNewFocus=" + forceNewFocus
1883 + " package="
1884 + (mServedView != null ? mServedView.getContext().getPackageName() : "<none>"));
Dianne Hackborna82ba542012-02-15 18:19:55 -08001885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 if (mNextServedView == null) {
1887 finishInputLocked();
1888 // In this case, we used to have a focused view on the window,
1889 // but no longer do. We should make sure the input method is
1890 // no longer shown, since it serves no purpose.
1891 closeCurrentInput();
Dianne Hackborna82ba542012-02-15 18:19:55 -08001892 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001894
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001895 ic = mServedInputConnectionWrapper;
Dianne Hackborna82ba542012-02-15 18:19:55 -08001896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 mServedView = mNextServedView;
1898 mCurrentTextBoxAttribute = null;
1899 mCompletions = null;
1900 mServedConnecting = true;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001901 // servedView has changed and it's not editable.
1902 if (!mServedView.onCheckIsTextEditor()) {
1903 maybeCallServedViewChangedLocked(null);
1904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001906
Yohei Yukawa241eac22016-03-28 00:28:50 -07001907 if (ic != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 ic.finishComposingText();
1909 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001910
1911 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001913
Mathew Inwooda570dee2018-08-17 14:56:00 +01001914 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 void closeCurrentInput() {
1916 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001917 mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001919 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 }
1921 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07001924 * Called by ViewAncestor when its window gets input focus.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 * @hide
1926 */
Yohei Yukawa22dac1c2017-02-12 16:54:16 -08001927 public void onPostWindowFocus(View rootView, View focusedView,
1928 @SoftInputModeFlags int softInputMode, boolean first, int windowFlags) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001929 boolean forceNewFocus = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 synchronized (mH) {
1931 if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
Yohei Yukawaa468d702018-10-21 11:42:34 -07001932 + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 + " first=" + first + " flags=#"
1934 + Integer.toHexString(windowFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001935 if (mRestartOnNextWindowFocus) {
1936 if (DEBUG) Log.v(TAG, "Restarting due to mRestartOnNextWindowFocus");
1937 mRestartOnNextWindowFocus = false;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001938 forceNewFocus = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940 focusInLocked(focusedView != null ? focusedView : rootView);
1941 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001942
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001943 int startInputFlags = 0;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001944 if (focusedView != null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001945 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001946 if (focusedView.onCheckIsTextEditor()) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001947 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 }
1949 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001950 if (first) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001951 startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001952 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001953
Yohei Yukawa241eac22016-03-28 00:28:50 -07001954 if (checkFocusNoStartInput(forceNewFocus)) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001955 // We need to restart input on the current focus view. This
1956 // should be done in conjunction with telling the system service
1957 // about the window gaining focus, to help make the transition
1958 // smooth.
Yohei Yukawa42194222018-10-21 20:14:40 -07001959 if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001960 startInputFlags, softInputMode, windowFlags)) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001961 return;
1962 }
1963 }
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001964
Dianne Hackborn7663d802012-02-24 13:08:49 -08001965 // For some reason we didn't do a startInput + windowFocusGain, so
1966 // we'll just do a window focus gain and call it a day.
1967 synchronized (mH) {
1968 try {
Dianne Hackbornac920872012-05-22 11:49:49 -07001969 if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001970 mService.startInputOrWindowGainedFocus(
Yohei Yukawa42194222018-10-21 20:14:40 -07001971 StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001972 rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags,
1973 null, null, 0 /* missingMethodFlags */,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001974 rootView.getContext().getApplicationInfo().targetSdkVersion);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001975 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001976 throw e.rethrowFromSystemServer();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001977 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -08001978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001980
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001981 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001982 @UnsupportedAppUsage
Yohei Yukawa5f059652015-05-14 22:16:41 -07001983 public void onPreWindowFocus(View rootView, boolean hasWindowFocus) {
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001984 synchronized (mH) {
Yohei Yukawa5f059652015-05-14 22:16:41 -07001985 if (rootView == null) {
1986 mCurRootView = null;
1987 } if (hasWindowFocus) {
1988 mCurRootView = rootView;
1989 } else if (rootView == mCurRootView) {
1990 // If the mCurRootView is losing window focus, release the strong reference to it
1991 // so as not to prevent it from being garbage-collected.
1992 mCurRootView = null;
1993 } else {
1994 if (DEBUG) {
1995 Log.v(TAG, "Ignoring onPreWindowFocus()."
1996 + " mCurRootView=" + mCurRootView + " rootView=" + rootView);
1997 }
1998 }
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001999 }
2000 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07002001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002002 /**
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08002003 * Register for IME state callbacks and applying visibility in
2004 * {@link android.view.ImeInsetsSourceConsumer}.
2005 * @hide
2006 */
2007 public void registerImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2008 if (imeInsetsConsumer == null) {
2009 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2010 }
2011
2012 synchronized (mH) {
2013 mImeInsetsConsumer = imeInsetsConsumer;
2014 }
2015 }
2016
2017 /**
Louis Chang3d4a7d12019-04-12 16:18:30 +08002018 * Unregister for IME state callbacks and applying visibility in
2019 * {@link android.view.ImeInsetsSourceConsumer}.
2020 * @hide
2021 */
2022 public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2023 if (imeInsetsConsumer == null) {
2024 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2025 }
2026
2027 synchronized (mH) {
2028 if (mImeInsetsConsumer == imeInsetsConsumer) {
2029 mImeInsetsConsumer = null;
2030 }
2031 }
2032 }
2033
2034 /**
Tarandeep Singh46d59f02019-01-29 18:09:15 -08002035 * Call showSoftInput with currently focused view.
2036 * @return {@code true} if IME can be shown.
2037 * @hide
2038 */
2039 public boolean requestImeShow(ResultReceiver resultReceiver) {
2040 synchronized (mH) {
2041 if (mServedView == null) {
2042 return false;
2043 }
2044 showSoftInput(mServedView, 0 /* flags */, resultReceiver);
2045 return true;
2046 }
2047 }
2048
2049 /**
2050 * Notify IME directly that it is no longer visible.
2051 * @hide
2052 */
2053 public void notifyImeHidden() {
2054 synchronized (mH) {
2055 try {
2056 if (mCurMethod != null) {
2057 mCurMethod.notifyImeHidden();
2058 }
2059 } catch (RemoteException re) {
2060 }
2061 }
2062 }
2063
2064 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 * Report the current selection range.
Jean Chalard6fd68e02014-02-20 17:48:46 +09002066 *
2067 * <p><strong>Editor authors</strong>, you need to call this method whenever
2068 * the cursor moves in your editor. Remember that in addition to doing this, your
2069 * editor needs to always supply current cursor values in
2070 * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
2071 * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
2072 * called, which happens whenever the keyboard shows up or the focus changes
2073 * to a text field, among other cases.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 */
2075 public void updateSelection(View view, int selStart, int selEnd,
2076 int candidatesStart, int candidatesEnd) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002077 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002078 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2079 if (fallbackImm != null) {
2080 fallbackImm.updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002081 return;
2082 }
2083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002084 checkFocus();
2085 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002086 if ((mServedView != view && (mServedView == null
2087 || !mServedView.checkInputConnectionProxy(view)))
2088 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 return;
2090 }
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
2093 || mCursorCandStart != candidatesStart
2094 || mCursorCandEnd != candidatesEnd) {
2095 if (DEBUG) Log.d(TAG, "updateSelection");
2096
2097 try {
2098 if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
Jean Chalardc743cb92013-09-12 16:28:45 +09002099 final int oldSelStart = mCursorSelStart;
2100 final int oldSelEnd = mCursorSelEnd;
2101 // Update internal values before sending updateSelection to the IME, because
2102 // if it changes the text within its onUpdateSelection handler in a way that
2103 // 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 -08002104 mCursorSelStart = selStart;
2105 mCursorSelEnd = selEnd;
2106 mCursorCandStart = candidatesStart;
2107 mCursorCandEnd = candidatesEnd;
Jean Chalardc743cb92013-09-12 16:28:45 +09002108 mCurMethod.updateSelection(oldSelStart, oldSelEnd,
2109 selStart, selEnd, candidatesStart, candidatesEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 } catch (RemoteException e) {
2111 Log.w(TAG, "IME died: " + mCurId, e);
2112 }
2113 }
2114 }
2115 }
2116
2117 /**
satok863fcd62011-06-21 17:38:02 +09002118 * Notify the event when the user tapped or clicked the text view.
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002119 *
2120 * @param view {@link View} which is being clicked.
2121 * @see InputMethodService#onViewClicked(boolean)
2122 * @deprecated The semantics of this method can never be defined well for composite {@link View}
2123 * that works as a giant "Canvas", which can host its own UI hierarchy and sub focus
2124 * state. {@link android.webkit.WebView} is a good example. Application / IME
2125 * developers should not rely on this method.
satok863fcd62011-06-21 17:38:02 +09002126 */
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002127 @Deprecated
satok863fcd62011-06-21 17:38:02 +09002128 public void viewClicked(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002129 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002130 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2131 if (fallbackImm != null) {
2132 fallbackImm.viewClicked(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002133 return;
2134 }
2135
satok863fcd62011-06-21 17:38:02 +09002136 final boolean focusChanged = mServedView != mNextServedView;
2137 checkFocus();
2138 synchronized (mH) {
2139 if ((mServedView != view && (mServedView == null
2140 || !mServedView.checkInputConnectionProxy(view)))
2141 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2142 return;
2143 }
2144 try {
2145 if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
2146 mCurMethod.viewClicked(focusChanged);
2147 } catch (RemoteException e) {
2148 Log.w(TAG, "IME died: " + mCurId, e);
2149 }
2150 }
2151 }
2152
2153 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002154 * Return true if the current input method wants to watch the location
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 * of the input editor's cursor in its window.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002156 *
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002157 * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002158 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002159 @Deprecated
2160 public boolean isWatchingCursor(View view) {
2161 return false;
Yohei Yukawa4de04792014-04-17 12:40:31 +09002162 }
2163
2164 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002165 * Return true if the current input method wants to be notified when cursor/anchor location
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002166 * is changed.
Yohei Yukawab7b79072014-03-25 11:02:00 +09002167 *
2168 * @hide
2169 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002170 @UnsupportedAppUsage
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002171 public boolean isCursorAnchorInfoEnabled() {
2172 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002173 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002174 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawaa277db22014-08-21 18:38:44 -07002175 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002176 InputConnection.CURSOR_UPDATE_MONITOR) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002177 return isImmediate || isMonitoring;
2178 }
2179 }
2180
2181 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002182 * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002183 *
2184 * @hide
2185 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002186 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -07002187 public void setUpdateCursorAnchorInfoMode(int flags) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002188 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002189 mRequestUpdateCursorAnchorInfoMonitorMode = flags;
Yohei Yukawab7b79072014-03-25 11:02:00 +09002190 }
2191 }
2192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 /**
2194 * Report the current cursor location in its window.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002195 *
2196 * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002198 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 public void updateCursor(View view, int left, int top, int right, int bottom) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002200 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002201 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2202 if (fallbackImm != null) {
2203 fallbackImm.updateCursor(view, left, top, right, bottom);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002204 return;
2205 }
2206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 checkFocus();
2208 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002209 if ((mServedView != view && (mServedView == null
2210 || !mServedView.checkInputConnectionProxy(view)))
2211 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 return;
2213 }
Yohei Yukawaa277db22014-08-21 18:38:44 -07002214
2215 mTmpCursorRect.set(left, top, right, bottom);
2216 if (!mCursorRect.equals(mTmpCursorRect)) {
2217 if (DEBUG) Log.d(TAG, "updateCursor");
2218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219 try {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002220 if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
2221 mCurMethod.updateCursor(mTmpCursorRect);
2222 mCursorRect.set(mTmpCursorRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 } catch (RemoteException e) {
2224 Log.w(TAG, "IME died: " + mCurId, e);
2225 }
2226 }
2227 }
2228 }
2229
2230 /**
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002231 * Report positional change of the text insertion point and/or characters in the composition
2232 * string.
2233 */
2234 public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
2235 if (view == null || cursorAnchorInfo == null) {
2236 return;
2237 }
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002238 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002239 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2240 if (fallbackImm != null) {
2241 fallbackImm.updateCursorAnchorInfo(view, cursorAnchorInfo);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002242 return;
2243 }
2244
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002245 checkFocus();
2246 synchronized (mH) {
2247 if ((mServedView != view &&
2248 (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
2249 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2250 return;
2251 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002252 // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
2253 // not been changed from the previous call.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002254 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002255 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002256 if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
Yohei Yukawa73605912014-08-13 16:49:35 +09002257 // TODO: Consider always emitting this message once we have addressed redundant
2258 // calls of this method from android.widget.Editor.
2259 if (DEBUG) {
2260 Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
2261 + cursorAnchorInfo);
2262 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002263 return;
2264 }
2265 if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002266 try {
Yohei Yukawab4f328a2019-05-02 08:41:27 -07002267 if (mActivityViewToScreenMatrix != null) {
2268 mCurMethod.updateCursorAnchorInfo(
2269 CursorAnchorInfo.createForAdditionalParentMatrix(
2270 cursorAnchorInfo, mActivityViewToScreenMatrix));
2271 } else {
2272 mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
2273 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002274 mCursorAnchorInfo = cursorAnchorInfo;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002275 // Clear immediate bit (if any).
Yohei Yukawaa277db22014-08-21 18:38:44 -07002276 mRequestUpdateCursorAnchorInfoMonitorMode &=
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002277 ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002278 } catch (RemoteException e) {
2279 Log.w(TAG, "IME died: " + mCurId, e);
2280 }
2281 }
2282 }
2283
2284 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
2286 * InputMethodSession.appPrivateCommand()} on the current Input Method.
2287 * @param view Optional View that is sending the command, or null if
2288 * you want to send the command regardless of the view that is attached
2289 * to the input method.
2290 * @param action Name of the command to be performed. This <em>must</em>
2291 * be a scoped name, i.e. prefixed with a package name you own, so that
2292 * different developers will not create conflicting commands.
2293 * @param data Any data to include with the command.
2294 */
2295 public void sendAppPrivateCommand(View view, String action, Bundle data) {
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.sendAppPrivateCommand(view, action, data);
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) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002305 if ((mServedView != view && (mServedView == null
2306 || !mServedView.checkInputConnectionProxy(view)))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2308 return;
2309 }
2310 try {
2311 if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
2312 mCurMethod.appPrivateCommand(action, data);
2313 } catch (RemoteException e) {
2314 Log.w(TAG, "IME died: " + mCurId, e);
2315 }
2316 }
2317 }
satok28203512010-11-24 11:06:49 +09002318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 /**
satok28203512010-11-24 11:06:49 +09002320 * Force switch to a new input method component. This can only be called
2321 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002322 *
2323 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, the undocumented behavior that
2324 * token can be {@code null} when the caller has
2325 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} is deprecated. Instead, update
2326 * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2327 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2328 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 * @param token Supplies the identifying token given to an input method
2330 * when it was started, which allows it to perform this operation on
2331 * itself.
2332 * @param id The unique identifier for the new input method to be switched to.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002333 * @deprecated Use {@link InputMethodService#switchInputMethod(String)}
2334 * instead. This method was intended for IME developers who should be accessing APIs through
2335 * 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 -08002336 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002337 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 public void setInputMethod(IBinder token, String id) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002339 if (token == null) {
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002340 // There are still some system components that rely on this undocumented behavior
2341 // regarding null IME token with WRITE_SECURE_SETTINGS. Provide a fallback logic as a
2342 // temporary remedy.
2343 if (id == null) {
2344 return;
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002345 }
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002346 if (Process.myUid() == Process.SYSTEM_UID) {
2347 Log.w(TAG, "System process should not be calling setInputMethod() because almost "
2348 + "always it is a bug under multi-user / multi-profile environment. "
2349 + "Consider interacting with InputMethodManagerService directly via "
2350 + "LocalServices.");
2351 return;
2352 }
2353 final Context fallbackContext = ActivityThread.currentApplication();
2354 if (fallbackContext == null) {
2355 return;
2356 }
2357 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2358 != PackageManager.PERMISSION_GRANTED) {
2359 return;
2360 }
2361 final List<InputMethodInfo> imis = getEnabledInputMethodList();
2362 final int numImis = imis.size();
2363 boolean found = false;
2364 for (int i = 0; i < numImis; ++i) {
2365 final InputMethodInfo imi = imis.get(i);
2366 if (id.equals(imi.getId())) {
2367 found = true;
2368 break;
2369 }
2370 }
2371 if (!found) {
2372 Log.e(TAG, "Ignoring setInputMethod(null, " + id + ") because the specified "
2373 + "id not found in enabled IMEs.");
2374 return;
2375 }
2376 Log.w(TAG, "The undocumented behavior that setInputMethod() accepts null token "
2377 + "when the caller has WRITE_SECURE_SETTINGS is deprecated. This behavior may "
2378 + "be completely removed in a future version. Update secure settings directly "
2379 + "instead.");
2380 final ContentResolver resolver = fallbackContext.getContentResolver();
2381 Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
2382 NOT_A_SUBTYPE_ID);
2383 Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, id);
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002384 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002386 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 }
satok28203512010-11-24 11:06:49 +09002388
2389 /**
2390 * Force switch to a new input method and subtype. This can only be called
2391 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002392 *
2393 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, {@code token} cannot be
2394 * {@code null} even with {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}. Instead,
2395 * update {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2396 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2397 *
satok28203512010-11-24 11:06:49 +09002398 * @param token Supplies the identifying token given to an input method
2399 * when it was started, which allows it to perform this operation on
2400 * itself.
2401 * @param id The unique identifier for the new input method to be switched to.
2402 * @param subtype The new subtype of the new input method to be switched to.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002403 * @deprecated Use
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002404 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002405 * instead. This method was intended for IME developers who should be accessing APIs through
2406 * the service. APIs in this class are intended for app developers interacting with the IME.
satok28203512010-11-24 11:06:49 +09002407 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002408 @Deprecated
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002409 public void setInputMethodAndSubtype(@NonNull IBinder token, String id,
2410 InputMethodSubtype subtype) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002411 if (token == null) {
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002412 Log.e(TAG, "setInputMethodAndSubtype() does not accept null token on Android Q "
2413 + "and later.");
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002414 return;
satok28203512010-11-24 11:06:49 +09002415 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002416 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype);
satok28203512010-11-24 11:06:49 +09002417 }
2418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 /**
2420 * Close/hide the input method's soft input area, so the user no longer
2421 * sees it or can interact with it. This can only be called
2422 * from the currently active input method, as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002423 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002424 * @param token Supplies the identifying token given to an input method
2425 * when it was started, which allows it to perform this operation on
2426 * itself.
2427 * @param flags Provides additional operating flags. Currently may be
The Android Open Source Project4df24232009-03-05 14:34:35 -08002428 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
2429 * {@link #HIDE_NOT_ALWAYS} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002430 * @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
2431 * intended for IME developers who should be accessing APIs through the service. APIs in this
2432 * class are intended for app developers interacting with the IME.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002433 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002434 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 public void hideSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002436 InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002439 /**
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002440 * Show the input method's soft input area, so the user
The Android Open Source Project4df24232009-03-05 14:34:35 -08002441 * sees the input method window and can interact with it.
2442 * This can only be called from the currently active input method,
2443 * as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002444 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08002445 * @param token Supplies the identifying token given to an input method
2446 * when it was started, which allows it to perform this operation on
2447 * itself.
2448 * @param flags Provides additional operating flags. Currently may be
2449 * 0 or have the {@link #SHOW_IMPLICIT} or
2450 * {@link #SHOW_FORCED} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002451 * @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
2452 * intended for IME developers who should be accessing APIs through the service. APIs in this
2453 * class are intended for app developers interacting with the IME.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002454 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002455 @Deprecated
The Android Open Source Project4df24232009-03-05 14:34:35 -08002456 public void showSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002457 InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
The Android Open Source Project4df24232009-03-05 14:34:35 -08002458 }
Jeff Brownc28867a2013-03-26 15:42:39 -07002459
The Android Open Source Project4df24232009-03-05 14:34:35 -08002460 /**
Jeff Brownf9e989d2013-04-04 23:04:03 -07002461 * Dispatches an input event to the IME.
2462 *
2463 * Returns {@link #DISPATCH_HANDLED} if the event was handled.
2464 * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
2465 * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
2466 * callback will be invoked later.
2467 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 * @hide
2469 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07002470 public int dispatchInputEvent(InputEvent event, Object token,
2471 FinishedInputEventCallback callback, Handler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002473 if (mCurMethod != null) {
Jeff Brownc28867a2013-03-26 15:42:39 -07002474 if (event instanceof KeyEvent) {
2475 KeyEvent keyEvent = (KeyEvent)event;
2476 if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
2477 && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
2478 && keyEvent.getRepeatCount() == 0) {
2479 showInputMethodPickerLocked();
Jeff Brownf9e989d2013-04-04 23:04:03 -07002480 return DISPATCH_HANDLED;
Jeff Brownc28867a2013-03-26 15:42:39 -07002481 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08002482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483
Jeff Brownc28867a2013-03-26 15:42:39 -07002484 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002485
2486 PendingEvent p = obtainPendingEventLocked(
2487 event, token, mCurId, callback, handler);
2488 if (mMainLooper.isCurrentThread()) {
2489 // Already running on the IMM thread so we can send the event immediately.
2490 return sendInputEventOnMainLooperLocked(p);
Victoria Leaseb38070c2012-08-24 13:46:02 -07002491 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002492
2493 // Post the event to the IMM thread.
2494 Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
2495 msg.setAsynchronous(true);
2496 mH.sendMessage(msg);
2497 return DISPATCH_IN_PROGRESS;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002498 }
2499 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002500 return DISPATCH_NOT_HANDLED;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002501 }
2502
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002503 /**
2504 * Provides the default implementation of {@link InputConnection#sendKeyEvent(KeyEvent)}, which
2505 * is expected to dispatch an keyboard event sent from the IME to an appropriate event target
2506 * depending on the given {@link View} and the current focus state.
2507 *
2508 * <p>CAUTION: This method is provided only for the situation where
2509 * {@link InputConnection#sendKeyEvent(KeyEvent)} needs to be implemented without relying on
2510 * {@link BaseInputConnection}. Do not use this API for anything else.</p>
2511 *
2512 * @param targetView the default target view. If {@code null} is specified, then this method
2513 * tries to find a good event target based on the current focus state.
2514 * @param event the key event to be dispatched.
2515 */
2516 public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
2517 @NonNull KeyEvent event) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002518 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002519 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
2520 if (fallbackImm != null) {
2521 fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002522 return;
2523 }
2524
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002525 synchronized (mH) {
2526 ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
2527 if (viewRootImpl == null) {
2528 if (mServedView != null) {
2529 viewRootImpl = mServedView.getViewRootImpl();
2530 }
2531 }
2532 if (viewRootImpl != null) {
2533 viewRootImpl.dispatchKeyFromIme(event);
2534 }
2535 }
2536 }
2537
Jeff Brownf9e989d2013-04-04 23:04:03 -07002538 // Must be called on the main looper
2539 void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
2540 final boolean handled;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002541 synchronized (mH) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002542 int result = sendInputEventOnMainLooperLocked(p);
2543 if (result == DISPATCH_IN_PROGRESS) {
2544 return;
2545 }
2546
2547 handled = (result == DISPATCH_HANDLED);
2548 }
2549
2550 invokeFinishedInputEventCallback(p, handled);
2551 }
2552
2553 // Must be called on the main looper
2554 int sendInputEventOnMainLooperLocked(PendingEvent p) {
2555 if (mCurChannel != null) {
2556 if (mCurSender == null) {
2557 mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
2558 }
2559
2560 final InputEvent event = p.mEvent;
2561 final int seq = event.getSequenceNumber();
2562 if (mCurSender.sendInputEvent(seq, event)) {
2563 mPendingEvents.put(seq, p);
2564 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
2565 mPendingEvents.size());
2566
gaoshang863ad2f2017-04-20 14:14:18 +08002567 Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, seq, 0, p);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002568 msg.setAsynchronous(true);
2569 mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
2570 return DISPATCH_IN_PROGRESS;
2571 }
2572
2573 Log.w(TAG, "Unable to send input event to IME: "
2574 + mCurId + " dropping: " + event);
2575 }
2576 return DISPATCH_NOT_HANDLED;
2577 }
2578
2579 void finishedInputEvent(int seq, boolean handled, boolean timeout) {
2580 final PendingEvent p;
2581 synchronized (mH) {
2582 int index = mPendingEvents.indexOfKey(seq);
2583 if (index < 0) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002584 return; // spurious, event already finished or timed out
2585 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002586
Jeff Brownf9e989d2013-04-04 23:04:03 -07002587 p = mPendingEvents.valueAt(index);
2588 mPendingEvents.removeAt(index);
2589 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002590
Jeff Brownf9e989d2013-04-04 23:04:03 -07002591 if (timeout) {
2592 Log.w(TAG, "Timeout waiting for IME to handle input event after "
2593 + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
2594 } else {
2595 mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
Jeff Brown4d656882013-04-03 14:39:19 -07002596 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002597 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002598
2599 invokeFinishedInputEventCallback(p, handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002600 }
2601
Jeff Brownf9e989d2013-04-04 23:04:03 -07002602 // Assumes the event has already been removed from the queue.
2603 void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
2604 p.mHandled = handled;
2605 if (p.mHandler.getLooper().isCurrentThread()) {
2606 // Already running on the callback handler thread so we can send the
2607 // callback immediately.
2608 p.run();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002609 } else {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002610 // Post the event to the callback handler thread.
2611 // In this case, the callback will be responsible for recycling the event.
2612 Message msg = Message.obtain(p.mHandler, p);
2613 msg.setAsynchronous(true);
2614 msg.sendToTarget();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 }
satokab751aa2010-09-14 19:17:36 +09002617
Michael Wrightef17e872013-04-01 13:15:55 -07002618 private void flushPendingEventsLocked() {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002619 mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
Jeff Brown4d656882013-04-03 14:39:19 -07002620
Jeff Brownf9e989d2013-04-04 23:04:03 -07002621 final int count = mPendingEvents.size();
2622 for (int i = 0; i < count; i++) {
2623 int seq = mPendingEvents.keyAt(i);
2624 Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
Michael Wrightef17e872013-04-01 13:15:55 -07002625 msg.setAsynchronous(true);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002626 msg.sendToTarget();
Michael Wrightef17e872013-04-01 13:15:55 -07002627 }
2628 }
2629
Jeff Brownf9e989d2013-04-04 23:04:03 -07002630 private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
2631 String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
2632 PendingEvent p = mPendingEventPool.acquire();
2633 if (p == null) {
2634 p = new PendingEvent();
2635 }
2636 p.mEvent = event;
2637 p.mToken = token;
2638 p.mInputMethodId = inputMethodId;
2639 p.mCallback = callback;
2640 p.mHandler = handler;
2641 return p;
2642 }
2643
2644 private void recyclePendingEventLocked(PendingEvent p) {
2645 p.recycle();
2646 mPendingEventPool.release(p);
2647 }
2648
Tarandeep Singh47e49fd2019-03-12 13:39:38 -07002649 /**
2650 * Show IME picker popup window.
2651 *
2652 * <p>Requires the {@link PackageManager#FEATURE_INPUT_METHODS} feature which can be detected
2653 * using {@link PackageManager#hasSystemFeature(String)}.
2654 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 public void showInputMethodPicker() {
2656 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002657 showInputMethodPickerLocked();
2658 }
2659 }
2660
Seigo Nonaka14e13912015-05-06 21:04:13 -07002661 /**
lumark0b05f9e2018-11-26 15:09:06 +08002662 * Shows the input method chooser dialog from system.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002663 *
2664 * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
lumark0b05f9e2018-11-26 15:09:06 +08002665 * @param displayId The ID of the display where the chooser dialog should be shown.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002666 * @hide
2667 */
lumark0b05f9e2018-11-26 15:09:06 +08002668 @RequiresPermission(WRITE_SECURE_SETTINGS)
2669 public void showInputMethodPickerFromSystem(boolean showAuxiliarySubtypes, int displayId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002670 final int mode = showAuxiliarySubtypes
2671 ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
2672 : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
2673 try {
lumark0b05f9e2018-11-26 15:09:06 +08002674 mService.showInputMethodPickerFromSystem(mClient, mode, displayId);
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002675 } catch (RemoteException e) {
2676 throw e.rethrowFromSystemServer();
Seigo Nonaka14e13912015-05-06 21:04:13 -07002677 }
2678 }
2679
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002680 private void showInputMethodPickerLocked() {
2681 try {
Seigo Nonaka14e13912015-05-06 21:04:13 -07002682 mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002683 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07002684 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 }
2686 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08002687
satokd4fce2b2011-04-11 12:07:13 +09002688 /**
Tarandeep Singheb570612018-01-29 16:20:32 -08002689 * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected.
2690 *
2691 * <p>When customizing the implementation of {@link #showInputMethodPicker()} API, make sure
2692 * that this test API returns when and only while and only while
2693 * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not
2694 * pass CTS.</p>
2695 *
2696 * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI.
2697 * @hide
2698 */
2699 @TestApi
2700 public boolean isInputMethodPickerShown() {
2701 try {
2702 return mService.isInputMethodPickerShownForTest();
2703 } catch (RemoteException e) {
2704 throw e.rethrowFromSystemServer();
2705 }
2706 }
2707
2708 /**
satokd4fce2b2011-04-11 12:07:13 +09002709 * Show the settings for enabling subtypes of the specified input method.
2710 * @param imiId An input method, whose subtypes settings will be shown. If imiId is null,
2711 * subtypes of all input methods will be shown.
2712 */
2713 public void showInputMethodAndSubtypeEnabler(String imiId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002714 try {
2715 mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
2716 } catch (RemoteException e) {
2717 throw e.rethrowFromSystemServer();
satok47a44912010-10-06 16:03:58 +09002718 }
2719 }
2720
satokd4fce2b2011-04-11 12:07:13 +09002721 /**
2722 * Returns the current input method subtype. This subtype is one of the subtypes in
2723 * the current input method. This method returns null when the current input method doesn't
2724 * have any input method subtype.
2725 */
satok04d50202010-10-25 22:20:12 +09002726 public InputMethodSubtype getCurrentInputMethodSubtype() {
Gopal Krishna Shuklafa1886f2016-06-30 11:34:21 +05302727 try {
2728 return mService.getCurrentInputMethodSubtype();
2729 } catch (RemoteException e) {
2730 throw e.rethrowFromSystemServer();
satok04d50202010-10-25 22:20:12 +09002731 }
2732 }
2733
satokd4fce2b2011-04-11 12:07:13 +09002734 /**
2735 * Switch to a new input method subtype of the current input method.
2736 * @param subtype A new input method subtype to switch.
2737 * @return true if the current subtype was successfully switched. When the specified subtype is
2738 * null, this method returns false.
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002739 * @deprecated If the calling process is an IME, use
2740 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}, which
2741 * does not require any permission as long as the caller is the current IME.
2742 * If the calling process is some privileged app that already has
2743 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission, just
2744 * directly update {@link Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE}.
satokd4fce2b2011-04-11 12:07:13 +09002745 */
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002746 @Deprecated
Yoshiki Iguchi00d51222015-05-29 15:36:22 +09002747 @RequiresPermission(WRITE_SECURE_SETTINGS)
satokb66d2872010-11-10 01:04:04 +09002748 public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002749 if (Process.myUid() == Process.SYSTEM_UID) {
2750 Log.w(TAG, "System process should not call setCurrentInputMethodSubtype() because "
2751 + "almost always it is a bug under multi-user / multi-profile environment. "
2752 + "Consider directly interacting with InputMethodManagerService "
2753 + "via LocalServices.");
2754 return false;
satokb66d2872010-11-10 01:04:04 +09002755 }
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002756 if (subtype == null) {
2757 // See the JavaDoc. This is how this method has worked.
2758 return false;
2759 }
2760 final Context fallbackContext = ActivityThread.currentApplication();
2761 if (fallbackContext == null) {
2762 return false;
2763 }
2764 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2765 != PackageManager.PERMISSION_GRANTED) {
2766 return false;
2767 }
2768 final ContentResolver contentResolver = fallbackContext.getContentResolver();
2769 final String imeId = Settings.Secure.getString(contentResolver,
2770 Settings.Secure.DEFAULT_INPUT_METHOD);
2771 if (ComponentName.unflattenFromString(imeId) == null) {
2772 // Null or invalid IME ID format.
2773 return false;
2774 }
2775 final List<InputMethodSubtype> enabledSubtypes;
2776 try {
2777 enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true);
2778 } catch (RemoteException e) {
2779 return false;
2780 }
2781 final int numSubtypes = enabledSubtypes.size();
2782 for (int i = 0; i < numSubtypes; ++i) {
2783 final InputMethodSubtype enabledSubtype = enabledSubtypes.get(i);
2784 if (enabledSubtype.equals(subtype)) {
2785 Settings.Secure.putInt(contentResolver,
2786 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, enabledSubtype.hashCode());
2787 return true;
2788 }
2789 }
2790 return false;
satokb66d2872010-11-10 01:04:04 +09002791 }
2792
satokd4fce2b2011-04-11 12:07:13 +09002793 /**
Yohei Yukawa02970512014-06-05 16:16:18 +09002794 * Notify that a user took some action with this input method.
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002795 *
2796 * @deprecated Just kept to avoid possible app compat issue.
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002797 * @hide
2798 */
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002799 @Deprecated
Yohei Yukawaa086f952018-09-11 11:37:08 -07002800 @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
Yohei Yukawa02970512014-06-05 16:16:18 +09002801 public void notifyUserAction() {
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002802 Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
2803 + " that does nothing. Leave comments in b.android.com/114740982 if your "
2804 + " application still depends on the previous behavior of this method.");
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002805 }
2806
2807 /**
satokd4fce2b2011-04-11 12:07:13 +09002808 * Returns a map of all shortcut input method info and their subtypes.
2809 */
satokf3db1af2010-11-23 13:34:33 +09002810 public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
Yohei Yukawafefedc52018-12-24 19:43:17 -08002811 final List<InputMethodInfo> enabledImes = getEnabledInputMethodList();
2812
2813 // Ensure we check system IMEs first.
2814 enabledImes.sort(Comparator.comparingInt(imi -> imi.isSystem() ? 0 : 1));
2815
2816 final int numEnabledImes = enabledImes.size();
2817 for (int imiIndex = 0; imiIndex < numEnabledImes; ++imiIndex) {
2818 final InputMethodInfo imi = enabledImes.get(imiIndex);
2819 final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(
2820 imi, true);
2821 final int subtypeCount = subtypes.size();
2822 for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
2823 final InputMethodSubtype subtype = imi.getSubtypeAt(subtypeIndex);
2824 if (SUBTYPE_MODE_VOICE.equals(subtype.getMode())) {
2825 return Collections.singletonMap(imi, Collections.singletonList(subtype));
satok4e4569d2010-11-19 18:45:53 +09002826 }
satok4e4569d2010-11-19 18:45:53 +09002827 }
satok4e4569d2010-11-19 18:45:53 +09002828 }
Yohei Yukawafefedc52018-12-24 19:43:17 -08002829 return Collections.emptyMap();
satok4e4569d2010-11-19 18:45:53 +09002830 }
satokf3db1af2010-11-23 13:34:33 +09002831
satokd4fce2b2011-04-11 12:07:13 +09002832 /**
Yohei Yukawab985e6e2018-09-05 17:07:52 -07002833 * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
2834 *
2835 * <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
2836 * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
2837 * started relying on it.</p>
2838 *
2839 * @return Something that is not well-defined.
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002840 * @hide
2841 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002842 @UnsupportedAppUsage
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002843 public int getInputMethodWindowVisibleHeight() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002844 try {
2845 return mService.getInputMethodWindowVisibleHeight();
2846 } catch (RemoteException e) {
2847 throw e.rethrowFromSystemServer();
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002848 }
2849 }
2850
2851 /**
Yohei Yukawab4f328a2019-05-02 08:41:27 -07002852 * An internal API for {@link android.app.ActivityView} to report where its embedded virtual
2853 * display is placed.
2854 *
2855 * @param childDisplayId Display ID of the embedded virtual display.
2856 * @param matrix {@link Matrix} to convert virtual display screen coordinates to
2857 * the host screen coordinates. {@code null} to clear the relationship.
2858 * @hide
2859 */
2860 public void reportActivityView(int childDisplayId, @Nullable Matrix matrix) {
2861 try {
2862 final float[] matrixValues;
2863 if (matrix == null) {
2864 matrixValues = null;
2865 } else {
2866 matrixValues = new float[9];
2867 matrix.getValues(matrixValues);
2868 }
2869 mService.reportActivityView(mClient, childDisplayId, matrixValues);
2870 } catch (RemoteException e) {
2871 throw e.rethrowFromSystemServer();
2872 }
2873 }
2874
2875 /**
satokd4fce2b2011-04-11 12:07:13 +09002876 * Force switch to the last used input method and subtype. If the last input method didn't have
2877 * any subtypes, the framework will simply switch to the last input method with no subtype
2878 * specified.
2879 * @param imeToken Supplies the identifying token given to an input method when it was started,
2880 * which allows it to perform this operation on itself.
2881 * @return true if the current input method and subtype was successfully switched to the last
2882 * used input method and subtype.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002883 * @deprecated Use {@link InputMethodService#switchToPreviousInputMethod()} instead. This method
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002884 * was intended for IME developers who should be accessing APIs through the service. APIs in
2885 * this class are intended for app developers interacting with the IME.
satokd4fce2b2011-04-11 12:07:13 +09002886 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002887 @Deprecated
satok735cf382010-11-11 20:40:09 +09002888 public boolean switchToLastInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002889 return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod();
satok735cf382010-11-11 20:40:09 +09002890 }
2891
satoke7c6998e2011-06-03 17:57:59 +09002892 /**
satok688bd472012-02-09 20:09:17 +09002893 * Force switch to the next input method and subtype. If there is no IME enabled except
2894 * current IME and subtype, do nothing.
2895 * @param imeToken Supplies the identifying token given to an input method when it was started,
2896 * which allows it to perform this operation on itself.
2897 * @param onlyCurrentIme if true, the framework will find the next subtype which
2898 * belongs to the current IME
2899 * @return true if the current input method and subtype was successfully switched to the next
2900 * input method and subtype.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002901 * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
2902 * method was intended for IME developers who should be accessing APIs through the service.
2903 * APIs in this class are intended for app developers interacting with the IME.
satok688bd472012-02-09 20:09:17 +09002904 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002905 @Deprecated
satok688bd472012-02-09 20:09:17 +09002906 public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002907 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
2908 .switchToNextInputMethod(onlyCurrentIme);
satok688bd472012-02-09 20:09:17 +09002909 }
2910
2911 /**
satok15ab6b02013-08-26 14:17:18 +09002912 * Returns true if the current IME needs to offer the users ways to switch to a next input
2913 * method (e.g. a globe key.).
2914 * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
2915 * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
2916 * <p> Note that the system determines the most appropriate next input method
2917 * and subtype in order to provide the consistent user experience in switching
2918 * between IMEs and subtypes.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002919 * @param imeToken Supplies the identifying token given to an input method when it was started,
2920 * which allows it to perform this operation on itself.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002921 * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
2922 * instead. This method was intended for IME developers who should be accessing APIs through
2923 * the service. APIs in this class are intended for app developers interacting with the IME.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002924 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002925 @Deprecated
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002926 public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002927 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
2928 .shouldOfferSwitchingToNextInputMethod();
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002929 }
2930
2931 /**
satok91e88122011-07-18 11:11:42 +09002932 * Set additional input method subtypes. Only a process which shares the same uid with the IME
2933 * can add additional input method subtypes to the IME.
satok75917b62011-08-31 23:27:39 +09002934 * Please note that a subtype's status is stored in the system.
2935 * For example, enabled subtypes are remembered by the framework even after they are removed
2936 * by using this method. If you re-add the same subtypes again,
2937 * they will just get enabled. If you want to avoid such conflicts, for instance, you may
2938 * want to create a "different" new subtype even with the same locale and mode,
2939 * by changing its extra value. The different subtype won't get affected by the stored past
2940 * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
2941 * to the current implementation.)
Yohei Yukawa70f5c482016-01-04 19:42:36 -08002942 *
2943 * <p>NOTE: If the same subtype exists in both the manifest XML file and additional subtypes
2944 * specified by {@code subtypes}, those multiple instances are automatically merged into one
2945 * instance.</p>
2946 *
2947 * <p>CAVEAT: In API Level 23 and prior, the system may do nothing if an empty
2948 * {@link InputMethodSubtype} is specified in {@code subtypes}, which prevents you from removing
2949 * the last one entry of additional subtypes. If your IME statically defines one or more
2950 * subtypes in the manifest XML file, you may be able to work around this limitation by
2951 * specifying one of those statically defined subtypes in {@code subtypes}.</p>
2952 *
satok91e88122011-07-18 11:11:42 +09002953 * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
satoke7c6998e2011-06-03 17:57:59 +09002954 * @param subtypes subtypes will be added as additional subtypes of the current input method.
Yohei Yukawa92c15b12019-01-22 13:26:45 -08002955 * @deprecated For IMEs that have already implemented features like customizable/downloadable
2956 * keyboard layouts/languages, please start migration to other approaches. One idea
2957 * would be exposing only one unified {@link InputMethodSubtype} then implement
2958 * IME's own language switching mechanism within that unified subtype. The support
2959 * of "Additional Subtype" may be completely dropped in a future version of Android.
satoke7c6998e2011-06-03 17:57:59 +09002960 */
Yohei Yukawa92c15b12019-01-22 13:26:45 -08002961 @Deprecated
satokee5e77c2011-09-02 18:50:15 +09002962 public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002963 try {
2964 mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
2965 } catch (RemoteException e) {
2966 throw e.rethrowFromSystemServer();
satoke7c6998e2011-06-03 17:57:59 +09002967 }
2968 }
2969
satok68f1b782011-04-11 14:26:04 +09002970 public InputMethodSubtype getLastInputMethodSubtype() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002971 try {
2972 return mService.getLastInputMethodSubtype();
2973 } catch (RemoteException e) {
2974 throw e.rethrowFromSystemServer();
satok68f1b782011-04-11 14:26:04 +09002975 }
2976 }
2977
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08002978 private void maybeCallServedViewChangedLocked(EditorInfo tba) {
2979 if (mImeInsetsConsumer != null) {
2980 mImeInsetsConsumer.onServedEditorChanged(tba);
2981 }
2982 }
2983
Charles Chen414820e2019-04-15 15:33:26 +08002984 /**
2985 * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
2986 * @return the ID of this display which this {@link InputMethodManager} resides
2987 * @hide
2988 */
2989 @TestApi
2990 public int getDisplayId() {
2991 return mDisplayId;
2992 }
2993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
2995 final Printer p = new PrintWriterPrinter(fout);
2996 p.println("Input method client state for " + this + ":");
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 p.println(" mService=" + mService);
2999 p.println(" mMainLooper=" + mMainLooper);
3000 p.println(" mIInputContext=" + mIInputContext);
3001 p.println(" mActive=" + mActive
Yohei Yukawa2553e482017-12-15 15:47:33 -08003002 + " mRestartOnNextWindowFocus=" + mRestartOnNextWindowFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 + " mBindSequence=" + mBindSequence
3004 + " mCurId=" + mCurId);
Yohei Yukawa2bc66172017-02-08 11:13:25 -08003005 p.println(" mFullscreenMode=" + mFullscreenMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 p.println(" mCurMethod=" + mCurMethod);
Wale Ogunwale159c3d82015-05-14 12:20:53 -07003007 p.println(" mCurRootView=" + mCurRootView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 p.println(" mServedView=" + mServedView);
Dianne Hackborn7663d802012-02-24 13:08:49 -08003009 p.println(" mNextServedView=" + mNextServedView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003010 p.println(" mServedConnecting=" + mServedConnecting);
3011 if (mCurrentTextBoxAttribute != null) {
3012 p.println(" mCurrentTextBoxAttribute:");
3013 mCurrentTextBoxAttribute.dump(p, " ");
3014 } else {
3015 p.println(" mCurrentTextBoxAttribute: null");
3016 }
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07003017 p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
Andreas Gampee6748ce2015-12-11 18:00:38 -08003018 p.println(" mCompletions=" + Arrays.toString(mCompletions));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 p.println(" mCursorRect=" + mCursorRect);
3020 p.println(" mCursorSelStart=" + mCursorSelStart
3021 + " mCursorSelEnd=" + mCursorSelEnd
3022 + " mCursorCandStart=" + mCursorCandStart
3023 + " mCursorCandEnd=" + mCursorCandEnd);
3024 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003025
3026 /**
3027 * Callback that is invoked when an input event that was dispatched to
3028 * the IME has been finished.
3029 * @hide
3030 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07003031 public interface FinishedInputEventCallback {
3032 public void onFinishedInputEvent(Object token, boolean handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003033 }
3034
Jeff Brownc28867a2013-03-26 15:42:39 -07003035 private final class ImeInputEventSender extends InputEventSender {
3036 public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
3037 super(inputChannel, looper);
3038 }
3039
3040 @Override
3041 public void onInputEventFinished(int seq, boolean handled) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07003042 finishedInputEvent(seq, handled, false);
Jeff Brownc28867a2013-03-26 15:42:39 -07003043 }
3044 }
3045
Jeff Brownf9e989d2013-04-04 23:04:03 -07003046 private final class PendingEvent implements Runnable {
3047 public InputEvent mEvent;
3048 public Object mToken;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003049 public String mInputMethodId;
Jeff Brownf9e989d2013-04-04 23:04:03 -07003050 public FinishedInputEventCallback mCallback;
3051 public Handler mHandler;
3052 public boolean mHandled;
3053
3054 public void recycle() {
3055 mEvent = null;
3056 mToken = null;
3057 mInputMethodId = null;
3058 mCallback = null;
3059 mHandler = null;
3060 mHandled = false;
3061 }
3062
3063 @Override
3064 public void run() {
3065 mCallback.onFinishedInputEvent(mToken, mHandled);
3066
3067 synchronized (mH) {
3068 recyclePendingEventLocked(this);
3069 }
3070 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07003071 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003072
3073 private static String dumpViewInfo(@Nullable final View view) {
3074 if (view == null) {
3075 return "null";
3076 }
3077 final StringBuilder sb = new StringBuilder();
3078 sb.append(view);
3079 sb.append(",focus=" + view.hasFocus());
3080 sb.append(",windowFocus=" + view.hasWindowFocus());
Dake Guddf6c1e2018-05-10 11:41:19 -07003081 sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003082 sb.append(",window=" + view.getWindowToken());
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08003083 sb.append(",displayId=" + view.getContext().getDisplayId());
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07003084 sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07003085 return sb.toString();
3086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087}