OLD | NEW |
---|---|
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.util.Log; | |
10 | |
11 import java.lang.reflect.Method; | |
9 | 12 |
10 class SystemMessageHandler extends Handler { | 13 class SystemMessageHandler extends Handler { |
11 | 14 |
15 private static final String TAG = "SystemMessageHandler"; | |
16 | |
12 private static final int SCHEDULED_WORK = 1; | 17 private static final int SCHEDULED_WORK = 1; |
13 private static final int DELAYED_SCHEDULED_WORK = 2; | 18 private static final int DELAYED_SCHEDULED_WORK = 2; |
14 | 19 |
20 // Reflected API for marking a message as asynchronous. This is a workaround | |
21 // to provide *fair* Chromium task dispatch when served by the Android UI | |
22 // thread's Looper, avoiding stalls when the Looper has a sync barrier. | |
23 // Note: Use of this API is experimental and demonstrative, and is likely | |
24 // to be removed in the near future. | |
25 private Method mMessageMethodSetAsynchonous; | |
26 | |
15 // Native class pointer set by the constructor of the SharedClient native cl ass. | 27 // Native class pointer set by the constructor of the SharedClient native cl ass. |
16 private long mMessagePumpDelegateNative = 0; | 28 private long mMessagePumpDelegateNative = 0; |
17 private long mDelayedScheduledTimeTicks = 0; | 29 private long mDelayedScheduledTimeTicks = 0; |
18 | 30 |
19 private SystemMessageHandler(long messagePumpDelegateNative) { | 31 private SystemMessageHandler(long messagePumpDelegateNative) { |
20 mMessagePumpDelegateNative = messagePumpDelegateNative; | 32 mMessagePumpDelegateNative = messagePumpDelegateNative; |
33 | |
34 try { | |
35 Class<?> messageClass = Class.forName("android.os.Message"); | |
36 mMessageMethodSetAsynchonous = messageClass.getMethod( | |
37 "setAsynchronous", new Class[]{boolean.class}); | |
38 } catch (ClassNotFoundException e) { | |
39 Log.e(TAG, "Failed to find android.os.Message class:" + e); | |
40 } catch (NoSuchMethodException e) { | |
41 Log.e(TAG, "Failed to load Message.setAsynchronous method:" + e); | |
42 } 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!
| |
43 Log.e(TAG, "Exception while loading Message.setAsynchronous method: " + e); | |
44 } | |
21 } | 45 } |
22 | 46 |
23 @Override | 47 @Override |
24 public void handleMessage(Message msg) { | 48 public void handleMessage(Message msg) { |
25 if (msg.what == DELAYED_SCHEDULED_WORK) { | 49 if (msg.what == DELAYED_SCHEDULED_WORK) { |
26 mDelayedScheduledTimeTicks = 0; | 50 mDelayedScheduledTimeTicks = 0; |
27 } | 51 } |
28 nativeDoRunLoopOnce(mMessagePumpDelegateNative, mDelayedScheduledTimeTic ks); | 52 nativeDoRunLoopOnce(mMessagePumpDelegateNative, mDelayedScheduledTimeTic ks); |
29 } | 53 } |
30 | 54 |
31 @SuppressWarnings("unused") | 55 @SuppressWarnings("unused") |
32 @CalledByNative | 56 @CalledByNative |
33 private void scheduleWork() { | 57 private void scheduleWork() { |
34 sendEmptyMessage(SCHEDULED_WORK); | 58 sendMessage(obtainAsyncMessage(SCHEDULED_WORK)); |
35 } | 59 } |
36 | 60 |
37 @SuppressWarnings("unused") | 61 @SuppressWarnings("unused") |
38 @CalledByNative | 62 @CalledByNative |
39 private void scheduleDelayedWork(long delayedTimeTicks, long millis) { | 63 private void scheduleDelayedWork(long delayedTimeTicks, long millis) { |
40 if (mDelayedScheduledTimeTicks != 0) { | 64 if (mDelayedScheduledTimeTicks != 0) { |
41 removeMessages(DELAYED_SCHEDULED_WORK); | 65 removeMessages(DELAYED_SCHEDULED_WORK); |
42 } | 66 } |
43 mDelayedScheduledTimeTicks = delayedTimeTicks; | 67 mDelayedScheduledTimeTicks = delayedTimeTicks; |
44 sendEmptyMessageDelayed(DELAYED_SCHEDULED_WORK, millis); | 68 sendMessageDelayed(obtainAsyncMessage(DELAYED_SCHEDULED_WORK), millis); |
45 } | 69 } |
46 | 70 |
47 @SuppressWarnings("unused") | 71 @SuppressWarnings("unused") |
48 @CalledByNative | 72 @CalledByNative |
49 private void removeAllPendingMessages() { | 73 private void removeAllPendingMessages() { |
50 removeMessages(SCHEDULED_WORK); | 74 removeMessages(SCHEDULED_WORK); |
51 removeMessages(DELAYED_SCHEDULED_WORK); | 75 removeMessages(DELAYED_SCHEDULED_WORK); |
52 } | 76 } |
53 | 77 |
78 private Message obtainAsyncMessage(int what) { | |
79 Message msg = Message.obtain(); | |
80 msg.what = what; | |
81 if (mMessageMethodSetAsynchonous != null) { | |
82 try { | |
83 mMessageMethodSetAsynchonous.invoke(msg, true); | |
84 } 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.
| |
85 Log.e(TAG, "Exception marking message as asynchronous: " + e); | |
86 // Assume that any failure is indicative of future failures, and | |
87 // avoid log spam by nulling the reflected method. | |
88 mMessageMethodSetAsynchonous = null; | |
89 } | |
90 } | |
91 return msg; | |
92 } | |
93 | |
54 @CalledByNative | 94 @CalledByNative |
55 private static SystemMessageHandler create(long messagePumpDelegateNative) { | 95 private static SystemMessageHandler create(long messagePumpDelegateNative) { |
56 return new SystemMessageHandler(messagePumpDelegateNative); | 96 return new SystemMessageHandler(messagePumpDelegateNative); |
57 } | 97 } |
58 | 98 |
59 private native void nativeDoRunLoopOnce( | 99 private native void nativeDoRunLoopOnce( |
60 long messagePumpDelegateNative, long delayedScheduledTimeTicks); | 100 long messagePumpDelegateNative, long delayedScheduledTimeTicks); |
61 } | 101 } |
OLD | NEW |