Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(238)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java

Issue 1278593004: Introduce ThreadedInputConnection behind a switch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove fallback mechanism and crash instead Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.content.browser.input;
6
7 import android.os.Handler;
8 import android.os.HandlerThread;
9 import android.view.View;
10 import android.view.inputmethod.EditorInfo;
11
12 import org.chromium.base.Log;
13 import org.chromium.base.VisibleForTesting;
14
15 /**
16 * A factory class for {@link ThreadedInputConnection}. The class also includes triggering
17 * mechanism (hack) to run our InputConnection on non-UI thread.
18 */
19 // TODO(changwan): add unit tests once Robolectric supports Android API level >= 21.
20 // See crbug.com/588547 for details.
21 public class ThreadedInputConnectionFactory implements ChromiumBaseInputConnecti on.Factory {
22 private static final String TAG = "cr_Ime";
23 private static final boolean DEBUG_LOGS = false;
24
25 private final Handler mHandler;
26 private final InputMethodManagerWrapper mInputMethodManagerWrapper;
27 private final InputMethodUma mInputMethodUma;
28 private ThreadedInputConnectionProxyView mProxyView;
29 private ThreadedInputConnection mThreadedInputConnection;
30
31 ThreadedInputConnectionFactory(
32 InputMethodManagerWrapper inputMethodManagerWrapper) {
33 mInputMethodManagerWrapper = inputMethodManagerWrapper;
34 mHandler = createHandler();
35 mInputMethodUma = createInputMethodUma();
36 }
37
38 @VisibleForTesting
39 protected Handler createHandler() {
40 HandlerThread thread =
41 new HandlerThread("InputConnectionHandlerThread", HandlerThread. NORM_PRIORITY);
42 thread.start();
43 return new Handler(thread.getLooper());
44 }
45
46 @VisibleForTesting
47 protected ThreadedInputConnectionProxyView createProxyView(
48 Handler handler, View containerView) {
49 return new ThreadedInputConnectionProxyView(
50 containerView.getContext(), handler, containerView);
51 }
52
53 @VisibleForTesting
54 protected InputMethodUma createInputMethodUma() {
55 return new InputMethodUma();
56 }
57
58 private boolean shouldTriggerDelayedOnCreateInputConnection() {
59 for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
60 String className = ste.getClassName();
61 if (className != null
62 && (className.contains(ThreadedInputConnectionProxyView.clas s.getName())
63 || className.contains("TestInputMethodManagerWrapper"))) {
64 return false;
65 }
66 }
67 return true;
68 }
69
70 @Override
71 public ThreadedInputConnection initializeAndGet(
72 View view, ImeAdapter imeAdapter, int inputType, int inputFlags, int selectionStart,
73 int selectionEnd, EditorInfo outAttrs) {
74 ImeUtils.checkOnUiThread();
75 if (shouldTriggerDelayedOnCreateInputConnection()) {
76 triggerDelayedOnCreateInputConnection(view);
77 return null;
78 }
79 if (DEBUG_LOGS) Log.w(TAG, "initializeAndGet: called from proxy view");
80 if (mThreadedInputConnection == null) {
81 if (DEBUG_LOGS) Log.w(TAG, "Creating ThreadedInputConnection...");
82 mThreadedInputConnection = new ThreadedInputConnection(imeAdapter, m Handler);
83 }
84 mThreadedInputConnection.initializeOutAttrsOnUiThread(inputType, inputFl ags,
85 selectionStart, selectionEnd, outAttrs);
86 return mThreadedInputConnection;
87 }
88
89 private void triggerDelayedOnCreateInputConnection(final View view) {
90 if (DEBUG_LOGS) Log.w(TAG, "triggerDelayedOnCreateInputConnection");
91 if (mProxyView == null) {
92 mProxyView = createProxyView(mHandler, view);
93 }
94 mProxyView.requestFocus();
95 view.getHandler().post(new Runnable() {
96 @Override
97 public void run() {
98 // This is a hack to make InputMethodManager believe that the pr oxy view
99 // now has a focus. As a result, InputMethodManager will think t hat mProxyView
100 // is focused, and will call getHandler() of the view when creat ing input
101 // connection.
102
103 // Step 1: Set mProxyView as InputMethodManager#mNextServedView.
104 mProxyView.onWindowFocusChanged(true);
105
106 // Step 2: Have InputMethodManager focus in on mNextServedView.
107 // As a result, IMM will call onCreateInputConnection() on mProx yView on the same
108 // thread as mProxyView.getHandler(). It will also call subseque nt InputConnection
109 // methods on this IME thread.
110 mInputMethodManagerWrapper.isActive(view);
111
112 // Step 3: Check that the above hack worked.
113 mHandler.post(new Runnable() {
114 @Override
115 public void run() {
116 // Some other view already took focus. Container view sh ould be active
117 // otherwise regardless of whether proxy view is registe red or not.
118 if (!mInputMethodManagerWrapper.isActive(view)) return;
119
120 // Success.
121 if (mInputMethodManagerWrapper.isActive(mProxyView)) {
122 mInputMethodUma.recordProxyViewSuccess();
123 return;
124 }
125
126 if (mThreadedInputConnection == null) {
127 // First time and failed. It is highly likely that t his does not work
128 // systematically.
129 mInputMethodUma.recordProxyViewFailure();
130 onRegisterProxyViewFailed();
131 } else {
132 // Most likely that we already lost view focus.
133 mInputMethodUma.recordProxyViewDetectionFailure();
134 }
135 }
136 });
137 }
138 });
139 }
140
141 @VisibleForTesting
142 protected void onRegisterProxyViewFailed() {
143 throw new AssertionError("Failed to register proxy view");
144 }
145
146 @Override
147 public Handler getHandler() {
148 return mHandler;
149 }
150 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698