Index: base/android/java/src/org/chromium/base/SystemMessageHandler.java |
diff --git a/base/android/java/src/org/chromium/base/SystemMessageHandler.java b/base/android/java/src/org/chromium/base/SystemMessageHandler.java |
index e1fbb0f4bed9538212313fdb374e81f0ac37f414..ea0d5683aaac99aae8c20e73eb1b1394a7b0303d 100644 |
--- a/base/android/java/src/org/chromium/base/SystemMessageHandler.java |
+++ b/base/android/java/src/org/chromium/base/SystemMessageHandler.java |
@@ -6,18 +6,42 @@ package org.chromium.base; |
import android.os.Handler; |
import android.os.Message; |
+import android.util.Log; |
+ |
+import java.lang.reflect.Method; |
class SystemMessageHandler extends Handler { |
+ private static final String TAG = "SystemMessageHandler"; |
+ |
private static final int SCHEDULED_WORK = 1; |
private static final int DELAYED_SCHEDULED_WORK = 2; |
+ // Reflected API for marking a message as asynchronous. This is a workaround |
+ // to provide *fair* Chromium task dispatch when served by the Android UI |
+ // thread's Looper, avoiding stalls when the Looper has a sync barrier. |
+ // Note: Use of this API is experimental and demonstrative, and is likely |
+ // to be removed in the near future. |
+ private Method mMessageMethodSetAsynchonous; |
+ |
// Native class pointer set by the constructor of the SharedClient native class. |
private long mMessagePumpDelegateNative = 0; |
private long mDelayedScheduledTimeTicks = 0; |
private SystemMessageHandler(long messagePumpDelegateNative) { |
mMessagePumpDelegateNative = messagePumpDelegateNative; |
+ |
+ try { |
+ Class<?> messageClass = Class.forName("android.os.Message"); |
+ mMessageMethodSetAsynchonous = messageClass.getMethod( |
+ "setAsynchronous", new Class[]{boolean.class}); |
+ } catch (ClassNotFoundException e) { |
+ Log.e(TAG, "Failed to find android.os.Message class:" + e); |
+ } catch (NoSuchMethodException e) { |
+ Log.e(TAG, "Failed to load Message.setAsynchronous method:" + e); |
+ } catch (Exception e) { |
nyquist
2014/08/28 23:27:27
Why is this not catching RuntimeException?
jdduke (slow)
2014/08/28 23:37:03
Is there anything to gain from catching that in ad
jdduke (slow)
2014/08/28 23:54:41
N/m, I have seen the error of my ways, done!
|
+ Log.e(TAG, "Exception while loading Message.setAsynchronous method: " + e); |
+ } |
} |
@Override |
@@ -31,7 +55,7 @@ class SystemMessageHandler extends Handler { |
@SuppressWarnings("unused") |
@CalledByNative |
private void scheduleWork() { |
- sendEmptyMessage(SCHEDULED_WORK); |
+ sendMessage(obtainAsyncMessage(SCHEDULED_WORK)); |
} |
@SuppressWarnings("unused") |
@@ -41,7 +65,7 @@ class SystemMessageHandler extends Handler { |
removeMessages(DELAYED_SCHEDULED_WORK); |
} |
mDelayedScheduledTimeTicks = delayedTimeTicks; |
- sendEmptyMessageDelayed(DELAYED_SCHEDULED_WORK, millis); |
+ sendMessageDelayed(obtainAsyncMessage(DELAYED_SCHEDULED_WORK), millis); |
} |
@SuppressWarnings("unused") |
@@ -51,6 +75,22 @@ class SystemMessageHandler extends Handler { |
removeMessages(DELAYED_SCHEDULED_WORK); |
} |
+ private Message obtainAsyncMessage(int what) { |
+ Message msg = Message.obtain(); |
+ msg.what = what; |
+ if (mMessageMethodSetAsynchonous != null) { |
+ try { |
+ mMessageMethodSetAsynchonous.invoke(msg, true); |
+ } catch (Exception e) { |
nyquist
2014/08/28 23:27:27
Why is this not catching IllegalAccessException, I
jdduke (slow)
2014/08/28 23:37:03
In practice, I'm not sure that we care, and I don'
jdduke (slow)
2014/08/28 23:54:41
Ditto above.
|
+ Log.e(TAG, "Exception marking message as asynchronous: " + e); |
+ // Assume that any failure is indicative of future failures, and |
+ // avoid log spam by nulling the reflected method. |
+ mMessageMethodSetAsynchonous = null; |
+ } |
+ } |
+ return msg; |
+ } |
+ |
@CalledByNative |
private static SystemMessageHandler create(long messagePumpDelegateNative) { |
return new SystemMessageHandler(messagePumpDelegateNative); |