Bug 1307816 - 9. Fix IC thread switching after async refactoring; r=esawin

When switching the IC thread from one thread to another, we can no
longer block on the old IC thread waiting for the Gecko thread. However,
we still block on the new IC thread, waiting for the old IC thread to
finish processing any old events.
This commit is contained in:
Jim Chen 2016-10-25 12:28:53 -04:00
Родитель 34ec3f2d7d
Коммит 5e0f876ff7
1 изменённых файлов: 25 добавлений и 19 удалений

Просмотреть файл

@ -594,6 +594,7 @@ final class GeckoEditable extends JNIObject
// Post to UI thread first to make sure any code that is using the old input // Post to UI thread first to make sure any code that is using the old input
// connection has finished running, before we switch to a new input connection or // connection has finished running, before we switch to a new input connection or
// before we clear the input connection on destruction. // before we clear the input connection on destruction.
final Handler icHandler = mIcPostHandler;
ThreadUtils.postToUiThread(new Runnable() { ThreadUtils.postToUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -611,7 +612,7 @@ final class GeckoEditable extends JNIObject
} }
mView = v; mView = v;
mIcPostHandler.post(setListenerRunnable); icHandler.post(setListenerRunnable);
} }
}); });
} }
@ -625,6 +626,9 @@ final class GeckoEditable extends JNIObject
} }
private void geckoPostToIc(Runnable runnable) { private void geckoPostToIc(Runnable runnable) {
if (DEBUG) {
ThreadUtils.assertOnGeckoThread();
}
mIcPostHandler.post(runnable); mIcPostHandler.post(runnable);
} }
@ -890,14 +894,15 @@ final class GeckoEditable extends JNIObject
mSuppressKeyUp = suppress; mSuppressKeyUp = suppress;
} }
@Override @Override // GeckoEditableClient
public Handler setInputConnectionHandler(Handler handler) { public Handler setInputConnectionHandler(final Handler handler) {
if (handler == mIcPostHandler || !mFocused) { if (handler == mIcRunHandler) {
return mIcPostHandler; return mIcRunHandler;
} }
if (DEBUG) { if (DEBUG) {
assertOnIcThread(); assertOnIcThread();
} }
// There are three threads at this point: Gecko thread, old IC thread, and new IC // There are three threads at this point: Gecko thread, old IC thread, and new IC
// thread, and we want to safely switch from old IC thread to new IC thread. // thread, and we want to safely switch from old IC thread to new IC thread.
// We first send a TYPE_SET_HANDLER action to the Gecko thread; this ensures that // We first send a TYPE_SET_HANDLER action to the Gecko thread; this ensures that
@ -910,6 +915,21 @@ final class GeckoEditable extends JNIObject
// also post a Runnable to the new IC thread; this Runnable blocks until the // also post a Runnable to the new IC thread; this Runnable blocks until the
// switch is complete; this ensures that the new IC thread won't accept // switch is complete; this ensures that the new IC thread won't accept
// InputConnection calls until after the switch. // InputConnection calls until after the switch.
handler.post(new Runnable() { // Make the new IC thread wait.
@Override
public void run() {
synchronized (handler) {
while (mIcRunHandler != handler) {
try {
handler.wait();
} catch (final InterruptedException e) {
}
}
}
}
});
icOfferAction(Action.newSetHandler(handler)); icOfferAction(Action.newSetHandler(handler));
return handler; return handler;
} }
@ -939,20 +959,6 @@ final class GeckoEditable extends JNIObject
// we don't switch mIcRunHandler yet because there may be pending Runnables on the // we don't switch mIcRunHandler yet because there may be pending Runnables on the
// old IC thread still waiting to run. // old IC thread still waiting to run.
mIcPostHandler = newHandler; mIcPostHandler = newHandler;
geckoPostToIc(new Runnable() { // posting to new IC thread
@Override
public void run() {
synchronized (newHandler) {
while (mIcRunHandler != newHandler) {
try {
newHandler.wait();
} catch (InterruptedException e) {
}
}
}
}
});
} }
private void geckoActionReply(final Action action) { private void geckoActionReply(final Action action) {