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

Unified Diff: base/android/java/src/org/chromium/base/SystemMessageHandler.java

Issue 723343002: Update from https://crrev.com/304121 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/allocator/BUILD.gn ('k') | base/android/linker/linker_jni.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 10f8d55448e014b8d9717d34197428fbf4bd9200..fd3dc5a08b640fe0d7002bd657d5e9973d127812 100644
--- a/base/android/java/src/org/chromium/base/SystemMessageHandler.java
+++ b/base/android/java/src/org/chromium/base/SystemMessageHandler.java
@@ -5,12 +5,9 @@
package org.chromium.base;
import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
-import android.os.MessageQueue;
import android.util.Log;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -25,23 +22,31 @@ class SystemMessageHandler extends Handler {
private long mMessagePumpDelegateNative = 0;
private long mDelayedScheduledTimeTicks = 0;
- // The following members are used to detect and trace the presence of sync
- // barriers in Android's MessageQueue. Note that this detection is
- // experimental, temporary and intended only for diagnostic purposes.
- private MessageQueue mMessageQueue;
- private Field mMessageQueueMessageField;
- private Field mMessageTargetField;
- private boolean mQueueHasSyncBarrier;
- private long mSyncBarrierTraceId;
+ // 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 likely to evolve in the future.
+ private Method mMessageMethodSetAsynchronous;
private SystemMessageHandler(long messagePumpDelegateNative) {
mMessagePumpDelegateNative = messagePumpDelegateNative;
- tryEnableSyncBarrierDetection();
+
+ try {
+ Class<?> messageClass = Class.forName("android.os.Message");
+ mMessageMethodSetAsynchronous = 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 (RuntimeException e) {
+ Log.e(TAG, "Exception while loading Message.setAsynchronous method: " + e);
+ }
+
}
@Override
public void handleMessage(Message msg) {
- updateWhetherQueueHasBlockingSyncBarrier();
if (msg.what == DELAYED_SCHEDULED_WORK) {
mDelayedScheduledTimeTicks = 0;
}
@@ -51,9 +56,7 @@ class SystemMessageHandler extends Handler {
@SuppressWarnings("unused")
@CalledByNative
private void scheduleWork() {
- updateWhetherQueueHasBlockingSyncBarrier();
- if (mQueueHasSyncBarrier) TraceEvent.instant("SystemMessageHandler:immediateWorkBlocked");
- sendEmptyMessage(SCHEDULED_WORK);
+ sendMessage(obtainAsyncMessage(SCHEDULED_WORK));
}
@SuppressWarnings("unused")
@@ -63,97 +66,39 @@ class SystemMessageHandler extends Handler {
removeMessages(DELAYED_SCHEDULED_WORK);
}
mDelayedScheduledTimeTicks = delayedTimeTicks;
- updateWhetherQueueHasBlockingSyncBarrier();
- if (mQueueHasSyncBarrier) TraceEvent.instant("SystemMessageHandler:delayedWorkBlocked");
- sendEmptyMessageDelayed(DELAYED_SCHEDULED_WORK, millis);
+ sendMessageDelayed(obtainAsyncMessage(DELAYED_SCHEDULED_WORK), millis);
}
@SuppressWarnings("unused")
@CalledByNative
private void removeAllPendingMessages() {
- updateWhetherQueueHasBlockingSyncBarrier();
removeMessages(SCHEDULED_WORK);
removeMessages(DELAYED_SCHEDULED_WORK);
}
- private void updateWhetherQueueHasBlockingSyncBarrier() {
- if (mMessageQueue == null) return;
- // As barrier detection is only used for tracing, early out when tracing
- // is disabled to avoid any potential performance penalties.
- if (!TraceEvent.enabled()) {
- mQueueHasSyncBarrier = false;
- return;
- }
- Message queueHead = (Message) getField(mMessageQueue, mMessageQueueMessageField);
- setqueueHasSyncBarrier(isSyncBarrierMessage(queueHead));
- }
-
- private boolean isSyncBarrierMessage(Message message) {
- if (message == null) return false;
- // Sync barrier messages have null targets.
- return getField(message, mMessageTargetField) == null;
- }
-
- private void tryEnableSyncBarrierDetection() {
- assert mMessageQueue == null;
-
- boolean success = false;
- try {
- Method getQueueMethod = Looper.class.getMethod("getQueue", new Class[]{});
- mMessageQueue = (MessageQueue) getQueueMethod.invoke(getLooper());
-
- mMessageQueueMessageField = mMessageQueue.getClass().getDeclaredField("mMessages");
- mMessageQueueMessageField.setAccessible(true);
-
- mMessageTargetField = Message.class.getDeclaredField("target");
- mMessageTargetField.setAccessible(true);
-
- mSyncBarrierTraceId = hashCode();
-
- success = true;
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "Failed to load method: " + e);
- } catch (NoSuchFieldException e) {
- Log.e(TAG, "Failed to load field: " + e);
- } catch (InvocationTargetException e) {
- Log.e(TAG, "Failed invocation: " + e);
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Illegal access to reflected invocation: " + e);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Illegal argument to reflected invocation: " + e);
- } catch (RuntimeException e) {
- Log.e(TAG, e.toString());
- } finally {
- if (!success) disableSyncBarrierDetection();
- }
- }
-
- private void disableSyncBarrierDetection() {
- Log.e(TAG, "Unexpected error with sync barrier detection, disabling.");
- mMessageQueue = null;
- mMessageQueueMessageField = null;
- mMessageTargetField = null;
- setqueueHasSyncBarrier(false);
- }
-
- private void setqueueHasSyncBarrier(boolean queueHasSyncBarrier) {
- if (queueHasSyncBarrier == mQueueHasSyncBarrier) return;
- mQueueHasSyncBarrier = queueHasSyncBarrier;
- if (mQueueHasSyncBarrier) {
- TraceEvent.startAsync("SyncBarrier", mSyncBarrierTraceId);
- } else {
- TraceEvent.finishAsync("SyncBarrier", mSyncBarrierTraceId);
- }
- }
-
- private Object getField(Object object, Field field) {
- try {
- return field.get(object);
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Failed field access: " + e);
- disableSyncBarrierDetection();
+ private Message obtainAsyncMessage(int what) {
+ Message msg = Message.obtain();
+ msg.what = what;
+ if (mMessageMethodSetAsynchronous != null) {
+ // If invocation fails, assume this is indicative of future
+ // failures, and avoid log spam by nulling the reflected method.
+ try {
+ mMessageMethodSetAsynchronous.invoke(msg, true);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Illegal access to asynchronous message creation, disabling.");
+ mMessageMethodSetAsynchronous = null;
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Illegal argument for asynchronous message creation, disabling.");
+ mMessageMethodSetAsynchronous = null;
+ } catch (InvocationTargetException e) {
+ Log.e(TAG, "Invocation exception during asynchronous message creation, disabling.");
+ mMessageMethodSetAsynchronous = null;
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Runtime exception during asynchronous message creation, disabling.");
+ mMessageMethodSetAsynchronous = null;
+ }
}
- return null;
+ return msg;
}
@CalledByNative
« no previous file with comments | « base/allocator/BUILD.gn ('k') | base/android/linker/linker_jni.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698