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

Side by Side Diff: base/android/java/src/org/chromium/base/SystemMessageHandler.java

Issue 575103002: [Android] Experimental sync barrier detection for tracing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updates Created 6 years, 3 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.base; 5 package org.chromium.base;
6 6
7 import android.os.Handler; 7 import android.os.Handler;
8 import android.os.Message; 8 import android.os.Message;
9 import android.os.MessageQueue;
10 import android.util.Log;
11
12 import java.lang.reflect.Field;
13 import java.lang.reflect.InvocationTargetException;
14 import java.lang.reflect.Method;
9 15
10 class SystemMessageHandler extends Handler { 16 class SystemMessageHandler extends Handler {
11 17
18 private static final String TAG = "SystemMessageHandler";
19
12 private static final int SCHEDULED_WORK = 1; 20 private static final int SCHEDULED_WORK = 1;
13 private static final int DELAYED_SCHEDULED_WORK = 2; 21 private static final int DELAYED_SCHEDULED_WORK = 2;
14 22
15 // Native class pointer set by the constructor of the SharedClient native cl ass. 23 // Native class pointer set by the constructor of the SharedClient native cl ass.
16 private long mMessagePumpDelegateNative = 0; 24 private long mMessagePumpDelegateNative = 0;
17 private long mDelayedScheduledTimeTicks = 0; 25 private long mDelayedScheduledTimeTicks = 0;
18 26
27 // The following members are used to detect and trace the presence of sync
28 // barriers in Android's MessageQueue. Note that this detection is
29 // experimental, temporary and intended only for diagnostic purposes.
30 private MessageQueue mMessageQueue;
31 private Field mMessageQueueMessageField;
32 private Field mMessageTargetField;
33 private boolean mQueueHasSyncBarrier;
34 private long mSyncBarrierTraceId;
35
19 private SystemMessageHandler(long messagePumpDelegateNative) { 36 private SystemMessageHandler(long messagePumpDelegateNative) {
20 mMessagePumpDelegateNative = messagePumpDelegateNative; 37 mMessagePumpDelegateNative = messagePumpDelegateNative;
21 } 38 tryEnableSyncBarrierDetection();
39 }
22 40
23 @Override 41 @Override
24 public void handleMessage(Message msg) { 42 public void handleMessage(Message msg) {
43 updateWhetherQueueHasBlockingSyncBarrier();
25 if (msg.what == DELAYED_SCHEDULED_WORK) { 44 if (msg.what == DELAYED_SCHEDULED_WORK) {
26 mDelayedScheduledTimeTicks = 0; 45 mDelayedScheduledTimeTicks = 0;
27 } 46 }
28 nativeDoRunLoopOnce(mMessagePumpDelegateNative, mDelayedScheduledTimeTic ks); 47 nativeDoRunLoopOnce(mMessagePumpDelegateNative, mDelayedScheduledTimeTic ks);
29 } 48 }
30 49
31 @SuppressWarnings("unused") 50 @SuppressWarnings("unused")
32 @CalledByNative 51 @CalledByNative
33 private void scheduleWork() { 52 private void scheduleWork() {
53 updateWhetherQueueHasBlockingSyncBarrier();
54 if (mQueueHasSyncBarrier) TraceEvent.instant("SystemMessageHandler:immed iateWorkBlocked");
34 sendEmptyMessage(SCHEDULED_WORK); 55 sendEmptyMessage(SCHEDULED_WORK);
35 } 56 }
36 57
37 @SuppressWarnings("unused") 58 @SuppressWarnings("unused")
38 @CalledByNative 59 @CalledByNative
39 private void scheduleDelayedWork(long delayedTimeTicks, long millis) { 60 private void scheduleDelayedWork(long delayedTimeTicks, long millis) {
40 if (mDelayedScheduledTimeTicks != 0) { 61 if (mDelayedScheduledTimeTicks != 0) {
41 removeMessages(DELAYED_SCHEDULED_WORK); 62 removeMessages(DELAYED_SCHEDULED_WORK);
42 } 63 }
43 mDelayedScheduledTimeTicks = delayedTimeTicks; 64 mDelayedScheduledTimeTicks = delayedTimeTicks;
65 updateWhetherQueueHasBlockingSyncBarrier();
66 if (mQueueHasSyncBarrier) TraceEvent.instant("SystemMessageHandler:delay edWorkBlocked");
44 sendEmptyMessageDelayed(DELAYED_SCHEDULED_WORK, millis); 67 sendEmptyMessageDelayed(DELAYED_SCHEDULED_WORK, millis);
45 } 68 }
46 69
47 @SuppressWarnings("unused") 70 @SuppressWarnings("unused")
48 @CalledByNative 71 @CalledByNative
49 private void removeAllPendingMessages() { 72 private void removeAllPendingMessages() {
73 updateWhetherQueueHasBlockingSyncBarrier();
50 removeMessages(SCHEDULED_WORK); 74 removeMessages(SCHEDULED_WORK);
51 removeMessages(DELAYED_SCHEDULED_WORK); 75 removeMessages(DELAYED_SCHEDULED_WORK);
52 } 76 }
53 77
78 private void updateWhetherQueueHasBlockingSyncBarrier() {
79 if (mMessageQueue == null) return;
80 // As barrier detection is only used for tracing, early out when tracing
81 // is disabled to avoid any potential performance penalties.
82 if (!TraceEvent.enabled()) {
83 mQueueHasSyncBarrier = false;
84 return;
85 }
86 final Message queueHead = (Message)getField(mMessageQueue, mMessageQueue MessageField);
nyquist 2014/09/23 00:08:39 These final qualifiers are unnecessary I believe.
jdduke (slow) 2014/09/23 16:20:46 Done.
87 final boolean queueHasSyncbarrier = isSyncBarrierMessage(queueHead);
nyquist 2014/09/23 00:08:38 queueHasSyncBarrier
jdduke (slow) 2014/09/23 16:20:46 Done.
88 setQueueHasSyncBarrier(queueHasSyncbarrier);
89 }
90
91 private boolean isSyncBarrierMessage(Message message) {
92 if (message == null) return false;
93 // Sync barrier messages have null targets.
94 return getField(message, mMessageTargetField) == null;
95 }
96
97 private void tryEnableSyncBarrierDetection() {
98 assert mMessageQueue == null;
99
100 boolean success = false;
101 try {
102 Class<?> looperClass = Class.forName("android.os.Looper");
103 Method getQueueMethod = looperClass.getMethod("getQueue", new Class[ ]{});
104 mMessageQueue = (MessageQueue)(getQueueMethod.invoke(getLooper()));
nyquist 2014/09/23 00:08:38 Just (MessageQueue) getQueueMethod.invoke(getLoope
jdduke (slow) 2014/09/23 16:20:46 Done.
105
106 mMessageQueueMessageField = mMessageQueue.getClass().getDeclaredFiel d("mMessages");
107 mMessageQueueMessageField.setAccessible(true);
108
109 mMessageTargetField = new Message().getClass().getDeclaredField("tar get");
nyquist 2014/09/23 00:08:38 Could this just be Message.class.getDeclaredField(
jdduke (slow) 2014/09/23 16:20:46 Done.
110 mMessageTargetField.setAccessible(true);
111
112 mSyncBarrierTraceId = hashCode();
113
114 success = true;
115 } catch (ClassNotFoundException e) {
116 Log.e(TAG, "Failed to find class: " + e);
117 } catch (NoSuchMethodException e) {
118 Log.e(TAG, "Failed to load method: " + e);
119 } catch (NoSuchFieldException e) {
120 Log.e(TAG, "Failed to load field: " + e);
121 } catch (InvocationTargetException e) {
122 Log.e(TAG, "Failed invocation: " + e);
123 } catch (IllegalAccessException e) {
124 Log.e(TAG, "Illegal access to reflected invocation: " + e);
125 } catch (RuntimeException e) {
nyquist 2014/09/23 00:08:39 This is masking IllegalArgumentException thrown by
jdduke (slow) 2014/09/23 16:20:46 Not intentional, good catch.
126 Log.e(TAG, e.toString());
127 } finally {
128 if (!success) disableSyncBarrierDetection();
129 }
130 }
131
132 private void disableSyncBarrierDetection() {
133 Log.e(TAG, "Unexpected error with sync barrier detection, disabling.");
134 mMessageQueue = null;
135 mMessageQueueMessageField = null;
136 mMessageTargetField = null;
137 setQueueHasSyncBarrier(false);
138 }
139
140 private void setQueueHasSyncBarrier(boolean queueHasSyncbarrier) {
nyquist 2014/09/23 00:08:39 queueHasSyncBarrier
jdduke (slow) 2014/09/23 16:20:46 Done.
141 if (queueHasSyncbarrier == mQueueHasSyncBarrier) return;
142 mQueueHasSyncBarrier = queueHasSyncbarrier;
143 if (mQueueHasSyncBarrier) {
144 TraceEvent.startAsync("SyncBarrier", mSyncBarrierTraceId);
145 } else {
146 TraceEvent.finishAsync("SyncBarrier", mSyncBarrierTraceId);
147 }
148 }
149
150 private Object getField(Object object, Field field) {
151 try {
152 return field.get(object);
153 } catch (IllegalAccessException e) {
154 Log.e(TAG, "Failed field access: " + e);
155 disableSyncBarrierDetection();
156 }
157 return null;
158 }
159
54 @CalledByNative 160 @CalledByNative
55 private static SystemMessageHandler create(long messagePumpDelegateNative) { 161 private static SystemMessageHandler create(long messagePumpDelegateNative) {
56 return new SystemMessageHandler(messagePumpDelegateNative); 162 return new SystemMessageHandler(messagePumpDelegateNative);
57 } 163 }
58 164
59 private native void nativeDoRunLoopOnce( 165 private native void nativeDoRunLoopOnce(
60 long messagePumpDelegateNative, long delayedScheduledTimeTicks); 166 long messagePumpDelegateNative, long delayedScheduledTimeTicks);
61 } 167 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698