Bug 850318 - Avoid blocking the UI thread on the background thread when calling getClipboardText. r=wesj

This commit is contained in:
Kartikaya Gupta 2013-03-22 22:03:17 -04:00
Родитель 30c94d7c71
Коммит 1dbc6eb9d5
2 изменённых файлов: 43 добавлений и 28 удалений

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

@ -1110,41 +1110,51 @@ public class GeckoAppShell
return intent;
}
static SynchronousQueue<String> sClipboardQueue =
new SynchronousQueue<String>();
/* On some devices, access to the clipboard service needs to happen
* on a thread with a looper, so this function requires a looper is
* present on the thread. */
@SuppressWarnings("deprecation")
private static String getClipboardTextImpl() {
Context context = GeckoApp.mAppContext;
if (android.os.Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = (android.content.ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
if (cm.hasPrimaryClip()) {
ClipData clip = cm.getPrimaryClip();
if (clip != null) {
ClipData.Item item = clip.getItemAt(0);
return item.coerceToText(context).toString();
}
}
} else {
android.text.ClipboardManager cm = (android.text.ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
if (cm.hasText()) {
return cm.getText().toString();
}
}
return null;
}
private static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
private static String EMPTY_STRING = new String();
// On some devices, access to the clipboard service needs to happen
// on a thread with a looper, so dispatch this to our looper thread
// Note: the main looper won't work because it may be blocked on the
// gecko thread, which is most likely this thread
static String getClipboardText() {
ThreadUtils.postToBackgroundThread(new Runnable() {
// If we're on the UI thread or the background thread, we have a looper on the thread
// and can just call this directly. For any other threads, post the call to the
// background thread.
if (ThreadUtils.isOnUiThread() || ThreadUtils.isOnBackgroundThread()) {
return getClipboardTextImpl();
}
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
@SuppressWarnings("deprecation")
public void run() {
Context context = GeckoApp.mAppContext;
String text = null;
if (android.os.Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = (android.content.ClipboardManager)
context.getSystemService(Context.CLIPBOARD_SERVICE);
if (cm.hasPrimaryClip()) {
ClipData clip = cm.getPrimaryClip();
if (clip != null) {
ClipData.Item item = clip.getItemAt(0);
text = item.coerceToText(context).toString();
}
}
} else {
android.text.ClipboardManager cm = (android.text.ClipboardManager)
context.getSystemService(Context.CLIPBOARD_SERVICE);
if (cm.hasText())
text = cm.getText().toString();
}
String text = getClipboardTextImpl();
try {
sClipboardQueue.put(text != null ? text : EMPTY_STRING);
} catch (InterruptedException ie) {}
}});
}
});
try {
String ret = sClipboardQueue.take();
return (EMPTY_STRING.equals(ret) ? null : ret);
@ -1167,7 +1177,8 @@ public class GeckoAppShell
context.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setText(text);
}
}});
}
});
}
public static void setNotificationClient(NotificationClient client) {

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

@ -84,6 +84,10 @@ public final class ThreadUtils {
return isOnThread(getUiThread());
}
public static boolean isOnBackgroundThread() {
return isOnThread(sBackgroundThread);
}
public static boolean isOnThread(Thread thread) {
return (Thread.currentThread().getId() == thread.getId());
}