blob: fd73856bf79b5833eac6f41111994c0d2f3f8d2d [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.graphics.Rect;
Tarandeep Singhd8d03a82017-11-28 13:35:32 -080037import android.inputmethodservice.InputMethodService;
Yohei Yukawacb768bc2018-10-24 16:05:09 -070038import android.os.Binder;
Yohei Yukawaa086f952018-09-11 11:37:08 -070039import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Bundle;
41import android.os.Handler;
42import android.os.IBinder;
43import android.os.Looper;
44import android.os.Message;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080045import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.RemoteException;
The Android Open Source Project4df24232009-03-05 14:34:35 -080047import android.os.ResultReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.os.ServiceManager;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060049import android.os.ServiceManager.ServiceNotFoundException;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070050import android.os.Trace;
Yohei Yukawa1fb13c52019-02-05 07:55:28 -080051import android.os.UserHandle;
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -080052import android.provider.Settings;
satokf9f01002011-05-19 21:31:50 +090053import android.text.style.SuggestionSpan;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.util.Log;
Jeff Brownf9e989d2013-04-04 23:04:03 -070055import android.util.Pools.Pool;
56import android.util.Pools.SimplePool;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.util.PrintWriterPrinter;
58import android.util.Printer;
Yohei Yukawab7b79072014-03-25 11:02:00 +090059import android.util.SparseArray;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +080060import android.view.Display;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -080061import android.view.ImeInsetsSourceConsumer;
Jeff Brownc28867a2013-03-26 15:42:39 -070062import android.view.InputChannel;
63import android.view.InputEvent;
64import android.view.InputEventSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.view.KeyEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.view.View;
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070067import android.view.ViewRootImpl;
Yohei Yukawa22dac1c2017-02-12 16:54:16 -080068import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
Dake Guddf6c1e2018-05-10 11:41:19 -070069import android.view.autofill.AutofillManager;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070070
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -070071import com.android.internal.annotations.GuardedBy;
Yohei Yukawaa468d702018-10-21 11:42:34 -070072import com.android.internal.inputmethod.InputMethodDebug;
Yohei Yukawaeec552e2018-09-09 20:48:41 -070073import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
Yohei Yukawa35fa6d52018-10-31 11:33:32 -070074import com.android.internal.inputmethod.StartInputFlags;
Yohei Yukawac6632df2018-10-21 11:47:16 -070075import com.android.internal.inputmethod.StartInputReason;
Yohei Yukawa499e3f72018-10-21 20:15:11 -070076import com.android.internal.inputmethod.UnbindReason;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070077import com.android.internal.os.SomeArgs;
78import com.android.internal.view.IInputConnectionWrapper;
79import com.android.internal.view.IInputContext;
80import com.android.internal.view.IInputMethodClient;
81import com.android.internal.view.IInputMethodManager;
82import com.android.internal.view.IInputMethodSession;
83import com.android.internal.view.InputBindResult;
Gilles Debunned4723bb2010-09-02 15:27:32 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import java.io.FileDescriptor;
86import java.io.PrintWriter;
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -070087import java.lang.reflect.Proxy;
Andreas Gampee6748ce2015-12-11 18:00:38 -080088import java.util.Arrays;
Yohei Yukawafefedc52018-12-24 19:43:17 -080089import java.util.Collections;
90import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import java.util.List;
satokf3db1af2010-11-23 13:34:33 +090092import java.util.Map;
Yohei Yukawac941fed2014-05-14 19:33:35 +090093import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import java.util.concurrent.CountDownLatch;
95import java.util.concurrent.TimeUnit;
96
97/**
98 * Central system API to the overall input method framework (IMF) architecture,
99 * which arbitrates interaction between applications and the current input method.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700100 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 * <p>Topics covered here:
102 * <ol>
103 * <li><a href="#ArchitectureOverview">Architecture Overview</a>
Ken Wakasa384f8ba2012-03-10 09:59:31 +0900104 * <li><a href="#Applications">Applications</a>
105 * <li><a href="#InputMethods">Input Methods</a>
106 * <li><a href="#Security">Security</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 * </ol>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700108 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 * <a name="ArchitectureOverview"></a>
110 * <h3>Architecture Overview</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700111 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 * <p>There are three primary parties involved in the input method
113 * framework (IMF) architecture:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700114 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 * <ul>
116 * <li> The <strong>input method manager</strong> as expressed by this class
117 * is the central point of the system that manages interaction between all
118 * other parts. It is expressed as the client-side API here which exists
119 * in each application context and communicates with a global system service
120 * that manages the interaction across all processes.
121 * <li> An <strong>input method (IME)</strong> implements a particular
122 * interaction model allowing the user to generate text. The system binds
Nick Felker8efc3ee2017-06-26 15:50:19 -0700123 * 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 -0800124 * and tells it when to hide and show its UI. Only one IME is running at a time.
125 * <li> Multiple <strong>client applications</strong> arbitrate with the input
126 * method manager for input focus and control over the state of the IME. Only
127 * one such client is ever active (working with the IME) at a time.
128 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700129 *
130 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 * <a name="Applications"></a>
132 * <h3>Applications</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700133 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 * <p>In most cases, applications that are using the standard
135 * {@link android.widget.TextView} or its subclasses will have little they need
136 * to do to work well with soft input methods. The main things you need to
137 * be aware of are:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700138 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 * <ul>
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800140 * <li> Properly set the {@link android.R.attr#inputType} in your editable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 * text views, so that the input method will have enough context to help the
142 * user in entering text into them.
143 * <li> Deal well with losing screen space when the input method is
144 * displayed. Ideally an application should handle its window being resized
145 * smaller, but it can rely on the system performing panning of the window
146 * if needed. You should set the {@link android.R.attr#windowSoftInputMode}
147 * attribute on your activity or the corresponding values on windows you
148 * create to help the system determine whether to pan or resize (it will
149 * try to determine this automatically but may get it wrong).
150 * <li> You can also control the preferred soft input state (open, closed, etc)
151 * for your window using the same {@link android.R.attr#windowSoftInputMode}
152 * attribute.
153 * </ul>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700154 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 * <p>More finer-grained control is available through the APIs here to directly
156 * interact with the IMF and its IME -- either showing or hiding the input
157 * area, letting the user pick an input method, etc.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700158 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 * <p>For the rare people amongst us writing their own text editors, you
160 * will need to implement {@link android.view.View#onCreateInputConnection}
161 * to return a new instance of your own {@link InputConnection} interface
162 * allowing the IME to interact with your editor.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700163 *
164 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 * <a name="InputMethods"></a>
166 * <h3>Input Methods</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700167 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 * <p>An input method (IME) is implemented
169 * as a {@link android.app.Service}, typically deriving from
170 * {@link android.inputmethodservice.InputMethodService}. It must provide
171 * the core {@link InputMethod} interface, though this is normally handled by
172 * {@link android.inputmethodservice.InputMethodService} and implementors will
173 * only need to deal with the higher-level API there.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700174 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 * See the {@link android.inputmethodservice.InputMethodService} class for
176 * more information on implementing IMEs.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700177 *
178 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 * <a name="Security"></a>
180 * <h3>Security</h3>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700181 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 * <p>There are a lot of security issues associated with input methods,
183 * since they essentially have freedom to completely drive the UI and monitor
184 * everything the user enters. The Android input method framework also allows
185 * arbitrary third party IMEs, so care must be taken to restrict their
186 * selection and interactions.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700187 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 * <p>Here are some key points about the security architecture behind the
189 * IMF:</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700190 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 * <ul>
192 * <li> <p>Only the system is allowed to directly access an IME's
193 * {@link InputMethod} interface, via the
194 * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission. This is
195 * enforced in the system by not binding to an input method service that does
196 * not require this permission, so the system can guarantee no other untrusted
197 * clients are accessing the current input method outside of its control.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700198 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 * <li> <p>There may be many client processes of the IMF, but only one may
200 * be active at a time. The inactive clients can not interact with key
201 * parts of the IMF through the mechanisms described below.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700202 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 * <li> <p>Clients of an input method are only given access to its
204 * {@link InputMethodSession} interface. One instance of this interface is
205 * created for each client, and only calls from the session associated with
206 * the active client will be processed by the current IME. This is enforced
207 * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
208 * IMEs, but must be explicitly handled by an IME that is customizing the
209 * raw {@link InputMethodSession} implementation.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700210 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 * <li> <p>Only the active client's {@link InputConnection} will accept
212 * operations. The IMF tells each client process whether it is active, and
213 * the framework enforces that in inactive processes calls on to the current
214 * InputConnection will be ignored. This ensures that the current IME can
215 * only deliver events and text edits to the UI that the user sees as
216 * being in focus.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700217 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 * <li> <p>An IME can never interact with an {@link InputConnection} while
219 * the screen is off. This is enforced by making all clients inactive while
220 * the screen is off, and prevents bad IMEs from driving the UI when the user
221 * can not be aware of its behavior.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700222 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 * <li> <p>A client application can ask that the system let the user pick a
224 * new IME, but can not programmatically switch to one itself. This avoids
225 * malicious applications from switching the user to their own IME, which
226 * remains running when the user navigates away to another application. An
227 * IME, on the other hand, <em>is</em> allowed to programmatically switch
228 * the system to another IME, since it already has full control of user
229 * input.</p>
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700230 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 * <li> <p>The user must explicitly enable a new IME in settings before
232 * they can switch to it, to confirm with the system that they know about it
233 * and want to make it available for use.</p>
234 * </ul>
235 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600236@SystemService(Context.INPUT_METHOD_SERVICE)
Jeff Sharkey98af2e42018-02-16 10:14:57 -0700237@RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238public final class InputMethodManager {
Dianne Hackborn4eba2712009-03-24 19:20:06 -0700239 static final boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 static final String TAG = "InputMethodManager";
241
Jeff Brownf9e989d2013-04-04 23:04:03 -0700242 static final String PENDING_EVENT_COUNTER = "aq:imm";
243
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -0800244 private static final int NOT_A_SUBTYPE_ID = -1;
245
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700246 /**
Yohei Yukawafefedc52018-12-24 19:43:17 -0800247 * A constant that represents Voice IME.
248 *
249 * @see InputMethodSubtype#getMode()
250 */
251 private static final String SUBTYPE_MODE_VOICE = "voice";
252
253 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700254 * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
255 * or indirectly relied on {@link #sInstance} via reflection or something like that.
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700256 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700257 * <p>Here are scenarios we know and there could be more scenarios we are not
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700258 * aware of right know.</p>
259 *
260 * <ul>
261 * <li>Apps that directly access {@link #sInstance} via reflection, which is currently
262 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
263 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
264 * {@link #sInstance} is not {@code null} when such an app is accessing it, but removing
265 * that code from {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal
266 * untested code paths in their apps, which probably happen in an early startup time of that
267 * app.</li>
268 * <li>Apps that directly access {@link #peekInstance()} via reflection, which is currently
269 * allowed because of {@link UnsupportedAppUsage} annotation. Currently
270 * {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
271 * {@link #peekInstance()} returns non-{@code null} object when such an app is calling
272 * {@link #peekInstance()}, but removing that code from
273 * {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal untested code
274 * paths in their apps, which probably happen in an early startup time of that app. The good
275 * news is that unlike {@link #sInstance}'s case we can at least work around this scenario
276 * by changing the semantics of {@link #peekInstance()}, which is currently defined as
277 * "retrieve the global {@link InputMethodManager} instance, if it exists" to something that
278 * always returns non-{@code null} {@link InputMethodManager}. However, introducing such an
279 * workaround can also trigger different compatibility issues if {@link #peekInstance()} was
280 * called before {@link android.view.WindowManagerGlobal#getWindowSession()} and it expected
281 * {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li>
282 * </ul>
283 *
Yohei Yukawa6c075722018-09-21 14:52:12 -0700284 * <p>Since this is purely a compatibility hack, this method must be used only from
285 * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p>
286 *
287 * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p>
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700288 * @hide
289 */
Yohei Yukawa6c075722018-09-21 14:52:12 -0700290 public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800291 forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
Yohei Yukawa6c075722018-09-21 14:52:12 -0700292 }
Yohei Yukawaa71bb252018-09-19 19:21:24 -0700293
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700294 private static final Object sLock = new Object();
295
Yohei Yukawa6c075722018-09-21 14:52:12 -0700296 /**
297 * @deprecated This cannot be compatible with multi-display. Please do not use this.
298 */
299 @Deprecated
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700300 @GuardedBy("sLock")
Mathew Inwooda570dee2018-08-17 14:56:00 +0100301 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -0700302 static InputMethodManager sInstance;
Dianne Hackborn7663d802012-02-24 13:08:49 -0800303
304 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800305 * Global map between display to {@link InputMethodManager}.
306 *
307 * <p>Currently this map works like a so-called leaky singleton. Once an instance is registered
308 * for the associated display ID, that instance will never be garbage collected.</p>
309 *
310 * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
311 */
312 @GuardedBy("sLock")
313 private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
314
315 /**
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700316 * Timeout in milliseconds for delivering a key to an IME.
317 */
318 static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
319
Jeff Brownf9e989d2013-04-04 23:04:03 -0700320 /** @hide */
321 public static final int DISPATCH_IN_PROGRESS = -1;
322
323 /** @hide */
324 public static final int DISPATCH_NOT_HANDLED = 0;
325
326 /** @hide */
327 public static final int DISPATCH_HANDLED = 1;
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700328
Seigo Nonaka14e13912015-05-06 21:04:13 -0700329 /** @hide */
330 public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
331 /** @hide */
332 public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
333 /** @hide */
334 public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
335
Mathew Inwooda570dee2018-08-17 14:56:00 +0100336 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 final IInputMethodManager mService;
338 final Looper mMainLooper;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 // For scheduling work on the main thread. This also serves as our
341 // global lock.
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000342 // Remark on @UnsupportedAppUsage: there were context leaks on old versions
343 // of android (b/37043700), so developers used this field to perform manual clean up.
344 // Leaks were fixed, hacks were backported to AppCompatActivity,
345 // so an access to the field is closed.
346 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 final H mH;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 // Our generic input connection if the current target does not have its own.
350 final IInputContext mIInputContext;
351
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800352 private final int mDisplayId;
353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 /**
355 * True if this input method client is active, initially false.
356 */
357 boolean mActive = false;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 /**
Yohei Yukawa2553e482017-12-15 15:47:33 -0800360 * {@code true} if next {@link #onPostWindowFocus(View, View, int, boolean, int)} needs to
361 * restart input.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 */
Yohei Yukawa2553e482017-12-15 15:47:33 -0800363 boolean mRestartOnNextWindowFocus = true;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 /**
366 * As reported by IME through InputConnection.
367 */
368 boolean mFullscreenMode;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700371
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700372 /**
373 * This is the root view of the overall window that currently has input
374 * method focus.
375 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100376 @UnsupportedAppUsage
Wale Ogunwale159c3d82015-05-14 12:20:53 -0700377 View mCurRootView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 /**
379 * This is the view that should currently be served by an input method,
380 * regardless of the state of setting that up.
381 */
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000382 // See comment to mH field in regard to @UnsupportedAppUsage
383 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 View mServedView;
385 /**
386 * This is then next view that will be served by the input method, when
387 * we get around to updating things.
388 */
Sergey Vasilinets6f1b7a22019-02-06 15:47:43 +0000389 // See comment to mH field in regard to @UnsupportedAppUsage
390 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 View mNextServedView;
392 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 * This is set when we are in the process of connecting, to determine
394 * when we have actually finished.
395 */
396 boolean mServedConnecting;
397 /**
398 * This is non-null when we have connected the served view; it holds
399 * the attributes that were last retrieved from the served view and given
400 * to the input connection.
401 */
402 EditorInfo mCurrentTextBoxAttribute;
403 /**
404 * The InputConnection that was last retrieved from the served view.
405 */
Mathew Inwood8c854f82018-09-14 12:35:36 +0100406 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackbornac920872012-05-22 11:49:49 -0700407 ControlledInputConnectionWrapper mServedInputConnectionWrapper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 /**
409 * The completions that were last provided by the served view.
410 */
411 CompletionInfo[] mCompletions;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 // Cursor position on the screen.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100414 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -0700415 Rect mTmpCursorRect = new Rect();
Mathew Inwooda570dee2018-08-17 14:56:00 +0100416 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 Rect mCursorRect = new Rect();
418 int mCursorSelStart;
419 int mCursorSelEnd;
420 int mCursorCandStart;
421 int mCursorCandEnd;
Yohei Yukawa056ffe62014-05-13 14:26:09 +0900422
423 /**
424 * The instance that has previously been sent to the input method.
425 */
426 private CursorAnchorInfo mCursorAnchorInfo = null;
427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 // -----------------------------------------------------------
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 /**
431 * Sequence number of this binding, as returned by the server.
432 */
433 int mBindSequence = -1;
434 /**
435 * ID of the method we are bound to.
436 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100437 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 String mCurId;
439 /**
440 * The actual instance of the method to make calls on it.
441 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100442 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 IInputMethodSession mCurMethod;
Jeff Brownc28867a2013-03-26 15:42:39 -0700444 InputChannel mCurChannel;
445 ImeInputEventSender mCurSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446
Yohei Yukawaa277db22014-08-21 18:38:44 -0700447 private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900448
449 /**
450 * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
451 */
Yohei Yukawaa277db22014-08-21 18:38:44 -0700452 private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawab7b79072014-03-25 11:02:00 +0900453
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800454 /**
455 * When {@link ViewRootImpl#sNewInsetsMode} is set to
456 * >= {@link ViewRootImpl#NEW_INSETS_MODE_IME}, {@link ImeInsetsSourceConsumer} applies the
457 * IME visibility and listens for other state changes.
458 */
459 private ImeInsetsSourceConsumer mImeInsetsConsumer;
460
Yohei Yukawab0377bb2015-08-10 21:06:30 -0700461 final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
462 final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 // -----------------------------------------------------------
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 static final int MSG_DUMP = 1;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800467 static final int MSG_BIND = 2;
468 static final int MSG_UNBIND = 3;
469 static final int MSG_SET_ACTIVE = 4;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700470 static final int MSG_SEND_INPUT_EVENT = 5;
471 static final int MSG_TIMEOUT_INPUT_EVENT = 6;
472 static final int MSG_FLUSH_INPUT_EVENT = 7;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800473 static final int MSG_REPORT_FULLSCREEN_MODE = 10;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800474 static final int MSG_REPORT_PRE_RENDERED = 15;
475 static final int MSG_APPLY_IME_VISIBILITY = 20;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700476
Dake Guddf6c1e2018-05-10 11:41:19 -0700477 private static boolean isAutofillUIShowing(View servedView) {
478 AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
479 return afm != null && afm.isAutofillUiShowing();
480 }
481
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800482 /**
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700483 * Returns fallback {@link InputMethodManager} if the called one is not likely to be compatible
484 * with the given {@code view}.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800485 *
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700486 * @param view {@link View} to be checked.
487 * @return {@code null} when it is unnecessary (or impossible) to use fallback
488 * {@link InputMethodManager} to which IME API calls need to be re-dispatched.
489 * Non-{@code null} {@link InputMethodManager} if this method believes it'd be safer to
490 * re-dispatch IME APIs calls on it.
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800491 */
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700492 @Nullable
493 private InputMethodManager getFallbackInputMethodManagerIfNecessary(@Nullable View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800494 if (view == null) {
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700495 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800496 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700497 // As evidenced in Bug 118341760, view.getViewRootImpl().getDisplayId() is supposed to be
498 // more reliable to determine with which display the given view is interacting than
499 // view.getContext().getDisplayId() / view.getContext().getSystemService(), which can be
500 // easily messed up by app developers (or library authors) by creating inconsistent
501 // ContextWrapper objects that re-dispatch those methods to other Context such as
502 // ApplicationContext.
503 final ViewRootImpl viewRootImpl = view.getViewRootImpl();
504 if (viewRootImpl == null) {
505 return null;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800506 }
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700507 final int viewRootDisplayId = viewRootImpl.getDisplayId();
508 if (viewRootDisplayId == mDisplayId) {
509 // Expected case. Good to go.
510 return null;
511 }
512 final InputMethodManager fallbackImm =
Charles Chenfd850362019-04-17 13:35:21 +0000513 viewRootImpl.mDisplayContext.getSystemService(InputMethodManager.class);
Yohei Yukawa052ab8c2018-10-26 08:43:30 -0700514 if (fallbackImm == null) {
515 Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
516 return null;
517 }
518 if (fallbackImm.mDisplayId != viewRootDisplayId) {
519 Log.e(TAG, "b/117267690: Failed to get fallback IMM with expected displayId="
520 + viewRootDisplayId + " actual IMM#displayId=" + fallbackImm.mDisplayId
521 + " view=" + view);
522 return null;
523 }
524 Log.w(TAG, "b/117267690: Display ID mismatch found."
525 + " ViewRootImpl displayId=" + viewRootDisplayId
526 + " InputMethodManager displayId=" + mDisplayId
527 + ". Use the right InputMethodManager instance to avoid performance overhead.",
528 new Throwable());
529 return fallbackImm;
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800530 }
531
Dake Guddf6c1e2018-05-10 11:41:19 -0700532 private static boolean canStartInput(View servedView) {
533 // We can start input ether the servedView has window focus
534 // or the activity is showing autofill ui.
535 return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
536 }
537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 class H extends Handler {
539 H(Looper looper) {
Jeff Brown29c0ed22013-01-14 13:50:37 -0800540 super(looper, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 @Override
544 public void handleMessage(Message msg) {
545 switch (msg.what) {
546 case MSG_DUMP: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700547 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 try {
549 doDump((FileDescriptor)args.arg1,
550 (PrintWriter)args.arg2, (String[])args.arg3);
551 } catch (RuntimeException e) {
552 ((PrintWriter)args.arg2).println("Exception: " + e);
553 }
554 synchronized (args.arg4) {
555 ((CountDownLatch)args.arg4).countDown();
556 }
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700557 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 return;
559 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800560 case MSG_BIND: {
561 final InputBindResult res = (InputBindResult)msg.obj;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900562 if (DEBUG) {
563 Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
564 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800565 synchronized (mH) {
566 if (mBindSequence < 0 || mBindSequence != res.sequence) {
567 Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
568 + ", given seq=" + res.sequence);
Jeff Brown4d656882013-04-03 14:39:19 -0700569 if (res.channel != null && res.channel != mCurChannel) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700570 res.channel.dispose();
571 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800572 return;
573 }
Jeff Brown4d656882013-04-03 14:39:19 -0700574
Yohei Yukawaa277db22014-08-21 18:38:44 -0700575 mRequestUpdateCursorAnchorInfoMonitorMode =
576 REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +0900577
Jeff Brown4d656882013-04-03 14:39:19 -0700578 setInputChannelLocked(res.channel);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800579 mCurMethod = res.method;
580 mCurId = res.id;
581 mBindSequence = res.sequence;
582 }
Yohei Yukawa42194222018-10-21 20:14:40 -0700583 startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800584 return;
585 }
586 case MSG_UNBIND: {
587 final int sequence = msg.arg1;
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700588 @UnbindReason
Yohei Yukawa33e81792015-11-17 21:14:42 -0800589 final int reason = msg.arg2;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900590 if (DEBUG) {
Yohei Yukawa33e81792015-11-17 21:14:42 -0800591 Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
Yohei Yukawaa468d702018-10-21 11:42:34 -0700592 " reason=" + InputMethodDebug.unbindReasonToString(reason));
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900593 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800594 final boolean startInput;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800595 synchronized (mH) {
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800596 if (mBindSequence != sequence) {
597 return;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800598 }
Yohei Yukawa678e38e2015-11-13 18:36:21 -0800599 clearBindingLocked();
600 // If we were actively using the last input method, then
601 // we would like to re-connect to the next input method.
602 if (mServedView != null && mServedView.isFocused()) {
603 mServedConnecting = true;
604 }
605 startInput = mActive;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800606 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800607 if (startInput) {
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800608 startInputInner(
Yohei Yukawa42194222018-10-21 20:14:40 -0700609 StartInputReason.UNBOUND_FROM_IMMS, null, 0, 0, 0);
Dianne Hackborn06a591c2012-02-16 10:25:26 -0800610 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800611 return;
612 }
613 case MSG_SET_ACTIVE: {
614 final boolean active = msg.arg1 != 0;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800615 final boolean fullscreen = msg.arg2 != 0;
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +0900616 if (DEBUG) {
617 Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
618 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800619 synchronized (mH) {
620 mActive = active;
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800621 mFullscreenMode = fullscreen;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800622 if (!active) {
623 // Some other client has starting using the IME, so note
624 // that this happened and make sure our own editor's
625 // state is reset.
Yohei Yukawa2553e482017-12-15 15:47:33 -0800626 mRestartOnNextWindowFocus = true;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800627 try {
628 // Note that finishComposingText() is allowed to run
629 // even when we are not active.
630 mIInputContext.finishComposingText();
631 } catch (RemoteException e) {
632 }
Mikael Gullstrand82ae3ff2014-11-25 12:41:53 +0100633 }
634 // Check focus again in case that "onWindowFocus" is called before
635 // handling this message.
Dake Guddf6c1e2018-05-10 11:41:19 -0700636 if (mServedView != null && canStartInput(mServedView)) {
Yohei Yukawa2553e482017-12-15 15:47:33 -0800637 if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
Yohei Yukawa42194222018-10-21 20:14:40 -0700638 final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
639 : StartInputReason.DEACTIVATED_BY_IMMS;
Yohei Yukawa35d3f372015-11-25 11:07:19 -0800640 startInputInner(reason, null, 0, 0, 0);
satok05a6cbe2012-04-05 23:04:08 +0900641 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800642 }
643 }
644 return;
645 }
Jeff Brownf9e989d2013-04-04 23:04:03 -0700646 case MSG_SEND_INPUT_EVENT: {
647 sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
648 return;
649 }
650 case MSG_TIMEOUT_INPUT_EVENT: {
651 finishedInputEvent(msg.arg1, false, true);
652 return;
653 }
654 case MSG_FLUSH_INPUT_EVENT: {
655 finishedInputEvent(msg.arg1, false, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700656 return;
657 }
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800658 case MSG_REPORT_FULLSCREEN_MODE: {
659 final boolean fullscreen = msg.arg1 != 0;
660 InputConnection ic = null;
661 synchronized (mH) {
662 mFullscreenMode = fullscreen;
663 if (mServedInputConnectionWrapper != null) {
664 ic = mServedInputConnectionWrapper.getInputConnection();
665 }
666 }
667 if (ic != null) {
668 ic.reportFullscreenMode(fullscreen);
669 }
670 return;
Yohei Yukawa3d1e8122014-06-06 19:12:47 +0900671 }
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800672 case MSG_REPORT_PRE_RENDERED: {
673 synchronized (mH) {
674 if (mImeInsetsConsumer != null) {
675 mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
676 }
677 }
678 return;
679
680 }
681 case MSG_APPLY_IME_VISIBILITY: {
682 synchronized (mH) {
683 if (mImeInsetsConsumer != null) {
684 mImeInsetsConsumer.applyImeVisibility(msg.arg1 != 0);
685 }
686 }
687 return;
688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 }
690 }
691 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800692
Jean Chalardde9dbb02011-10-20 19:50:45 +0900693 private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
694 private final InputMethodManager mParentInputMethodManager;
695
696 public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
697 final InputMethodManager inputMethodManager) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 super(mainLooper, conn);
Jean Chalardde9dbb02011-10-20 19:50:45 +0900699 mParentInputMethodManager = inputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 }
701
Gilles Debunne8cbb4c62011-01-24 12:33:56 -0800702 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 public boolean isActive() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700704 return mParentInputMethodManager.mActive && !isFinished();
Dianne Hackbornac920872012-05-22 11:49:49 -0700705 }
706
707 void deactivate() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700708 if (isFinished()) {
709 // This is a small performance optimization. Still only the 1st call of
710 // reportFinish() will take effect.
711 return;
712 }
Yohei Yukawa9f9afe522016-03-30 12:03:51 -0700713 closeConnection();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800715
716 @Override
717 public String toString() {
Yohei Yukawaaaa38c92016-03-27 23:46:04 -0700718 return "ControlledInputConnectionWrapper{"
719 + "connection=" + getInputConnection()
720 + " finished=" + isFinished()
Yohei Yukawa12d66c22015-11-18 13:44:14 -0800721 + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
722 + "}";
723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 }
Yohei Yukawa159dd472016-01-07 16:52:33 -0800725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
Jeff Brownc28867a2013-03-26 15:42:39 -0700727 @Override
728 protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 // No need to check for dump permission, since we only give this
730 // interface to the system.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 CountDownLatch latch = new CountDownLatch(1);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700732 SomeArgs sargs = SomeArgs.obtain();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 sargs.arg1 = fd;
734 sargs.arg2 = fout;
735 sargs.arg3 = args;
736 sargs.arg4 = latch;
737 mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
738 try {
739 if (!latch.await(5, TimeUnit.SECONDS)) {
740 fout.println("Timeout waiting for dump");
741 }
742 } catch (InterruptedException e) {
743 fout.println("Interrupted waiting for dump");
744 }
745 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700746
747 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 public void onBindMethod(InputBindResult res) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800749 mH.obtainMessage(MSG_BIND, res).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700751
752 @Override
Yohei Yukawa499e3f72018-10-21 20:15:11 -0700753 public void onUnbindMethod(int sequence, @UnbindReason int unbindReason) {
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800754 mH.obtainMessage(MSG_UNBIND, sequence, unbindReason).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700756
757 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800758 public void setActive(boolean active, boolean fullscreen) {
759 mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0).sendToTarget();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 }
Yohei Yukawab7b79072014-03-25 11:02:00 +0900761
762 @Override
Yohei Yukawa2bc66172017-02-08 11:13:25 -0800763 public void reportFullscreenMode(boolean fullscreen) {
764 mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
765 .sendToTarget();
766 }
767
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -0800768 @Override
769 public void reportPreRendered(EditorInfo info) {
770 mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
771 .sendToTarget();
772 }
773
774 @Override
775 public void applyImeVisibility(boolean setVisible) {
776 mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
777 .sendToTarget();
778 }
779
Jeff Brownc28867a2013-03-26 15:42:39 -0700780 };
781
Dianne Hackborn51bf0772009-03-24 19:11:41 -0700782 final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
Jeff Brown04ddf3c2012-06-14 03:57:49 -0700783
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700784 /**
785 * For layoutlib to clean up static objects inside {@link InputMethodManager}.
786 */
787 static void tearDownEditMode() {
788 if (!isInEditMode()) {
789 throw new UnsupportedOperationException(
790 "This method must be called only from layoutlib");
791 }
792 synchronized (sLock) {
793 sInstance = null;
794 }
Jeff Sharkeya4603d3c2016-08-11 16:54:13 -0600795 }
796
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700797 /**
798 * For layoutlib to override this method to return {@code true}.
799 *
800 * @return {@code true} if the process is running for developer tools
801 * @see View#isInEditMode()
802 */
803 private static boolean isInEditMode() {
804 return false;
805 }
806
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700807 @NonNull
808 private static InputMethodManager createInstance(int displayId, Looper looper) {
809 return isInEditMode() ? createStubInstance(displayId, looper)
810 : createRealInstance(displayId, looper);
Yohei Yukawadaf0d1b2018-09-20 15:53:07 -0700811 }
812
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700813 @NonNull
814 private static InputMethodManager createRealInstance(int displayId, Looper looper) {
815 final IInputMethodManager service;
816 try {
817 service = IInputMethodManager.Stub.asInterface(
818 ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
819 } catch (ServiceNotFoundException e) {
820 throw new IllegalStateException(e);
821 }
822 final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
Yohei Yukawacb768bc2018-10-24 16:05:09 -0700823 // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
824 // associate PID/UID with each IME client. This means:
825 // A. if this method call will be handled as an IPC, there is no problem.
826 // B. if this method call will be handled as an in-proc method call, we need to
827 // ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
828 // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
829 // 1) doing so has no effect for A and 2) doing so is sufficient for B.
830 final long identity = Binder.clearCallingIdentity();
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700831 try {
832 service.addClient(imm.mClient, imm.mIInputContext, displayId);
833 } catch (RemoteException e) {
834 e.rethrowFromSystemServer();
Yohei Yukawacb768bc2018-10-24 16:05:09 -0700835 } finally {
836 Binder.restoreCallingIdentity(identity);
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700837 }
838 return imm;
839 }
840
841 @NonNull
842 private static InputMethodManager createStubInstance(int displayId, Looper looper) {
843 // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
844 final Class<IInputMethodManager> c = IInputMethodManager.class;
845 final IInputMethodManager stubInterface =
846 (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
847 new Class[]{c}, (proxy, method, args) -> {
848 final Class<?> returnType = method.getReturnType();
849 if (returnType == boolean.class) {
850 return false;
851 } else if (returnType == int.class) {
852 return 0;
853 } else if (returnType == long.class) {
854 return 0L;
855 } else if (returnType == short.class) {
856 return 0;
857 } else if (returnType == char.class) {
858 return 0;
859 } else if (returnType == byte.class) {
860 return 0;
861 } else if (returnType == float.class) {
862 return 0f;
863 } else if (returnType == double.class) {
864 return 0.0;
865 } else {
866 return null;
867 }
868 });
869 return new InputMethodManager(stubInterface, displayId, looper);
870 }
871
872 private InputMethodManager(IInputMethodManager service, int displayId, Looper looper) {
873 mService = service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 mMainLooper = looper;
875 mH = new H(looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800876 mDisplayId = displayId;
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700877 mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 }
879
880 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800881 * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
Yohei Yukawa6c075722018-09-21 14:52:12 -0700882 *
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800883 * @param context {@link Context} for which IME APIs need to work
884 * @return {@link InputMethodManager} instance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 * @hide
886 */
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700887 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800888 public static InputMethodManager forContext(Context context) {
889 final int displayId = context.getDisplayId();
890 // For better backward compatibility, we always use Looper.getMainLooper() for the default
891 // display case.
892 final Looper looper = displayId == Display.DEFAULT_DISPLAY
893 ? Looper.getMainLooper() : context.getMainLooper();
894 return forContextInternal(displayId, looper);
895 }
896
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700897 @NonNull
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800898 private static InputMethodManager forContextInternal(int displayId, Looper looper) {
899 final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700900 synchronized (sLock) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800901 InputMethodManager instance = sInstanceMap.get(displayId);
902 if (instance != null) {
903 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 }
Yohei Yukawaf682b1a5c42018-10-24 16:05:02 -0700905 instance = createInstance(displayId, looper);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800906 // For backward compatibility, store the instance also to sInstance for default display.
907 if (sInstance == null && isDefaultDisplay) {
908 sInstance = instance;
909 }
910 sInstanceMap.put(displayId, instance);
911 return instance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 /**
Yohei Yukawa6c075722018-09-21 14:52:12 -0700916 * Deprecated. Do not use.
917 *
918 * @return global {@link InputMethodManager} instance
Yohei Yukawa484d4af2018-09-17 16:47:08 -0700919 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
920 * support multi-display scenario.
Yohei Yukawa6c075722018-09-21 14:52:12 -0700921 * @hide
922 */
923 @Deprecated
924 @UnsupportedAppUsage
925 public static InputMethodManager getInstance() {
926 Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be"
927 + " compatible with multi-display."
928 + " Use context.getSystemService(InputMethodManager.class) instead.",
929 new Throwable());
930 ensureDefaultInstanceForDefaultDisplayIfNecessary();
931 return peekInstance();
932 }
933
934 /**
935 * Deprecated. Do not use.
936 *
937 * @return {@link #sInstance}
938 * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
939 * support multi-display scenario.
940 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 */
Yohei Yukawa484d4af2018-09-17 16:47:08 -0700942 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +0100943 @UnsupportedAppUsage
Jeff Brownf9e989d2013-04-04 23:04:03 -0700944 public static InputMethodManager peekInstance() {
Yohei Yukawa6c075722018-09-21 14:52:12 -0700945 Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be"
946 + " compatible with multi-display."
947 + " Use context.getSystemService(InputMethodManager.class) instead.",
948 new Throwable());
Yohei Yukawa3b3a2ad2018-09-20 15:50:35 -0700949 synchronized (sLock) {
950 return sInstance;
951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100955 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 public IInputMethodClient getClient() {
957 return mClient;
958 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100961 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 public IInputContext getInputContext() {
963 return mIInputContext;
964 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -0700965
Yohei Yukawa629271a2019-02-05 07:50:36 -0800966 /**
967 * Returns the list of installed input methods.
968 *
969 * <p>On multi user environment, this API returns a result for the calling process user.</p>
970 *
971 * @return {@link List} of {@link InputMethodInfo}.
972 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 public List<InputMethodInfo> getInputMethodList() {
974 try {
Yohei Yukawad20eef82019-02-05 10:45:32 -0800975 // We intentionally do not use UserHandle.getCallingUserId() here because for system
976 // services InputMethodManagerInternal.getInputMethodListAsUser() should be used
977 // instead.
978 return mService.getInputMethodList(UserHandle.myUserId());
979 } catch (RemoteException e) {
980 throw e.rethrowFromSystemServer();
981 }
982 }
983
984 /**
985 * Returns the list of installed input methods for the specified user.
986 *
987 * @param userId user ID to query
988 * @return {@link List} of {@link InputMethodInfo}.
989 * @hide
990 */
991 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
992 public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
993 try {
994 return mService.getInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700996 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 }
998 }
999
Yohei Yukawa629271a2019-02-05 07:50:36 -08001000 /**
1001 * Returns the list of enabled input methods.
1002 *
1003 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1004 *
1005 * @return {@link List} of {@link InputMethodInfo}.
1006 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 public List<InputMethodInfo> getEnabledInputMethodList() {
1008 try {
Yohei Yukawa1fb13c52019-02-05 07:55:28 -08001009 // We intentionally do not use UserHandle.getCallingUserId() here because for system
1010 // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used
1011 // instead.
1012 return mService.getEnabledInputMethodList(UserHandle.myUserId());
1013 } catch (RemoteException e) {
1014 throw e.rethrowFromSystemServer();
1015 }
1016 }
1017
1018 /**
1019 * Returns the list of enabled input methods for the specified user.
1020 *
1021 * @param userId user ID to query
1022 * @return {@link List} of {@link InputMethodInfo}.
1023 * @hide
1024 */
1025 @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
1026 public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
1027 try {
1028 return mService.getEnabledInputMethodList(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001030 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
1032 }
1033
satokd4fce2b2011-04-11 12:07:13 +09001034 /**
1035 * Returns a list of enabled input method subtypes for the specified input method info.
Yohei Yukawa629271a2019-02-05 07:50:36 -08001036 *
1037 * <p>On multi user environment, this API returns a result for the calling process user.</p>
1038 *
satokd4fce2b2011-04-11 12:07:13 +09001039 * @param imi An input method info whose subtypes list will be returned.
1040 * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly
1041 * selected subtypes. If an input method info doesn't have enabled subtypes, the framework
1042 * will implicitly enable subtypes according to the current system language.
1043 */
satok16331c82010-12-20 23:48:46 +09001044 public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
1045 boolean allowsImplicitlySelectedSubtypes) {
satok67ddf9c2010-11-17 09:45:54 +09001046 try {
Satoshi Kataokab3c21ac2013-08-07 15:43:29 +09001047 return mService.getEnabledInputMethodSubtypeList(
1048 imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
satok67ddf9c2010-11-17 09:45:54 +09001049 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001050 throw e.rethrowFromSystemServer();
satok67ddf9c2010-11-17 09:45:54 +09001051 }
1052 }
1053
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001054 /**
1055 * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
1056 * intended for IME developers who should be accessing APIs through the service. APIs in this
1057 * class are intended for app developers interacting with the IME.
1058 */
1059 @Deprecated
Yohei Yukawa41b094f2018-09-09 23:58:45 -07001060 public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001061 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 }
1063
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08001064 /**
1065 * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
1066 * intended for IME developers who should be accessing APIs through the service. APIs in
1067 * this class are intended for app developers interacting with the IME.
1068 */
1069 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 public void hideStatusIcon(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07001071 InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 }
1073
Yohei Yukawa17ace292019-01-21 09:24:26 -08001074 /**
1075 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1076 *
1077 * @param spans will be ignored.
1078 *
1079 * @deprecated Do not use.
1080 * @hide
1081 */
1082 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001083 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001084 public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001085 Log.w(TAG, "registerSuggestionSpansForNotification() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001086 }
1087
Yohei Yukawa17ace292019-01-21 09:24:26 -08001088 /**
1089 * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1090 *
1091 * @deprecated Do not use.
1092 * @hide
1093 */
1094 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +01001095 @UnsupportedAppUsage
satokf9f01002011-05-19 21:31:50 +09001096 public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
Yohei Yukawa17ace292019-01-21 09:24:26 -08001097 Log.w(TAG, "notifySuggestionPicked() is deprecated. Does nothing.");
satokf9f01002011-05-19 21:31:50 +09001098 }
1099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 /**
1101 * Allows you to discover whether the attached input method is running
1102 * in fullscreen mode. Return true if it is fullscreen, entirely covering
1103 * your UI, else returns false.
1104 */
1105 public boolean isFullscreenMode() {
Yohei Yukawa1544def2016-04-26 17:13:38 -07001106 synchronized (mH) {
1107 return mFullscreenMode;
1108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 }
Yohei Yukawa1544def2016-04-26 17:13:38 -07001110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 /**
1112 * Return true if the given view is the currently active view for the
1113 * input method.
1114 */
1115 public boolean isActive(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001116 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001117 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1118 if (fallbackImm != null) {
1119 return fallbackImm.isActive(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001120 }
1121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 checkFocus();
1123 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001124 return (mServedView == view
1125 || (mServedView != null
1126 && mServedView.checkInputConnectionProxy(view)))
1127 && mCurrentTextBoxAttribute != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 }
1129 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 /**
1132 * Return true if any view is currently active in the input method.
1133 */
1134 public boolean isActive() {
1135 checkFocus();
1136 synchronized (mH) {
1137 return mServedView != null && mCurrentTextBoxAttribute != null;
1138 }
1139 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 /**
1142 * Return true if the currently served view is accepting full text edits.
1143 * If false, it has no input connection, so can only handle raw key events.
1144 */
1145 public boolean isAcceptingText() {
1146 checkFocus();
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001147 return mServedInputConnectionWrapper != null &&
1148 mServedInputConnectionWrapper.getInputConnection() != null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 }
1150
1151 /**
1152 * Reset all of the state associated with being bound to an input method.
1153 */
1154 void clearBindingLocked() {
Dianne Hackborn6b6b3fd2014-03-24 11:27:18 -07001155 if (DEBUG) Log.v(TAG, "Clearing binding!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 clearConnectionLocked();
Jeff Brown4d656882013-04-03 14:39:19 -07001157 setInputChannelLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 mBindSequence = -1;
1159 mCurId = null;
1160 mCurMethod = null;
Jeff Brown4d656882013-04-03 14:39:19 -07001161 }
1162
1163 void setInputChannelLocked(InputChannel channel) {
1164 if (mCurChannel != channel) {
1165 if (mCurSender != null) {
1166 flushPendingEventsLocked();
1167 mCurSender.dispose();
1168 mCurSender = null;
1169 }
1170 if (mCurChannel != null) {
1171 mCurChannel.dispose();
1172 }
1173 mCurChannel = channel;
Jeff Brownc28867a2013-03-26 15:42:39 -07001174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 }
Jeff Brown4d656882013-04-03 14:39:19 -07001176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 /**
1178 * Reset all of the state associated with a served view being connected
1179 * to an input method
1180 */
1181 void clearConnectionLocked() {
1182 mCurrentTextBoxAttribute = null;
Dianne Hackbornac920872012-05-22 11:49:49 -07001183 if (mServedInputConnectionWrapper != null) {
1184 mServedInputConnectionWrapper.deactivate();
1185 mServedInputConnectionWrapper = null;
1186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 }
Yohei Yukawa0f3a99d2015-05-21 00:15:05 -07001188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 /**
1190 * Disconnect any existing input connection, clearing the served view.
1191 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001192 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 void finishInputLocked() {
1194 mNextServedView = null;
1195 if (mServedView != null) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001196 if (DEBUG) Log.v(TAG, "FINISH INPUT: mServedView=" + dumpViewInfo(mServedView));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 mServedView = null;
1198 mCompletions = null;
1199 mServedConnecting = false;
1200 clearConnectionLocked();
1201 }
1202 }
Gilles Debunnec478c172011-12-19 17:29:24 -08001203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 public void displayCompletions(View view, CompletionInfo[] completions) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001205 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001206 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1207 if (fallbackImm != null) {
1208 fallbackImm.displayCompletions(view, completions);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001209 return;
1210 }
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 checkFocus();
1213 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001214 if (mServedView != view && (mServedView == null
1215 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 return;
1217 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 mCompletions = completions;
1220 if (mCurMethod != null) {
1221 try {
1222 mCurMethod.displayCompletions(mCompletions);
1223 } catch (RemoteException e) {
1224 }
1225 }
1226 }
1227 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 public void updateExtractedText(View view, int token, ExtractedText text) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001230 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001231 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1232 if (fallbackImm != null) {
1233 fallbackImm.updateExtractedText(view, token, text);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001234 return;
1235 }
1236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 checkFocus();
1238 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001239 if (mServedView != view && (mServedView == null
1240 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 return;
1242 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 if (mCurMethod != null) {
1245 try {
1246 mCurMethod.updateExtractedText(token, text);
1247 } catch (RemoteException e) {
1248 }
1249 }
1250 }
1251 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 /**
1254 * Flag for {@link #showSoftInput} to indicate that this is an implicit
1255 * request to show the input window, not as the result of a direct request
1256 * by the user. The window may not be shown in this case.
1257 */
1258 public static final int SHOW_IMPLICIT = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 /**
1261 * Flag for {@link #showSoftInput} to indicate that the user has forced
1262 * the input method open (such as by long-pressing menu) so it should
1263 * not be closed until they explicitly do so.
1264 */
1265 public static final int SHOW_FORCED = 0x0002;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001268 * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
1269 * a result receiver: explicitly request that the current input method's
1270 * soft input area be shown to the user, if needed.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001271 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001272 * @param view The currently focused view, which would like to receive
1273 * soft keyboard input.
1274 * @param flags Provides additional operating flags. Currently may be
1275 * 0 or have the {@link #SHOW_IMPLICIT} bit set.
1276 */
1277 public boolean showSoftInput(View view, int flags) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001278 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001279 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1280 if (fallbackImm != null) {
1281 return fallbackImm.showSoftInput(view, flags);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001282 }
1283
The Android Open Source Project4df24232009-03-05 14:34:35 -08001284 return showSoftInput(view, flags, null);
1285 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001286
The Android Open Source Project4df24232009-03-05 14:34:35 -08001287 /**
1288 * Flag for the {@link ResultReceiver} result code from
1289 * {@link #showSoftInput(View, int, ResultReceiver)} and
1290 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1291 * state of the soft input window was unchanged and remains shown.
1292 */
1293 public static final int RESULT_UNCHANGED_SHOWN = 0;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001294
The Android Open Source Project4df24232009-03-05 14:34:35 -08001295 /**
1296 * Flag for the {@link ResultReceiver} result code from
1297 * {@link #showSoftInput(View, int, ResultReceiver)} and
1298 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1299 * state of the soft input window was unchanged and remains hidden.
1300 */
1301 public static final int RESULT_UNCHANGED_HIDDEN = 1;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001302
The Android Open Source Project4df24232009-03-05 14:34:35 -08001303 /**
1304 * Flag for the {@link ResultReceiver} result code from
1305 * {@link #showSoftInput(View, int, ResultReceiver)} and
1306 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1307 * state of the soft input window changed from hidden to shown.
1308 */
1309 public static final int RESULT_SHOWN = 2;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001310
The Android Open Source Project4df24232009-03-05 14:34:35 -08001311 /**
1312 * Flag for the {@link ResultReceiver} result code from
1313 * {@link #showSoftInput(View, int, ResultReceiver)} and
1314 * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1315 * state of the soft input window changed from shown to hidden.
1316 */
1317 public static final int RESULT_HIDDEN = 3;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001318
The Android Open Source Project4df24232009-03-05 14:34:35 -08001319 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 * Explicitly request that the current input method's soft input area be
1321 * shown to the user, if needed. Call this if the user interacts with
1322 * your view in such a way that they have expressed they would like to
1323 * start performing input into it.
Yohei Yukawad552a522016-03-20 15:08:31 -07001324 *
1325 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1326 * this method can be a long-lived object, because it may not be
1327 * garbage-collected until all the corresponding {@link ResultReceiver}
1328 * objects transferred to different processes get garbage-collected.
1329 * Follow the general patterns to avoid memory leaks in Android.
1330 * Consider to use {@link java.lang.ref.WeakReference} so that application
1331 * logic objects such as {@link android.app.Activity} and {@link Context}
1332 * can be garbage collected regardless of the lifetime of
1333 * {@link ResultReceiver}.
1334 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -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.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001339 * @param resultReceiver If non-null, this will be called by the IME when
1340 * it has processed your request to tell you what it has done. The result
1341 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1342 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1343 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 */
Gilles Debunnead8484b2011-02-17 17:37:51 -08001345 public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001346 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001347 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1348 if (fallbackImm != null) {
1349 return fallbackImm.showSoftInput(view, flags, resultReceiver);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001350 }
1351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 checkFocus();
1353 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001354 if (mServedView != view && (mServedView == null
1355 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001356 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 }
1358
1359 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001360 return mService.showSoftInput(mClient, flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001362 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364 }
1365 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001366
Yohei Yukawa101ae462017-03-31 14:28:18 -07001367 /**
1368 * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
1369 * is publicly released because previous implementations of that class had relied on this method
1370 * via reflection.
1371 *
1372 * @deprecated This is a hidden API. You should never use this.
1373 * @hide
1374 */
1375 @Deprecated
Yohei Yukawa1466e4a2019-02-12 01:42:56 -08001376 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
The Android Open Source Project4df24232009-03-05 14:34:35 -08001377 public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 try {
Yohei Yukawa101ae462017-03-31 14:28:18 -07001379 Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
1380 + "soon. If you are using android.support.v7.widget.SearchView, please update "
1381 + "to version 26.0 or newer version.");
The Android Open Source Project4df24232009-03-05 14:34:35 -08001382 mService.showSoftInput(mClient, flags, resultReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001384 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
1386 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001389 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
1390 * 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 -08001391 * by the user.
1392 */
1393 public static final int HIDE_IMPLICIT_ONLY = 0x0001;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 /**
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08001396 * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestShowSelf(int)}
1397 * 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 -08001398 * shown with {@link #SHOW_FORCED}.
1399 */
1400 public static final int HIDE_NOT_ALWAYS = 0x0002;
Gilles Debunnec478c172011-12-19 17:29:24 -08001401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 /**
Gilles Debunne7c8c6d62011-01-24 14:48:14 -08001403 * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
The Android Open Source Project4df24232009-03-05 14:34:35 -08001404 * without a result: request to hide the soft input window from the
1405 * context of the window that is currently accepting input.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001406 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08001407 * @param windowToken The token of the window that is making the request,
1408 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1409 * @param flags Provides additional operating flags. Currently may be
1410 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
1411 */
1412 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
1413 return hideSoftInputFromWindow(windowToken, flags, null);
1414 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001415
The Android Open Source Project4df24232009-03-05 14:34:35 -08001416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 * Request to hide the soft input window from the context of the window
1418 * that is currently accepting input. This should be called as a result
1419 * of the user doing some actually than fairly explicitly requests to
1420 * have the input window hidden.
Yohei Yukawad552a522016-03-20 15:08:31 -07001421 *
1422 * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1423 * this method can be a long-lived object, because it may not be
1424 * garbage-collected until all the corresponding {@link ResultReceiver}
1425 * objects transferred to different processes get garbage-collected.
1426 * Follow the general patterns to avoid memory leaks in Android.
1427 * Consider to use {@link java.lang.ref.WeakReference} so that application
1428 * logic objects such as {@link android.app.Activity} and {@link Context}
1429 * can be garbage collected regardless of the lifetime of
1430 * {@link ResultReceiver}.
1431 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 * @param windowToken The token of the window that is making the request,
1433 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1434 * @param flags Provides additional operating flags. Currently may be
1435 * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001436 * @param resultReceiver If non-null, this will be called by the IME when
1437 * it has processed your request to tell you what it has done. The result
1438 * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1439 * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1440 * {@link #RESULT_HIDDEN}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 */
The Android Open Source Project4df24232009-03-05 14:34:35 -08001442 public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
1443 ResultReceiver resultReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 checkFocus();
1445 synchronized (mH) {
1446 if (mServedView == null || mServedView.getWindowToken() != windowToken) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001447 return false;
1448 }
1449
1450 try {
1451 return mService.hideSoftInput(mClient, flags, resultReceiver);
1452 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001453 throw e.rethrowFromSystemServer();
The Android Open Source Project4df24232009-03-05 14:34:35 -08001454 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001455 }
1456 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001457
The Android Open Source Project4df24232009-03-05 14:34:35 -08001458 /**
1459 * This method toggles the input method window display.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001460 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001461 * If not the input window will be displayed.
1462 * @param windowToken The token of the window that is making the request,
1463 * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1464 * @param showFlags Provides additional operating flags. May be
1465 * 0 or have the {@link #SHOW_IMPLICIT},
1466 * {@link #SHOW_FORCED} bit set.
1467 * @param hideFlags Provides additional operating flags. May be
1468 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1469 * {@link #HIDE_NOT_ALWAYS} bit set.
1470 **/
1471 public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
1472 synchronized (mH) {
1473 if (mServedView == null || mServedView.getWindowToken() != windowToken) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 return;
1475 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001476 if (mCurMethod != null) {
1477 try {
1478 mCurMethod.toggleSoftInput(showFlags, hideFlags);
1479 } catch (RemoteException e) {
1480 }
1481 }
1482 }
1483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001485 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -08001486 * This method toggles the input method window display.
Yohei Yukawa3db07bb2018-02-05 15:26:25 +09001487 *
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001488 * If the input window is already displayed, it gets hidden.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001489 * If not the input window will be displayed.
1490 * @param showFlags Provides additional operating flags. May be
1491 * 0 or have the {@link #SHOW_IMPLICIT},
1492 * {@link #SHOW_FORCED} bit set.
1493 * @param hideFlags Provides additional operating flags. May be
1494 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1495 * {@link #HIDE_NOT_ALWAYS} bit set.
The Android Open Source Project4df24232009-03-05 14:34:35 -08001496 */
1497 public void toggleSoftInput(int showFlags, int hideFlags) {
1498 if (mCurMethod != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001500 mCurMethod.toggleSoftInput(showFlags, hideFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 } catch (RemoteException e) {
1502 }
1503 }
1504 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 /**
1507 * If the input method is currently connected to the given view,
1508 * restart it with its new contents. You should call this when the text
1509 * within your view changes outside of the normal input method or key
1510 * input flow, such as when an application calls TextView.setText().
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001511 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 * @param view The view whose text has changed.
1513 */
1514 public void restartInput(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001515 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07001516 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1517 if (fallbackImm != null) {
1518 fallbackImm.restartInput(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08001519 return;
1520 }
1521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 checkFocus();
1523 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001524 if (mServedView != view && (mServedView == null
1525 || !mServedView.checkInputConnectionProxy(view))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 return;
1527 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 mServedConnecting = true;
1530 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001531
Yohei Yukawa42194222018-10-21 20:14:40 -07001532 startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001534
Yohei Yukawac6632df2018-10-21 11:47:16 -07001535 boolean startInputInner(@StartInputReason int startInputReason,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001536 @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
1537 @SoftInputModeFlags int softInputMode, int windowFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 final View view;
1539 synchronized (mH) {
1540 view = mServedView;
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 // Make sure we have a window token for the served view.
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001543 if (DEBUG) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001544 Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) +
Yohei Yukawaa468d702018-10-21 11:42:34 -07001545 " reason=" + InputMethodDebug.startInputReasonToString(startInputReason));
Yohei Yukawa35d3f372015-11-25 11:07:19 -08001546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 if (view == null) {
1548 if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
Dianne Hackborn7663d802012-02-24 13:08:49 -08001549 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
1551 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001552
Yohei Yukawa80498d52018-06-21 16:24:36 -07001553 if (windowGainingFocus == null) {
1554 windowGainingFocus = view.getWindowToken();
1555 if (windowGainingFocus == null) {
1556 Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
1557 return false;
1558 }
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001559 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
Yohei Yukawa80498d52018-06-21 16:24:36 -07001560 if (view.onCheckIsTextEditor()) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001561 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
Yohei Yukawa80498d52018-06-21 16:24:36 -07001562 }
1563 softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
1564 windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
1565 }
1566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // Now we need to get an input connection from the served view.
1568 // This is complicated in a couple ways: we can't be holding our lock
1569 // when calling out to the view, and we need to make sure we call into
1570 // the view on the same thread that is driving its view hierarchy.
1571 Handler vh = view.getHandler();
1572 if (vh == null) {
1573 // If the view doesn't have a handler, something has changed out
Satoshi Kataoka35739502012-10-02 19:00:26 +09001574 // from under us, so just close the current input.
1575 // If we don't close the current input, the current input method can remain on the
1576 // screen without a connection.
1577 if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
1578 closeCurrentInput();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001579 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 }
1581 if (vh.getLooper() != Looper.myLooper()) {
1582 // The view is running on a different thread than our own, so
1583 // we need to reschedule our work for over there.
1584 if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
Yohei Yukawa623e94b2018-01-14 16:30:59 -08001585 vh.post(() -> startInputInner(startInputReason, null, 0, 0, 0));
Dianne Hackborn7663d802012-02-24 13:08:49 -08001586 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 // Okay we are now ready to call into the served view and have it
1590 // do its stuff.
1591 // Life is good: let's hook everything up!
1592 EditorInfo tba = new EditorInfo();
Yohei Yukawa02df3282015-06-03 15:58:59 -07001593 // Note: Use Context#getOpPackageName() rather than Context#getPackageName() so that the
1594 // system can verify the consistency between the uid of this process and package name passed
1595 // from here. See comment of Context#getOpPackageName() for details.
1596 tba.packageName = view.getContext().getOpPackageName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 tba.fieldId = view.getId();
1598 InputConnection ic = view.onCreateInputConnection(tba);
1599 if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
Gilles Debunnec478c172011-12-19 17:29:24 -08001600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 synchronized (mH) {
1602 // Now that we are locked again, validate that our state hasn't
1603 // changed.
1604 if (mServedView != view || !mServedConnecting) {
1605 // Something else happened, so abort.
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001606 if (DEBUG) Log.v(TAG,
1607 "Starting input: finished by someone else. view=" + dumpViewInfo(view)
1608 + " mServedView=" + dumpViewInfo(mServedView)
1609 + " mServedConnecting=" + mServedConnecting);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001610 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 // If we already have a text box, then this view is already
1614 // connected so we want to restart it.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001615 if (mCurrentTextBoxAttribute == null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001616 startInputFlags |= StartInputFlags.INITIAL_CONNECTION;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001617 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 // Hook 'em up and let 'er rip.
1620 mCurrentTextBoxAttribute = tba;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001621 maybeCallServedViewChangedLocked(tba);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 mServedConnecting = false;
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001623 if (mServedInputConnectionWrapper != null) {
1624 mServedInputConnectionWrapper.deactivate();
1625 mServedInputConnectionWrapper = null;
1626 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001627 ControlledInputConnectionWrapper servedContext;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001628 final int missingMethodFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 if (ic != null) {
1630 mCursorSelStart = tba.initialSelStart;
1631 mCursorSelEnd = tba.initialSelEnd;
1632 mCursorCandStart = -1;
1633 mCursorCandEnd = -1;
1634 mCursorRect.setEmpty();
Yohei Yukawa056ffe62014-05-13 14:26:09 +09001635 mCursorAnchorInfo = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001636 final Handler icHandler;
1637 missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
1638 if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER)
1639 != 0) {
1640 // InputConnection#getHandler() is not implemented.
1641 icHandler = null;
1642 } else {
1643 icHandler = ic.getHandler();
1644 }
Yohei Yukawa612cce92016-02-11 17:47:33 -08001645 servedContext = new ControlledInputConnectionWrapper(
1646 icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 } else {
1648 servedContext = null;
Yohei Yukawa19a80a12016-03-14 22:57:37 -07001649 missingMethodFlags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 }
Dianne Hackbornac920872012-05-22 11:49:49 -07001651 mServedInputConnectionWrapper = servedContext;
Yohei Yukawa612cce92016-02-11 17:47:33 -08001652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 try {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001654 if (DEBUG) Log.v(TAG, "START INPUT: view=" + dumpViewInfo(view) + " ic="
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001655 + ic + " tba=" + tba + " startInputFlags="
1656 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001657 final InputBindResult res = mService.startInputOrWindowGainedFocus(
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001658 startInputReason, mClient, windowGainingFocus, startInputFlags,
1659 softInputMode, windowFlags, tba, servedContext, missingMethodFlags,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001660 view.getContext().getApplicationInfo().targetSdkVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
Yohei Yukawa2553e482017-12-15 15:47:33 -08001662 if (res == null) {
1663 Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
1664 + " null. startInputReason="
Yohei Yukawaa468d702018-10-21 11:42:34 -07001665 + InputMethodDebug.startInputReasonToString(startInputReason)
Yohei Yukawa2553e482017-12-15 15:47:33 -08001666 + " editorInfo=" + tba
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001667 + " startInputFlags="
1668 + InputMethodDebug.startInputFlagsToString(startInputFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001669 return false;
1670 }
1671 if (res.id != null) {
1672 setInputChannelLocked(res.channel);
1673 mBindSequence = res.sequence;
1674 mCurMethod = res.method;
1675 mCurId = res.id;
Yohei Yukawa2553e482017-12-15 15:47:33 -08001676 } else if (res.channel != null && res.channel != mCurChannel) {
1677 res.channel.dispose();
1678 }
1679 switch (res.result) {
1680 case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
1681 mRestartOnNextWindowFocus = true;
1682 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
1684 if (mCurMethod != null && mCompletions != null) {
1685 try {
1686 mCurMethod.displayCompletions(mCompletions);
1687 } catch (RemoteException e) {
1688 }
1689 }
1690 } catch (RemoteException e) {
1691 Log.w(TAG, "IME died: " + mCurId, e);
1692 }
1693 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001694
1695 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 }
1697
1698 /**
1699 * When the focused window is dismissed, this method is called to finish the
1700 * input method started before.
1701 * @hide
1702 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001703 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 public void windowDismissed(IBinder appWindowToken) {
1705 checkFocus();
1706 synchronized (mH) {
1707 if (mServedView != null &&
1708 mServedView.getWindowToken() == appWindowToken) {
1709 finishInputLocked();
1710 }
daqidff365e2018-09-19 15:51:22 +08001711 if (mCurRootView != null &&
1712 mCurRootView.getWindowToken() == appWindowToken) {
1713 mCurRootView = null;
1714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 }
1716 }
1717
1718 /**
1719 * Call this when a view receives focus.
1720 * @hide
1721 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001722 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 public void focusIn(View view) {
1724 synchronized (mH) {
1725 focusInLocked(view);
1726 }
1727 }
1728
1729 void focusInLocked(View view) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001730 if (DEBUG) Log.v(TAG, "focusIn: " + dumpViewInfo(view));
Yohei Yukawa5f059652015-05-14 22:16:41 -07001731
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07001732 if (view != null && view.isTemporarilyDetached()) {
1733 // This is a request from a view that is temporarily detached from a window.
1734 if (DEBUG) Log.v(TAG, "Temporarily detached view, ignoring");
1735 return;
1736 }
1737
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001738 if (mCurRootView != view.getRootView()) {
1739 // This is a request from a window that isn't in the window with
1740 // IME focus, so ignore it.
1741 if (DEBUG) Log.v(TAG, "Not IME target window, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 return;
1743 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 mNextServedView = view;
1746 scheduleCheckFocusLocked(view);
1747 }
1748
1749 /**
1750 * Call this when a view loses focus.
1751 * @hide
1752 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001753 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 public void focusOut(View view) {
1755 synchronized (mH) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001756 if (DEBUG) Log.v(TAG, "focusOut: view=" + dumpViewInfo(view)
1757 + " mServedView=" + dumpViewInfo(mServedView));
Yohei Yukawa0b52ed02015-05-29 11:07:02 -07001758 if (mServedView != view) {
1759 // The following code would auto-hide the IME if we end up
1760 // with no more views with focus. This can happen, however,
1761 // whenever we go into touch mode, so it ends up hiding
1762 // at times when we don't really want it to. For now it
1763 // seems better to just turn it all off.
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07001764 // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
Dake Guddf6c1e2018-05-10 11:41:19 -07001765 if (false && canStartInput(view)) {
Yohei Yukawa0b52ed02015-05-29 11:07:02 -07001766 mNextServedView = null;
1767 scheduleCheckFocusLocked(view);
1768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 }
1770 }
1771 }
1772
Yohei Yukawab13f0152015-05-29 17:09:14 -07001773 /**
1774 * Call this when a view is being detached from a {@link android.view.Window}.
1775 * @hide
1776 */
1777 public void onViewDetachedFromWindow(View view) {
1778 synchronized (mH) {
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07001779 if (DEBUG) Log.v(TAG, "onViewDetachedFromWindow: view=" + dumpViewInfo(view)
1780 + " mServedView=" + dumpViewInfo(mServedView));
Yohei Yukawaa4f52ad2016-03-28 17:21:55 -07001781 if (mServedView == view) {
Yohei Yukawab13f0152015-05-29 17:09:14 -07001782 mNextServedView = null;
1783 scheduleCheckFocusLocked(view);
1784 }
1785 }
1786 }
1787
Gilles Debunnec478c172011-12-19 17:29:24 -08001788 static void scheduleCheckFocusLocked(View view) {
Jeff Browna175a5b2012-02-15 19:18:31 -08001789 ViewRootImpl viewRootImpl = view.getViewRootImpl();
1790 if (viewRootImpl != null) {
1791 viewRootImpl.dispatchCheckFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 }
1793 }
Jeff Browna175a5b2012-02-15 19:18:31 -08001794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 /**
1796 * @hide
1797 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001798 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 public void checkFocus() {
Yohei Yukawa241eac22016-03-28 00:28:50 -07001800 if (checkFocusNoStartInput(false)) {
Yohei Yukawa42194222018-10-21 20:14:40 -07001801 startInputInner(StartInputReason.CHECK_FOCUS, null, 0, 0, 0);
Satoshi Kataoka4e5184f2012-07-13 23:10:58 +09001802 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001803 }
1804
Yohei Yukawa241eac22016-03-28 00:28:50 -07001805 private boolean checkFocusNoStartInput(boolean forceNewFocus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 // This is called a lot, so short-circuit before locking.
Dianne Hackborn7663d802012-02-24 13:08:49 -08001807 if (mServedView == mNextServedView && !forceNewFocus) {
Dianne Hackborna82ba542012-02-15 18:19:55 -08001808 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
satok863fcd62011-06-21 17:38:02 +09001810
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001811 final ControlledInputConnectionWrapper ic;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 synchronized (mH) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001813 if (mServedView == mNextServedView && !forceNewFocus) {
Dianne Hackborna82ba542012-02-15 18:19:55 -08001814 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 }
1816 if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
1817 + " next=" + mNextServedView
satok05a6cbe2012-04-05 23:04:08 +09001818 + " forceNewFocus=" + forceNewFocus
1819 + " package="
1820 + (mServedView != null ? mServedView.getContext().getPackageName() : "<none>"));
Dianne Hackborna82ba542012-02-15 18:19:55 -08001821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 if (mNextServedView == null) {
1823 finishInputLocked();
1824 // In this case, we used to have a focused view on the window,
1825 // but no longer do. We should make sure the input method is
1826 // no longer shown, since it serves no purpose.
1827 closeCurrentInput();
Dianne Hackborna82ba542012-02-15 18:19:55 -08001828 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001830
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07001831 ic = mServedInputConnectionWrapper;
Dianne Hackborna82ba542012-02-15 18:19:55 -08001832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 mServedView = mNextServedView;
1834 mCurrentTextBoxAttribute = null;
1835 mCompletions = null;
1836 mServedConnecting = true;
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001837 // servedView has changed and it's not editable.
1838 if (!mServedView.onCheckIsTextEditor()) {
1839 maybeCallServedViewChangedLocked(null);
1840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001842
Yohei Yukawa241eac22016-03-28 00:28:50 -07001843 if (ic != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 ic.finishComposingText();
1845 }
Dianne Hackborna82ba542012-02-15 18:19:55 -08001846
1847 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001849
Mathew Inwooda570dee2018-08-17 14:56:00 +01001850 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 void closeCurrentInput() {
1852 try {
The Android Open Source Project4df24232009-03-05 14:34:35 -08001853 mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001855 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07001860 * Called by ViewAncestor when its window gets input focus.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 * @hide
1862 */
Yohei Yukawa22dac1c2017-02-12 16:54:16 -08001863 public void onPostWindowFocus(View rootView, View focusedView,
1864 @SoftInputModeFlags int softInputMode, boolean first, int windowFlags) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001865 boolean forceNewFocus = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 synchronized (mH) {
1867 if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
Yohei Yukawaa468d702018-10-21 11:42:34 -07001868 + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 + " first=" + first + " flags=#"
1870 + Integer.toHexString(windowFlags));
Yohei Yukawa2553e482017-12-15 15:47:33 -08001871 if (mRestartOnNextWindowFocus) {
1872 if (DEBUG) Log.v(TAG, "Restarting due to mRestartOnNextWindowFocus");
1873 mRestartOnNextWindowFocus = false;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001874 forceNewFocus = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 }
1876 focusInLocked(focusedView != null ? focusedView : rootView);
1877 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001878
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001879 int startInputFlags = 0;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001880 if (focusedView != null) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001881 startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001882 if (focusedView.onCheckIsTextEditor()) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001883 startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 }
1885 }
Dianne Hackborn7663d802012-02-24 13:08:49 -08001886 if (first) {
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001887 startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN;
Dianne Hackborn7663d802012-02-24 13:08:49 -08001888 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07001889
Yohei Yukawa241eac22016-03-28 00:28:50 -07001890 if (checkFocusNoStartInput(forceNewFocus)) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001891 // We need to restart input on the current focus view. This
1892 // should be done in conjunction with telling the system service
1893 // about the window gaining focus, to help make the transition
1894 // smooth.
Yohei Yukawa42194222018-10-21 20:14:40 -07001895 if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001896 startInputFlags, softInputMode, windowFlags)) {
Dianne Hackborn7663d802012-02-24 13:08:49 -08001897 return;
1898 }
1899 }
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001900
Dianne Hackborn7663d802012-02-24 13:08:49 -08001901 // For some reason we didn't do a startInput + windowFocusGain, so
1902 // we'll just do a window focus gain and call it a day.
1903 synchronized (mH) {
1904 try {
Dianne Hackbornac920872012-05-22 11:49:49 -07001905 if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
Yohei Yukawa05c25f82016-02-22 12:41:17 -08001906 mService.startInputOrWindowGainedFocus(
Yohei Yukawa42194222018-10-21 20:14:40 -07001907 StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
Yohei Yukawa35fa6d52018-10-31 11:33:32 -07001908 rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags,
1909 null, null, 0 /* missingMethodFlags */,
Yohei Yukawacf68d522017-12-12 09:33:26 -08001910 rootView.getContext().getApplicationInfo().targetSdkVersion);
Dianne Hackborn7663d802012-02-24 13:08:49 -08001911 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07001912 throw e.rethrowFromSystemServer();
Dianne Hackborn7663d802012-02-24 13:08:49 -08001913 }
Dianne Hackborn06a591c2012-02-16 10:25:26 -08001914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001916
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001917 /** @hide */
Mathew Inwooda570dee2018-08-17 14:56:00 +01001918 @UnsupportedAppUsage
Yohei Yukawa5f059652015-05-14 22:16:41 -07001919 public void onPreWindowFocus(View rootView, boolean hasWindowFocus) {
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001920 synchronized (mH) {
Yohei Yukawa5f059652015-05-14 22:16:41 -07001921 if (rootView == null) {
1922 mCurRootView = null;
1923 } if (hasWindowFocus) {
1924 mCurRootView = rootView;
1925 } else if (rootView == mCurRootView) {
1926 // If the mCurRootView is losing window focus, release the strong reference to it
1927 // so as not to prevent it from being garbage-collected.
1928 mCurRootView = null;
1929 } else {
1930 if (DEBUG) {
1931 Log.v(TAG, "Ignoring onPreWindowFocus()."
1932 + " mCurRootView=" + mCurRootView + " rootView=" + rootView);
1933 }
1934 }
Wale Ogunwale159c3d82015-05-14 12:20:53 -07001935 }
1936 }
Yohei Yukawa5f059652015-05-14 22:16:41 -07001937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 /**
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08001939 * Register for IME state callbacks and applying visibility in
1940 * {@link android.view.ImeInsetsSourceConsumer}.
1941 * @hide
1942 */
1943 public void registerImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
1944 if (imeInsetsConsumer == null) {
1945 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
1946 }
1947
1948 synchronized (mH) {
1949 mImeInsetsConsumer = imeInsetsConsumer;
1950 }
1951 }
1952
1953 /**
Louis Chang3d4a7d12019-04-12 16:18:30 +08001954 * Unregister for IME state callbacks and applying visibility in
1955 * {@link android.view.ImeInsetsSourceConsumer}.
1956 * @hide
1957 */
1958 public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
1959 if (imeInsetsConsumer == null) {
1960 throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
1961 }
1962
1963 synchronized (mH) {
1964 if (mImeInsetsConsumer == imeInsetsConsumer) {
1965 mImeInsetsConsumer = null;
1966 }
1967 }
1968 }
1969
1970 /**
Tarandeep Singh46d59f02019-01-29 18:09:15 -08001971 * Call showSoftInput with currently focused view.
1972 * @return {@code true} if IME can be shown.
1973 * @hide
1974 */
1975 public boolean requestImeShow(ResultReceiver resultReceiver) {
1976 synchronized (mH) {
1977 if (mServedView == null) {
1978 return false;
1979 }
1980 showSoftInput(mServedView, 0 /* flags */, resultReceiver);
1981 return true;
1982 }
1983 }
1984
1985 /**
1986 * Notify IME directly that it is no longer visible.
1987 * @hide
1988 */
1989 public void notifyImeHidden() {
1990 synchronized (mH) {
1991 try {
1992 if (mCurMethod != null) {
1993 mCurMethod.notifyImeHidden();
1994 }
1995 } catch (RemoteException re) {
1996 }
1997 }
1998 }
1999
2000 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 * Report the current selection range.
Jean Chalard6fd68e02014-02-20 17:48:46 +09002002 *
2003 * <p><strong>Editor authors</strong>, you need to call this method whenever
2004 * the cursor moves in your editor. Remember that in addition to doing this, your
2005 * editor needs to always supply current cursor values in
2006 * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
2007 * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
2008 * called, which happens whenever the keyboard shows up or the focus changes
2009 * to a text field, among other cases.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 */
2011 public void updateSelection(View view, int selStart, int selEnd,
2012 int candidatesStart, int candidatesEnd) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002013 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002014 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2015 if (fallbackImm != null) {
2016 fallbackImm.updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002017 return;
2018 }
2019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 checkFocus();
2021 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002022 if ((mServedView != view && (mServedView == null
2023 || !mServedView.checkInputConnectionProxy(view)))
2024 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 return;
2026 }
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
2029 || mCursorCandStart != candidatesStart
2030 || mCursorCandEnd != candidatesEnd) {
2031 if (DEBUG) Log.d(TAG, "updateSelection");
2032
2033 try {
2034 if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
Jean Chalardc743cb92013-09-12 16:28:45 +09002035 final int oldSelStart = mCursorSelStart;
2036 final int oldSelEnd = mCursorSelEnd;
2037 // Update internal values before sending updateSelection to the IME, because
2038 // if it changes the text within its onUpdateSelection handler in a way that
2039 // 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 -08002040 mCursorSelStart = selStart;
2041 mCursorSelEnd = selEnd;
2042 mCursorCandStart = candidatesStart;
2043 mCursorCandEnd = candidatesEnd;
Jean Chalardc743cb92013-09-12 16:28:45 +09002044 mCurMethod.updateSelection(oldSelStart, oldSelEnd,
2045 selStart, selEnd, candidatesStart, candidatesEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 } catch (RemoteException e) {
2047 Log.w(TAG, "IME died: " + mCurId, e);
2048 }
2049 }
2050 }
2051 }
2052
2053 /**
satok863fcd62011-06-21 17:38:02 +09002054 * Notify the event when the user tapped or clicked the text view.
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002055 *
2056 * @param view {@link View} which is being clicked.
2057 * @see InputMethodService#onViewClicked(boolean)
2058 * @deprecated The semantics of this method can never be defined well for composite {@link View}
2059 * that works as a giant "Canvas", which can host its own UI hierarchy and sub focus
2060 * state. {@link android.webkit.WebView} is a good example. Application / IME
2061 * developers should not rely on this method.
satok863fcd62011-06-21 17:38:02 +09002062 */
Yohei Yukawa0eb8d162019-01-22 21:47:57 -08002063 @Deprecated
satok863fcd62011-06-21 17:38:02 +09002064 public void viewClicked(View view) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002065 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002066 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2067 if (fallbackImm != null) {
2068 fallbackImm.viewClicked(view);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002069 return;
2070 }
2071
satok863fcd62011-06-21 17:38:02 +09002072 final boolean focusChanged = mServedView != mNextServedView;
2073 checkFocus();
2074 synchronized (mH) {
2075 if ((mServedView != view && (mServedView == null
2076 || !mServedView.checkInputConnectionProxy(view)))
2077 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2078 return;
2079 }
2080 try {
2081 if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
2082 mCurMethod.viewClicked(focusChanged);
2083 } catch (RemoteException e) {
2084 Log.w(TAG, "IME died: " + mCurId, e);
2085 }
2086 }
2087 }
2088
2089 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002090 * Return true if the current input method wants to watch the location
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 * of the input editor's cursor in its window.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002092 *
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002093 * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
Yohei Yukawa4de04792014-04-17 12:40:31 +09002094 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002095 @Deprecated
2096 public boolean isWatchingCursor(View view) {
2097 return false;
Yohei Yukawa4de04792014-04-17 12:40:31 +09002098 }
2099
2100 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002101 * Return true if the current input method wants to be notified when cursor/anchor location
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002102 * is changed.
Yohei Yukawab7b79072014-03-25 11:02:00 +09002103 *
2104 * @hide
2105 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002106 @UnsupportedAppUsage
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002107 public boolean isCursorAnchorInfoEnabled() {
2108 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002109 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002110 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawaa277db22014-08-21 18:38:44 -07002111 final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002112 InputConnection.CURSOR_UPDATE_MONITOR) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002113 return isImmediate || isMonitoring;
2114 }
2115 }
2116
2117 /**
Yohei Yukawaa277db22014-08-21 18:38:44 -07002118 * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002119 *
2120 * @hide
2121 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002122 @UnsupportedAppUsage
Yohei Yukawaa277db22014-08-21 18:38:44 -07002123 public void setUpdateCursorAnchorInfoMode(int flags) {
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002124 synchronized (mH) {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002125 mRequestUpdateCursorAnchorInfoMonitorMode = flags;
Yohei Yukawab7b79072014-03-25 11:02:00 +09002126 }
2127 }
2128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 /**
2130 * Report the current cursor location in its window.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002131 *
2132 * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 */
Yohei Yukawaa277db22014-08-21 18:38:44 -07002134 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 public void updateCursor(View view, int left, int top, int right, int bottom) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002136 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002137 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2138 if (fallbackImm != null) {
2139 fallbackImm.updateCursor(view, left, top, right, bottom);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002140 return;
2141 }
2142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 checkFocus();
2144 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002145 if ((mServedView != view && (mServedView == null
2146 || !mServedView.checkInputConnectionProxy(view)))
2147 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 return;
2149 }
Yohei Yukawaa277db22014-08-21 18:38:44 -07002150
2151 mTmpCursorRect.set(left, top, right, bottom);
2152 if (!mCursorRect.equals(mTmpCursorRect)) {
2153 if (DEBUG) Log.d(TAG, "updateCursor");
2154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 try {
Yohei Yukawaa277db22014-08-21 18:38:44 -07002156 if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
2157 mCurMethod.updateCursor(mTmpCursorRect);
2158 mCursorRect.set(mTmpCursorRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 } catch (RemoteException e) {
2160 Log.w(TAG, "IME died: " + mCurId, e);
2161 }
2162 }
2163 }
2164 }
2165
2166 /**
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002167 * Report positional change of the text insertion point and/or characters in the composition
2168 * string.
2169 */
2170 public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
2171 if (view == null || cursorAnchorInfo == null) {
2172 return;
2173 }
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002174 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002175 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2176 if (fallbackImm != null) {
2177 fallbackImm.updateCursorAnchorInfo(view, cursorAnchorInfo);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002178 return;
2179 }
2180
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002181 checkFocus();
2182 synchronized (mH) {
2183 if ((mServedView != view &&
2184 (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
2185 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2186 return;
2187 }
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002188 // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
2189 // not been changed from the previous call.
Yohei Yukawaa277db22014-08-21 18:38:44 -07002190 final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002191 InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002192 if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
Yohei Yukawa73605912014-08-13 16:49:35 +09002193 // TODO: Consider always emitting this message once we have addressed redundant
2194 // calls of this method from android.widget.Editor.
2195 if (DEBUG) {
2196 Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
2197 + cursorAnchorInfo);
2198 }
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002199 return;
2200 }
2201 if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002202 try {
2203 mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
Yohei Yukawa056ffe62014-05-13 14:26:09 +09002204 mCursorAnchorInfo = cursorAnchorInfo;
Yohei Yukawa0023d0e2014-07-11 04:13:03 +09002205 // Clear immediate bit (if any).
Yohei Yukawaa277db22014-08-21 18:38:44 -07002206 mRequestUpdateCursorAnchorInfoMonitorMode &=
Yohei Yukawad8636ea2014-09-02 22:03:30 -07002207 ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
Yohei Yukawac2ddd602014-05-06 21:22:49 +09002208 } catch (RemoteException e) {
2209 Log.w(TAG, "IME died: " + mCurId, e);
2210 }
2211 }
2212 }
2213
2214 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
2216 * InputMethodSession.appPrivateCommand()} on the current Input Method.
2217 * @param view Optional View that is sending the command, or null if
2218 * you want to send the command regardless of the view that is attached
2219 * to the input method.
2220 * @param action Name of the command to be performed. This <em>must</em>
2221 * be a scoped name, i.e. prefixed with a package name you own, so that
2222 * different developers will not create conflicting commands.
2223 * @param data Any data to include with the command.
2224 */
2225 public void sendAppPrivateCommand(View view, String action, Bundle data) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002226 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002227 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2228 if (fallbackImm != null) {
2229 fallbackImm.sendAppPrivateCommand(view, action, data);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002230 return;
2231 }
2232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 checkFocus();
2234 synchronized (mH) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07002235 if ((mServedView != view && (mServedView == null
2236 || !mServedView.checkInputConnectionProxy(view)))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 || mCurrentTextBoxAttribute == null || mCurMethod == null) {
2238 return;
2239 }
2240 try {
2241 if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
2242 mCurMethod.appPrivateCommand(action, data);
2243 } catch (RemoteException e) {
2244 Log.w(TAG, "IME died: " + mCurId, e);
2245 }
2246 }
2247 }
satok28203512010-11-24 11:06:49 +09002248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 /**
satok28203512010-11-24 11:06:49 +09002250 * Force switch to a new input method component. This can only be called
2251 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002252 *
2253 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, the undocumented behavior that
2254 * token can be {@code null} when the caller has
2255 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} is deprecated. Instead, update
2256 * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2257 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2258 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 * @param token Supplies the identifying token given to an input method
2260 * when it was started, which allows it to perform this operation on
2261 * itself.
2262 * @param id The unique identifier for the new input method to be switched to.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002263 * @deprecated Use {@link InputMethodService#switchInputMethod(String)}
2264 * instead. This method was intended for IME developers who should be accessing APIs through
2265 * 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 -08002266 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002267 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 public void setInputMethod(IBinder token, String id) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002269 if (token == null) {
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002270 // There are still some system components that rely on this undocumented behavior
2271 // regarding null IME token with WRITE_SECURE_SETTINGS. Provide a fallback logic as a
2272 // temporary remedy.
2273 if (id == null) {
2274 return;
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002275 }
Yohei Yukawa0c1ebff2018-12-27 14:06:28 -08002276 if (Process.myUid() == Process.SYSTEM_UID) {
2277 Log.w(TAG, "System process should not be calling setInputMethod() because almost "
2278 + "always it is a bug under multi-user / multi-profile environment. "
2279 + "Consider interacting with InputMethodManagerService directly via "
2280 + "LocalServices.");
2281 return;
2282 }
2283 final Context fallbackContext = ActivityThread.currentApplication();
2284 if (fallbackContext == null) {
2285 return;
2286 }
2287 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2288 != PackageManager.PERMISSION_GRANTED) {
2289 return;
2290 }
2291 final List<InputMethodInfo> imis = getEnabledInputMethodList();
2292 final int numImis = imis.size();
2293 boolean found = false;
2294 for (int i = 0; i < numImis; ++i) {
2295 final InputMethodInfo imi = imis.get(i);
2296 if (id.equals(imi.getId())) {
2297 found = true;
2298 break;
2299 }
2300 }
2301 if (!found) {
2302 Log.e(TAG, "Ignoring setInputMethod(null, " + id + ") because the specified "
2303 + "id not found in enabled IMEs.");
2304 return;
2305 }
2306 Log.w(TAG, "The undocumented behavior that setInputMethod() accepts null token "
2307 + "when the caller has WRITE_SECURE_SETTINGS is deprecated. This behavior may "
2308 + "be completely removed in a future version. Update secure settings directly "
2309 + "instead.");
2310 final ContentResolver resolver = fallbackContext.getContentResolver();
2311 Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
2312 NOT_A_SUBTYPE_ID);
2313 Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, id);
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002314 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002316 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 }
satok28203512010-11-24 11:06:49 +09002318
2319 /**
2320 * Force switch to a new input method and subtype. This can only be called
2321 * from an application or a service which has a token of the currently active input method.
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002322 *
2323 * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, {@code token} cannot be
2324 * {@code null} even with {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}. Instead,
2325 * update {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2326 * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2327 *
satok28203512010-11-24 11:06:49 +09002328 * @param token Supplies the identifying token given to an input method
2329 * when it was started, which allows it to perform this operation on
2330 * itself.
2331 * @param id The unique identifier for the new input method to be switched to.
2332 * @param subtype The new subtype of the new input method to be switched to.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002333 * @deprecated Use
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002334 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002335 * instead. This method was intended for IME developers who should be accessing APIs through
2336 * the service. APIs in this class are intended for app developers interacting with the IME.
satok28203512010-11-24 11:06:49 +09002337 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002338 @Deprecated
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002339 public void setInputMethodAndSubtype(@NonNull IBinder token, String id,
2340 InputMethodSubtype subtype) {
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002341 if (token == null) {
Yohei Yukawa4773ee12018-12-24 21:13:53 -08002342 Log.e(TAG, "setInputMethodAndSubtype() does not accept null token on Android Q "
2343 + "and later.");
Yohei Yukawaeec552e2018-09-09 20:48:41 -07002344 return;
satok28203512010-11-24 11:06:49 +09002345 }
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002346 InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype);
satok28203512010-11-24 11:06:49 +09002347 }
2348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 /**
2350 * Close/hide the input method's soft input area, so the user no longer
2351 * sees it or can interact with it. This can only be called
2352 * from the currently active input method, as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002353 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 * @param token Supplies the identifying token given to an input method
2355 * when it was started, which allows it to perform this operation on
2356 * itself.
2357 * @param flags Provides additional operating flags. Currently may be
The Android Open Source Project4df24232009-03-05 14:34:35 -08002358 * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
2359 * {@link #HIDE_NOT_ALWAYS} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002360 * @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
2361 * intended for IME developers who should be accessing APIs through the service. APIs in this
2362 * class are intended for app developers interacting with the IME.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002364 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 public void hideSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002366 InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 }
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 /**
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002370 * Show the input method's soft input area, so the user
The Android Open Source Project4df24232009-03-05 14:34:35 -08002371 * sees the input method window and can interact with it.
2372 * This can only be called from the currently active input method,
2373 * as validated by the given token.
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002374 *
The Android Open Source Project4df24232009-03-05 14:34:35 -08002375 * @param token Supplies the identifying token given to an input method
2376 * when it was started, which allows it to perform this operation on
2377 * itself.
2378 * @param flags Provides additional operating flags. Currently may be
2379 * 0 or have the {@link #SHOW_IMPLICIT} or
2380 * {@link #SHOW_FORCED} bit set.
Yohei Yukawafbc2f7a2018-01-16 08:09:11 -08002381 * @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
2382 * intended for IME developers who should be accessing APIs through the service. APIs in this
2383 * class are intended for app developers interacting with the IME.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002384 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002385 @Deprecated
The Android Open Source Project4df24232009-03-05 14:34:35 -08002386 public void showSoftInputFromInputMethod(IBinder token, int flags) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002387 InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
The Android Open Source Project4df24232009-03-05 14:34:35 -08002388 }
Jeff Brownc28867a2013-03-26 15:42:39 -07002389
The Android Open Source Project4df24232009-03-05 14:34:35 -08002390 /**
Jeff Brownf9e989d2013-04-04 23:04:03 -07002391 * Dispatches an input event to the IME.
2392 *
2393 * Returns {@link #DISPATCH_HANDLED} if the event was handled.
2394 * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
2395 * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
2396 * callback will be invoked later.
2397 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 * @hide
2399 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07002400 public int dispatchInputEvent(InputEvent event, Object token,
2401 FinishedInputEventCallback callback, Handler handler) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002403 if (mCurMethod != null) {
Jeff Brownc28867a2013-03-26 15:42:39 -07002404 if (event instanceof KeyEvent) {
2405 KeyEvent keyEvent = (KeyEvent)event;
2406 if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
2407 && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
2408 && keyEvent.getRepeatCount() == 0) {
2409 showInputMethodPickerLocked();
Jeff Brownf9e989d2013-04-04 23:04:03 -07002410 return DISPATCH_HANDLED;
Jeff Brownc28867a2013-03-26 15:42:39 -07002411 }
Jeff Brown29c0ed22013-01-14 13:50:37 -08002412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413
Jeff Brownc28867a2013-03-26 15:42:39 -07002414 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002415
2416 PendingEvent p = obtainPendingEventLocked(
2417 event, token, mCurId, callback, handler);
2418 if (mMainLooper.isCurrentThread()) {
2419 // Already running on the IMM thread so we can send the event immediately.
2420 return sendInputEventOnMainLooperLocked(p);
Victoria Leaseb38070c2012-08-24 13:46:02 -07002421 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002422
2423 // Post the event to the IMM thread.
2424 Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
2425 msg.setAsynchronous(true);
2426 mH.sendMessage(msg);
2427 return DISPATCH_IN_PROGRESS;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002428 }
2429 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002430 return DISPATCH_NOT_HANDLED;
Victoria Leaseb38070c2012-08-24 13:46:02 -07002431 }
2432
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002433 /**
2434 * Provides the default implementation of {@link InputConnection#sendKeyEvent(KeyEvent)}, which
2435 * is expected to dispatch an keyboard event sent from the IME to an appropriate event target
2436 * depending on the given {@link View} and the current focus state.
2437 *
2438 * <p>CAUTION: This method is provided only for the situation where
2439 * {@link InputConnection#sendKeyEvent(KeyEvent)} needs to be implemented without relying on
2440 * {@link BaseInputConnection}. Do not use this API for anything else.</p>
2441 *
2442 * @param targetView the default target view. If {@code null} is specified, then this method
2443 * tries to find a good event target based on the current focus state.
2444 * @param event the key event to be dispatched.
2445 */
2446 public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
2447 @NonNull KeyEvent event) {
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002448 // Re-dispatch if there is a context mismatch.
Yohei Yukawa052ab8c2018-10-26 08:43:30 -07002449 final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
2450 if (fallbackImm != null) {
2451 fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002452 return;
2453 }
2454
Yohei Yukawa2afe2aa2016-01-07 18:09:44 -08002455 synchronized (mH) {
2456 ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
2457 if (viewRootImpl == null) {
2458 if (mServedView != null) {
2459 viewRootImpl = mServedView.getViewRootImpl();
2460 }
2461 }
2462 if (viewRootImpl != null) {
2463 viewRootImpl.dispatchKeyFromIme(event);
2464 }
2465 }
2466 }
2467
Jeff Brownf9e989d2013-04-04 23:04:03 -07002468 // Must be called on the main looper
2469 void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
2470 final boolean handled;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002471 synchronized (mH) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002472 int result = sendInputEventOnMainLooperLocked(p);
2473 if (result == DISPATCH_IN_PROGRESS) {
2474 return;
2475 }
2476
2477 handled = (result == DISPATCH_HANDLED);
2478 }
2479
2480 invokeFinishedInputEventCallback(p, handled);
2481 }
2482
2483 // Must be called on the main looper
2484 int sendInputEventOnMainLooperLocked(PendingEvent p) {
2485 if (mCurChannel != null) {
2486 if (mCurSender == null) {
2487 mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
2488 }
2489
2490 final InputEvent event = p.mEvent;
2491 final int seq = event.getSequenceNumber();
2492 if (mCurSender.sendInputEvent(seq, event)) {
2493 mPendingEvents.put(seq, p);
2494 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
2495 mPendingEvents.size());
2496
gaoshang863ad2f2017-04-20 14:14:18 +08002497 Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, seq, 0, p);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002498 msg.setAsynchronous(true);
2499 mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
2500 return DISPATCH_IN_PROGRESS;
2501 }
2502
2503 Log.w(TAG, "Unable to send input event to IME: "
2504 + mCurId + " dropping: " + event);
2505 }
2506 return DISPATCH_NOT_HANDLED;
2507 }
2508
2509 void finishedInputEvent(int seq, boolean handled, boolean timeout) {
2510 final PendingEvent p;
2511 synchronized (mH) {
2512 int index = mPendingEvents.indexOfKey(seq);
2513 if (index < 0) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002514 return; // spurious, event already finished or timed out
2515 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002516
Jeff Brownf9e989d2013-04-04 23:04:03 -07002517 p = mPendingEvents.valueAt(index);
2518 mPendingEvents.removeAt(index);
2519 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002520
Jeff Brownf9e989d2013-04-04 23:04:03 -07002521 if (timeout) {
2522 Log.w(TAG, "Timeout waiting for IME to handle input event after "
2523 + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
2524 } else {
2525 mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
Jeff Brown4d656882013-04-03 14:39:19 -07002526 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002527 }
Jeff Brownf9e989d2013-04-04 23:04:03 -07002528
2529 invokeFinishedInputEventCallback(p, handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002530 }
2531
Jeff Brownf9e989d2013-04-04 23:04:03 -07002532 // Assumes the event has already been removed from the queue.
2533 void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
2534 p.mHandled = handled;
2535 if (p.mHandler.getLooper().isCurrentThread()) {
2536 // Already running on the callback handler thread so we can send the
2537 // callback immediately.
2538 p.run();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002539 } else {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002540 // Post the event to the callback handler thread.
2541 // In this case, the callback will be responsible for recycling the event.
2542 Message msg = Message.obtain(p.mHandler, p);
2543 msg.setAsynchronous(true);
2544 msg.sendToTarget();
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 }
satokab751aa2010-09-14 19:17:36 +09002547
Michael Wrightef17e872013-04-01 13:15:55 -07002548 private void flushPendingEventsLocked() {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002549 mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
Jeff Brown4d656882013-04-03 14:39:19 -07002550
Jeff Brownf9e989d2013-04-04 23:04:03 -07002551 final int count = mPendingEvents.size();
2552 for (int i = 0; i < count; i++) {
2553 int seq = mPendingEvents.keyAt(i);
2554 Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
Michael Wrightef17e872013-04-01 13:15:55 -07002555 msg.setAsynchronous(true);
Jeff Brownf9e989d2013-04-04 23:04:03 -07002556 msg.sendToTarget();
Michael Wrightef17e872013-04-01 13:15:55 -07002557 }
2558 }
2559
Jeff Brownf9e989d2013-04-04 23:04:03 -07002560 private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
2561 String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
2562 PendingEvent p = mPendingEventPool.acquire();
2563 if (p == null) {
2564 p = new PendingEvent();
2565 }
2566 p.mEvent = event;
2567 p.mToken = token;
2568 p.mInputMethodId = inputMethodId;
2569 p.mCallback = callback;
2570 p.mHandler = handler;
2571 return p;
2572 }
2573
2574 private void recyclePendingEventLocked(PendingEvent p) {
2575 p.recycle();
2576 mPendingEventPool.release(p);
2577 }
2578
Tarandeep Singh47e49fd2019-03-12 13:39:38 -07002579 /**
2580 * Show IME picker popup window.
2581 *
2582 * <p>Requires the {@link PackageManager#FEATURE_INPUT_METHODS} feature which can be detected
2583 * using {@link PackageManager#hasSystemFeature(String)}.
2584 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 public void showInputMethodPicker() {
2586 synchronized (mH) {
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002587 showInputMethodPickerLocked();
2588 }
2589 }
2590
Seigo Nonaka14e13912015-05-06 21:04:13 -07002591 /**
lumark0b05f9e2018-11-26 15:09:06 +08002592 * Shows the input method chooser dialog from system.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002593 *
2594 * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
lumark0b05f9e2018-11-26 15:09:06 +08002595 * @param displayId The ID of the display where the chooser dialog should be shown.
Seigo Nonaka14e13912015-05-06 21:04:13 -07002596 * @hide
2597 */
lumark0b05f9e2018-11-26 15:09:06 +08002598 @RequiresPermission(WRITE_SECURE_SETTINGS)
2599 public void showInputMethodPickerFromSystem(boolean showAuxiliarySubtypes, int displayId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002600 final int mode = showAuxiliarySubtypes
2601 ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
2602 : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
2603 try {
lumark0b05f9e2018-11-26 15:09:06 +08002604 mService.showInputMethodPickerFromSystem(mClient, mode, displayId);
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002605 } catch (RemoteException e) {
2606 throw e.rethrowFromSystemServer();
Seigo Nonaka14e13912015-05-06 21:04:13 -07002607 }
2608 }
2609
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002610 private void showInputMethodPickerLocked() {
2611 try {
Seigo Nonaka14e13912015-05-06 21:04:13 -07002612 mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002613 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -07002614 throw e.rethrowFromSystemServer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 }
2616 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08002617
satokd4fce2b2011-04-11 12:07:13 +09002618 /**
Tarandeep Singheb570612018-01-29 16:20:32 -08002619 * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected.
2620 *
2621 * <p>When customizing the implementation of {@link #showInputMethodPicker()} API, make sure
2622 * that this test API returns when and only while and only while
2623 * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not
2624 * pass CTS.</p>
2625 *
2626 * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI.
2627 * @hide
2628 */
2629 @TestApi
2630 public boolean isInputMethodPickerShown() {
2631 try {
2632 return mService.isInputMethodPickerShownForTest();
2633 } catch (RemoteException e) {
2634 throw e.rethrowFromSystemServer();
2635 }
2636 }
2637
2638 /**
satokd4fce2b2011-04-11 12:07:13 +09002639 * Show the settings for enabling subtypes of the specified input method.
2640 * @param imiId An input method, whose subtypes settings will be shown. If imiId is null,
2641 * subtypes of all input methods will be shown.
2642 */
2643 public void showInputMethodAndSubtypeEnabler(String imiId) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002644 try {
2645 mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
2646 } catch (RemoteException e) {
2647 throw e.rethrowFromSystemServer();
satok47a44912010-10-06 16:03:58 +09002648 }
2649 }
2650
satokd4fce2b2011-04-11 12:07:13 +09002651 /**
2652 * Returns the current input method subtype. This subtype is one of the subtypes in
2653 * the current input method. This method returns null when the current input method doesn't
2654 * have any input method subtype.
2655 */
satok04d50202010-10-25 22:20:12 +09002656 public InputMethodSubtype getCurrentInputMethodSubtype() {
Gopal Krishna Shuklafa1886f2016-06-30 11:34:21 +05302657 try {
2658 return mService.getCurrentInputMethodSubtype();
2659 } catch (RemoteException e) {
2660 throw e.rethrowFromSystemServer();
satok04d50202010-10-25 22:20:12 +09002661 }
2662 }
2663
satokd4fce2b2011-04-11 12:07:13 +09002664 /**
2665 * Switch to a new input method subtype of the current input method.
2666 * @param subtype A new input method subtype to switch.
2667 * @return true if the current subtype was successfully switched. When the specified subtype is
2668 * null, this method returns false.
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002669 * @deprecated If the calling process is an IME, use
2670 * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}, which
2671 * does not require any permission as long as the caller is the current IME.
2672 * If the calling process is some privileged app that already has
2673 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission, just
2674 * directly update {@link Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE}.
satokd4fce2b2011-04-11 12:07:13 +09002675 */
Yohei Yukawaff42b1b2019-01-23 15:47:35 -08002676 @Deprecated
Yoshiki Iguchi00d51222015-05-29 15:36:22 +09002677 @RequiresPermission(WRITE_SECURE_SETTINGS)
satokb66d2872010-11-10 01:04:04 +09002678 public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002679 if (Process.myUid() == Process.SYSTEM_UID) {
2680 Log.w(TAG, "System process should not call setCurrentInputMethodSubtype() because "
2681 + "almost always it is a bug under multi-user / multi-profile environment. "
2682 + "Consider directly interacting with InputMethodManagerService "
2683 + "via LocalServices.");
2684 return false;
satokb66d2872010-11-10 01:04:04 +09002685 }
Yohei Yukawafd8f7212019-01-22 19:25:44 -08002686 if (subtype == null) {
2687 // See the JavaDoc. This is how this method has worked.
2688 return false;
2689 }
2690 final Context fallbackContext = ActivityThread.currentApplication();
2691 if (fallbackContext == null) {
2692 return false;
2693 }
2694 if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2695 != PackageManager.PERMISSION_GRANTED) {
2696 return false;
2697 }
2698 final ContentResolver contentResolver = fallbackContext.getContentResolver();
2699 final String imeId = Settings.Secure.getString(contentResolver,
2700 Settings.Secure.DEFAULT_INPUT_METHOD);
2701 if (ComponentName.unflattenFromString(imeId) == null) {
2702 // Null or invalid IME ID format.
2703 return false;
2704 }
2705 final List<InputMethodSubtype> enabledSubtypes;
2706 try {
2707 enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true);
2708 } catch (RemoteException e) {
2709 return false;
2710 }
2711 final int numSubtypes = enabledSubtypes.size();
2712 for (int i = 0; i < numSubtypes; ++i) {
2713 final InputMethodSubtype enabledSubtype = enabledSubtypes.get(i);
2714 if (enabledSubtype.equals(subtype)) {
2715 Settings.Secure.putInt(contentResolver,
2716 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, enabledSubtype.hashCode());
2717 return true;
2718 }
2719 }
2720 return false;
satokb66d2872010-11-10 01:04:04 +09002721 }
2722
satokd4fce2b2011-04-11 12:07:13 +09002723 /**
Yohei Yukawa02970512014-06-05 16:16:18 +09002724 * Notify that a user took some action with this input method.
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002725 *
2726 * @deprecated Just kept to avoid possible app compat issue.
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002727 * @hide
2728 */
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002729 @Deprecated
Yohei Yukawaa086f952018-09-11 11:37:08 -07002730 @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
Yohei Yukawa02970512014-06-05 16:16:18 +09002731 public void notifyUserAction() {
Yohei Yukawac07fd4c2018-09-11 11:37:13 -07002732 Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
2733 + " that does nothing. Leave comments in b.android.com/114740982 if your "
2734 + " application still depends on the previous behavior of this method.");
Satoshi Kataokad7443c82013-10-15 17:45:43 +09002735 }
2736
2737 /**
satokd4fce2b2011-04-11 12:07:13 +09002738 * Returns a map of all shortcut input method info and their subtypes.
2739 */
satokf3db1af2010-11-23 13:34:33 +09002740 public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
Yohei Yukawafefedc52018-12-24 19:43:17 -08002741 final List<InputMethodInfo> enabledImes = getEnabledInputMethodList();
2742
2743 // Ensure we check system IMEs first.
2744 enabledImes.sort(Comparator.comparingInt(imi -> imi.isSystem() ? 0 : 1));
2745
2746 final int numEnabledImes = enabledImes.size();
2747 for (int imiIndex = 0; imiIndex < numEnabledImes; ++imiIndex) {
2748 final InputMethodInfo imi = enabledImes.get(imiIndex);
2749 final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(
2750 imi, true);
2751 final int subtypeCount = subtypes.size();
2752 for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
2753 final InputMethodSubtype subtype = imi.getSubtypeAt(subtypeIndex);
2754 if (SUBTYPE_MODE_VOICE.equals(subtype.getMode())) {
2755 return Collections.singletonMap(imi, Collections.singletonList(subtype));
satok4e4569d2010-11-19 18:45:53 +09002756 }
satok4e4569d2010-11-19 18:45:53 +09002757 }
satok4e4569d2010-11-19 18:45:53 +09002758 }
Yohei Yukawafefedc52018-12-24 19:43:17 -08002759 return Collections.emptyMap();
satok4e4569d2010-11-19 18:45:53 +09002760 }
satokf3db1af2010-11-23 13:34:33 +09002761
satokd4fce2b2011-04-11 12:07:13 +09002762 /**
Yohei Yukawab985e6e2018-09-05 17:07:52 -07002763 * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
2764 *
2765 * <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
2766 * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
2767 * started relying on it.</p>
2768 *
2769 * @return Something that is not well-defined.
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002770 * @hide
2771 */
Mathew Inwooda570dee2018-08-17 14:56:00 +01002772 @UnsupportedAppUsage
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002773 public int getInputMethodWindowVisibleHeight() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002774 try {
2775 return mService.getInputMethodWindowVisibleHeight();
2776 } catch (RemoteException e) {
2777 throw e.rethrowFromSystemServer();
Satoshi Kataoka658c7b82013-10-10 17:03:51 +09002778 }
2779 }
2780
2781 /**
satokd4fce2b2011-04-11 12:07:13 +09002782 * Force switch to the last used input method and subtype. If the last input method didn't have
2783 * any subtypes, the framework will simply switch to the last input method with no subtype
2784 * specified.
2785 * @param imeToken Supplies the identifying token given to an input method when it was started,
2786 * which allows it to perform this operation on itself.
2787 * @return true if the current input method and subtype was successfully switched to the last
2788 * used input method and subtype.
Tarandeep Singh164cfba2018-02-28 14:17:43 -08002789 * @deprecated Use {@link InputMethodService#switchToPreviousInputMethod()} instead. This method
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002790 * was intended for IME developers who should be accessing APIs through the service. APIs in
2791 * this class are intended for app developers interacting with the IME.
satokd4fce2b2011-04-11 12:07:13 +09002792 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002793 @Deprecated
satok735cf382010-11-11 20:40:09 +09002794 public boolean switchToLastInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002795 return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod();
satok735cf382010-11-11 20:40:09 +09002796 }
2797
satoke7c6998e2011-06-03 17:57:59 +09002798 /**
satok688bd472012-02-09 20:09:17 +09002799 * Force switch to the next input method and subtype. If there is no IME enabled except
2800 * current IME and subtype, do nothing.
2801 * @param imeToken Supplies the identifying token given to an input method when it was started,
2802 * which allows it to perform this operation on itself.
2803 * @param onlyCurrentIme if true, the framework will find the next subtype which
2804 * belongs to the current IME
2805 * @return true if the current input method and subtype was successfully switched to the next
2806 * input method and subtype.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002807 * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
2808 * method was intended for IME developers who should be accessing APIs through the service.
2809 * APIs in this class are intended for app developers interacting with the IME.
satok688bd472012-02-09 20:09:17 +09002810 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002811 @Deprecated
satok688bd472012-02-09 20:09:17 +09002812 public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002813 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
2814 .switchToNextInputMethod(onlyCurrentIme);
satok688bd472012-02-09 20:09:17 +09002815 }
2816
2817 /**
satok15ab6b02013-08-26 14:17:18 +09002818 * Returns true if the current IME needs to offer the users ways to switch to a next input
2819 * method (e.g. a globe key.).
2820 * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
2821 * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
2822 * <p> Note that the system determines the most appropriate next input method
2823 * and subtype in order to provide the consistent user experience in switching
2824 * between IMEs and subtypes.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002825 * @param imeToken Supplies the identifying token given to an input method when it was started,
2826 * which allows it to perform this operation on itself.
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002827 * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
2828 * instead. This method was intended for IME developers who should be accessing APIs through
2829 * the service. APIs in this class are intended for app developers interacting with the IME.
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002830 */
Tarandeep Singhd8d03a82017-11-28 13:35:32 -08002831 @Deprecated
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002832 public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
Yohei Yukawad746a7e2018-09-18 18:55:02 -07002833 return InputMethodPrivilegedOperationsRegistry.get(imeToken)
2834 .shouldOfferSwitchingToNextInputMethod();
Satoshi Kataoka2b10b522013-08-21 20:39:12 +09002835 }
2836
2837 /**
satok91e88122011-07-18 11:11:42 +09002838 * Set additional input method subtypes. Only a process which shares the same uid with the IME
2839 * can add additional input method subtypes to the IME.
satok75917b62011-08-31 23:27:39 +09002840 * Please note that a subtype's status is stored in the system.
2841 * For example, enabled subtypes are remembered by the framework even after they are removed
2842 * by using this method. If you re-add the same subtypes again,
2843 * they will just get enabled. If you want to avoid such conflicts, for instance, you may
2844 * want to create a "different" new subtype even with the same locale and mode,
2845 * by changing its extra value. The different subtype won't get affected by the stored past
2846 * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
2847 * to the current implementation.)
Yohei Yukawa70f5c482016-01-04 19:42:36 -08002848 *
2849 * <p>NOTE: If the same subtype exists in both the manifest XML file and additional subtypes
2850 * specified by {@code subtypes}, those multiple instances are automatically merged into one
2851 * instance.</p>
2852 *
2853 * <p>CAVEAT: In API Level 23 and prior, the system may do nothing if an empty
2854 * {@link InputMethodSubtype} is specified in {@code subtypes}, which prevents you from removing
2855 * the last one entry of additional subtypes. If your IME statically defines one or more
2856 * subtypes in the manifest XML file, you may be able to work around this limitation by
2857 * specifying one of those statically defined subtypes in {@code subtypes}.</p>
2858 *
satok91e88122011-07-18 11:11:42 +09002859 * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
satoke7c6998e2011-06-03 17:57:59 +09002860 * @param subtypes subtypes will be added as additional subtypes of the current input method.
Yohei Yukawa92c15b12019-01-22 13:26:45 -08002861 * @deprecated For IMEs that have already implemented features like customizable/downloadable
2862 * keyboard layouts/languages, please start migration to other approaches. One idea
2863 * would be exposing only one unified {@link InputMethodSubtype} then implement
2864 * IME's own language switching mechanism within that unified subtype. The support
2865 * of "Additional Subtype" may be completely dropped in a future version of Android.
satoke7c6998e2011-06-03 17:57:59 +09002866 */
Yohei Yukawa92c15b12019-01-22 13:26:45 -08002867 @Deprecated
satokee5e77c2011-09-02 18:50:15 +09002868 public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002869 try {
2870 mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
2871 } catch (RemoteException e) {
2872 throw e.rethrowFromSystemServer();
satoke7c6998e2011-06-03 17:57:59 +09002873 }
2874 }
2875
satok68f1b782011-04-11 14:26:04 +09002876 public InputMethodSubtype getLastInputMethodSubtype() {
Yohei Yukawa83b7d722018-09-09 20:48:25 -07002877 try {
2878 return mService.getLastInputMethodSubtype();
2879 } catch (RemoteException e) {
2880 throw e.rethrowFromSystemServer();
satok68f1b782011-04-11 14:26:04 +09002881 }
2882 }
2883
Tarandeep Singh2cbcd7f2019-01-25 11:47:57 -08002884 private void maybeCallServedViewChangedLocked(EditorInfo tba) {
2885 if (mImeInsetsConsumer != null) {
2886 mImeInsetsConsumer.onServedEditorChanged(tba);
2887 }
2888 }
2889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
2891 final Printer p = new PrintWriterPrinter(fout);
2892 p.println("Input method client state for " + this + ":");
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -07002893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 p.println(" mService=" + mService);
2895 p.println(" mMainLooper=" + mMainLooper);
2896 p.println(" mIInputContext=" + mIInputContext);
2897 p.println(" mActive=" + mActive
Yohei Yukawa2553e482017-12-15 15:47:33 -08002898 + " mRestartOnNextWindowFocus=" + mRestartOnNextWindowFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 + " mBindSequence=" + mBindSequence
2900 + " mCurId=" + mCurId);
Yohei Yukawa2bc66172017-02-08 11:13:25 -08002901 p.println(" mFullscreenMode=" + mFullscreenMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 p.println(" mCurMethod=" + mCurMethod);
Wale Ogunwale159c3d82015-05-14 12:20:53 -07002903 p.println(" mCurRootView=" + mCurRootView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 p.println(" mServedView=" + mServedView);
Dianne Hackborn7663d802012-02-24 13:08:49 -08002905 p.println(" mNextServedView=" + mNextServedView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 p.println(" mServedConnecting=" + mServedConnecting);
2907 if (mCurrentTextBoxAttribute != null) {
2908 p.println(" mCurrentTextBoxAttribute:");
2909 mCurrentTextBoxAttribute.dump(p, " ");
2910 } else {
2911 p.println(" mCurrentTextBoxAttribute: null");
2912 }
Yohei Yukawaaaa38c92016-03-27 23:46:04 -07002913 p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
Andreas Gampee6748ce2015-12-11 18:00:38 -08002914 p.println(" mCompletions=" + Arrays.toString(mCompletions));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 p.println(" mCursorRect=" + mCursorRect);
2916 p.println(" mCursorSelStart=" + mCursorSelStart
2917 + " mCursorSelEnd=" + mCursorSelEnd
2918 + " mCursorCandStart=" + mCursorCandStart
2919 + " mCursorCandEnd=" + mCursorCandEnd);
2920 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002921
2922 /**
2923 * Callback that is invoked when an input event that was dispatched to
2924 * the IME has been finished.
2925 * @hide
2926 */
Jeff Brownf9e989d2013-04-04 23:04:03 -07002927 public interface FinishedInputEventCallback {
2928 public void onFinishedInputEvent(Object token, boolean handled);
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002929 }
2930
Jeff Brownc28867a2013-03-26 15:42:39 -07002931 private final class ImeInputEventSender extends InputEventSender {
2932 public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
2933 super(inputChannel, looper);
2934 }
2935
2936 @Override
2937 public void onInputEventFinished(int seq, boolean handled) {
Jeff Brownf9e989d2013-04-04 23:04:03 -07002938 finishedInputEvent(seq, handled, false);
Jeff Brownc28867a2013-03-26 15:42:39 -07002939 }
2940 }
2941
Jeff Brownf9e989d2013-04-04 23:04:03 -07002942 private final class PendingEvent implements Runnable {
2943 public InputEvent mEvent;
2944 public Object mToken;
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002945 public String mInputMethodId;
Jeff Brownf9e989d2013-04-04 23:04:03 -07002946 public FinishedInputEventCallback mCallback;
2947 public Handler mHandler;
2948 public boolean mHandled;
2949
2950 public void recycle() {
2951 mEvent = null;
2952 mToken = null;
2953 mInputMethodId = null;
2954 mCallback = null;
2955 mHandler = null;
2956 mHandled = false;
2957 }
2958
2959 @Override
2960 public void run() {
2961 mCallback.onFinishedInputEvent(mToken, mHandled);
2962
2963 synchronized (mH) {
2964 recyclePendingEventLocked(this);
2965 }
2966 }
Jeff Brown04ddf3c2012-06-14 03:57:49 -07002967 }
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07002968
2969 private static String dumpViewInfo(@Nullable final View view) {
2970 if (view == null) {
2971 return "null";
2972 }
2973 final StringBuilder sb = new StringBuilder();
2974 sb.append(view);
2975 sb.append(",focus=" + view.hasFocus());
2976 sb.append(",windowFocus=" + view.hasWindowFocus());
Dake Guddf6c1e2018-05-10 11:41:19 -07002977 sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07002978 sb.append(",window=" + view.getWindowToken());
Yohei Yukawa4052a10f2018-10-15 15:35:55 +08002979 sb.append(",displayId=" + view.getContext().getDisplayId());
Yohei Yukawaa4ed0cf2016-03-29 19:06:36 -07002980 sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
Yohei Yukawa5c1e6752016-03-28 01:52:47 -07002981 return sb.toString();
2982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983}