Skip to content

Commit caa8e69

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Fix issue #5756204: Crespo IME briefly appears shortened when..." into ics-mr1
2 parents 19636dc + 33b8ee5 commit caa8e69

File tree

2 files changed

+124
-86
lines changed

2 files changed

+124
-86
lines changed

core/java/android/service/textservice/SpellCheckerService.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.content.Intent;
2525
import android.os.Bundle;
2626
import android.os.IBinder;
27+
import android.os.Process;
2728
import android.os.RemoteException;
2829
import android.util.Log;
2930
import android.view.textservice.SuggestionsInfo;
@@ -187,23 +188,39 @@ public InternalISpellCheckerSession(String locale, ISpellCheckerSessionListener
187188
@Override
188189
public void onGetSuggestionsMultiple(
189190
TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
191+
int pri = Process.getThreadPriority(Process.myTid());
190192
try {
193+
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
191194
mListener.onGetSuggestions(
192195
mSession.onGetSuggestionsMultiple(
193196
textInfos, suggestionsLimit, sequentialWords));
194197
} catch (RemoteException e) {
198+
} finally {
199+
Process.setThreadPriority(pri);
195200
}
196201
}
197202

198203
@Override
199204
public void onCancel() {
200-
mSession.onCancel();
205+
int pri = Process.getThreadPriority(Process.myTid());
206+
try {
207+
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
208+
mSession.onCancel();
209+
} finally {
210+
Process.setThreadPriority(pri);
211+
}
201212
}
202213

203214
@Override
204215
public void onClose() {
205-
mSession.onClose();
206-
mListener = null;
216+
int pri = Process.getThreadPriority(Process.myTid());
217+
try {
218+
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
219+
mSession.onClose();
220+
} finally {
221+
Process.setThreadPriority(pri);
222+
mListener = null;
223+
}
207224
}
208225

209226
public String getLocale() {

core/java/android/view/textservice/SpellCheckerSession.java

Lines changed: 104 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
import com.android.internal.textservice.ITextServicesManager;
2222
import com.android.internal.textservice.ITextServicesSessionListener;
2323

24+
import android.os.Binder;
2425
import android.os.Handler;
26+
import android.os.HandlerThread;
2527
import android.os.Message;
28+
import android.os.Process;
2629
import android.os.RemoteException;
2730
import android.util.Log;
2831
import android.view.textservice.SpellCheckerInfo;
@@ -205,6 +208,8 @@ private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessio
205208

206209
private boolean mOpened;
207210
private ISpellCheckerSession mISpellCheckerSession;
211+
private HandlerThread mThread;
212+
private Handler mAsyncHandler;
208213

209214
public SpellCheckerSessionListenerImpl(Handler handler) {
210215
mOpened = false;
@@ -216,6 +221,7 @@ private static class SpellCheckerParams {
216221
public final TextInfo[] mTextInfos;
217222
public final int mSuggestionsLimit;
218223
public final boolean mSequentialWords;
224+
public ISpellCheckerSession mSession;
219225
public SpellCheckerParams(int what, TextInfo[] textInfos, int suggestionsLimit,
220226
boolean sequentialWords) {
221227
mWhat = what;
@@ -225,27 +231,86 @@ public SpellCheckerParams(int what, TextInfo[] textInfos, int suggestionsLimit,
225231
}
226232
}
227233

228-
private void processTask(SpellCheckerParams scp) {
229-
switch (scp.mWhat) {
230-
case TASK_CANCEL:
231-
processCancel();
232-
break;
233-
case TASK_GET_SUGGESTIONS_MULTIPLE:
234-
processGetSuggestionsMultiple(scp);
235-
break;
236-
case TASK_CLOSE:
237-
processClose();
238-
break;
234+
private void processTask(ISpellCheckerSession session, SpellCheckerParams scp,
235+
boolean async) {
236+
if (async || mAsyncHandler == null) {
237+
switch (scp.mWhat) {
238+
case TASK_CANCEL:
239+
if (DBG) {
240+
Log.w(TAG, "Cancel spell checker tasks.");
241+
}
242+
try {
243+
session.onCancel();
244+
} catch (RemoteException e) {
245+
Log.e(TAG, "Failed to cancel " + e);
246+
}
247+
break;
248+
case TASK_GET_SUGGESTIONS_MULTIPLE:
249+
if (DBG) {
250+
Log.w(TAG, "Get suggestions from the spell checker.");
251+
}
252+
try {
253+
session.onGetSuggestionsMultiple(scp.mTextInfos,
254+
scp.mSuggestionsLimit, scp.mSequentialWords);
255+
} catch (RemoteException e) {
256+
Log.e(TAG, "Failed to get suggestions " + e);
257+
}
258+
break;
259+
case TASK_CLOSE:
260+
if (DBG) {
261+
Log.w(TAG, "Close spell checker tasks.");
262+
}
263+
try {
264+
session.onClose();
265+
} catch (RemoteException e) {
266+
Log.e(TAG, "Failed to close " + e);
267+
}
268+
break;
269+
}
270+
} else {
271+
// The interface is to a local object, so need to execute it
272+
// asynchronously.
273+
scp.mSession = session;
274+
mAsyncHandler.sendMessage(Message.obtain(mAsyncHandler, 1, scp));
275+
}
276+
277+
if (scp.mWhat == TASK_CLOSE) {
278+
// If we are closing, we want to clean up our state now even
279+
// if it is pending as an async operation.
280+
synchronized (this) {
281+
mISpellCheckerSession = null;
282+
mHandler = null;
283+
if (mThread != null) {
284+
mThread.quit();
285+
}
286+
mThread = null;
287+
mAsyncHandler = null;
288+
}
239289
}
240290
}
241291

242292
public synchronized void onServiceConnected(ISpellCheckerSession session) {
243-
mISpellCheckerSession = session;
244-
mOpened = true;
293+
synchronized (this) {
294+
mISpellCheckerSession = session;
295+
if (session.asBinder() instanceof Binder && mThread == null) {
296+
// If this is a local object, we need to do our own threading
297+
// to make sure we handle it asynchronously.
298+
mThread = new HandlerThread("SpellCheckerSession",
299+
Process.THREAD_PRIORITY_BACKGROUND);
300+
mThread.start();
301+
mAsyncHandler = new Handler(mThread.getLooper()) {
302+
@Override public void handleMessage(Message msg) {
303+
SpellCheckerParams scp = (SpellCheckerParams)msg.obj;
304+
processTask(scp.mSession, scp, true);
305+
}
306+
};
307+
}
308+
mOpened = true;
309+
}
245310
if (DBG)
246311
Log.d(TAG, "onServiceConnected - Success");
247312
while (!mPendingTasks.isEmpty()) {
248-
processTask(mPendingTasks.poll());
313+
processTask(session, mPendingTasks.poll(), false);
249314
}
250315
}
251316

@@ -277,87 +342,43 @@ public boolean isDisconnected() {
277342
return mOpened && mISpellCheckerSession == null;
278343
}
279344

280-
public boolean checkOpenConnection() {
281-
if (mISpellCheckerSession != null) {
282-
return true;
283-
}
284-
Log.e(TAG, "not connected to the spellchecker service.");
285-
return false;
286-
}
287-
288345
private void processOrEnqueueTask(SpellCheckerParams scp) {
289346
if (DBG) {
290347
Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession);
291348
}
292-
SpellCheckerParams closeTask = null;
293-
if (mISpellCheckerSession == null) {
294-
if (scp.mWhat == TASK_CANCEL) {
295-
while (!mPendingTasks.isEmpty()) {
296-
final SpellCheckerParams tmp = mPendingTasks.poll();
297-
if (tmp.mWhat == TASK_CLOSE) {
298-
// Only one close task should be processed, while we need to remove all
299-
// close tasks from the queue
300-
closeTask = tmp;
349+
ISpellCheckerSession session;
350+
synchronized (this) {
351+
session = mISpellCheckerSession;
352+
if (session == null) {
353+
SpellCheckerParams closeTask = null;
354+
if (scp.mWhat == TASK_CANCEL) {
355+
while (!mPendingTasks.isEmpty()) {
356+
final SpellCheckerParams tmp = mPendingTasks.poll();
357+
if (tmp.mWhat == TASK_CLOSE) {
358+
// Only one close task should be processed, while we need to remove all
359+
// close tasks from the queue
360+
closeTask = tmp;
361+
}
301362
}
302363
}
364+
mPendingTasks.offer(scp);
365+
if (closeTask != null) {
366+
mPendingTasks.offer(closeTask);
367+
}
368+
return;
303369
}
304-
mPendingTasks.offer(scp);
305-
if (closeTask != null) {
306-
mPendingTasks.offer(closeTask);
307-
}
308-
} else {
309-
processTask(scp);
310-
}
311-
}
312-
313-
private void processCancel() {
314-
if (!checkOpenConnection()) {
315-
return;
316-
}
317-
if (DBG) {
318-
Log.w(TAG, "Cancel spell checker tasks.");
319-
}
320-
try {
321-
mISpellCheckerSession.onCancel();
322-
} catch (RemoteException e) {
323-
Log.e(TAG, "Failed to cancel " + e);
324-
}
325-
}
326-
327-
private void processClose() {
328-
if (!checkOpenConnection()) {
329-
return;
330-
}
331-
if (DBG) {
332-
Log.w(TAG, "Close spell checker tasks.");
333-
}
334-
try {
335-
mISpellCheckerSession.onClose();
336-
mISpellCheckerSession = null;
337-
mHandler = null;
338-
} catch (RemoteException e) {
339-
Log.e(TAG, "Failed to close " + e);
340-
}
341-
}
342-
343-
private void processGetSuggestionsMultiple(SpellCheckerParams scp) {
344-
if (!checkOpenConnection()) {
345-
return;
346-
}
347-
if (DBG) {
348-
Log.w(TAG, "Get suggestions from the spell checker.");
349-
}
350-
try {
351-
mISpellCheckerSession.onGetSuggestionsMultiple(
352-
scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords);
353-
} catch (RemoteException e) {
354-
Log.e(TAG, "Failed to get suggestions " + e);
355370
}
371+
processTask(session, scp, false);
356372
}
357373

358374
@Override
359375
public void onGetSuggestions(SuggestionsInfo[] results) {
360-
mHandler.sendMessage(Message.obtain(mHandler, MSG_ON_GET_SUGGESTION_MULTIPLE, results));
376+
synchronized (this) {
377+
if (mHandler != null) {
378+
mHandler.sendMessage(Message.obtain(mHandler,
379+
MSG_ON_GET_SUGGESTION_MULTIPLE, results));
380+
}
381+
}
361382
}
362383
}
363384

0 commit comments

Comments
 (0)