Skip to content

Commit a2910d0

Browse files
author
Jeff Brown
committed
Make it easier to create asynchronous Handlers.
There are potentially very many Handlers owned by services that should not be blocked by barriers introduced by UI traversals occurring on the same thread (if that ever happens). Add some convenience constructors to make it easy to switch these Handlers over to being async. Bug: 7057752 Change-Id: I64d9bffe81e7c52ada4cfad4e89d4340153f4688
1 parent ba94170 commit a2910d0

File tree

7 files changed

+84
-48
lines changed

7 files changed

+84
-48
lines changed

core/java/android/os/Handler.java

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -101,37 +101,88 @@ public void dispatchMessage(Message msg) {
101101
}
102102

103103
/**
104-
* Default constructor associates this handler with the queue for the
104+
* Default constructor associates this handler with the {@link Looper} for the
105105
* current thread.
106106
*
107-
* If there isn't one, this handler won't be able to receive messages.
107+
* If this thread does not have a looper, this handler won't be able to receive messages
108+
* so an exception is thrown.
108109
*/
109110
public Handler() {
110-
if (FIND_POTENTIAL_LEAKS) {
111-
final Class<? extends Handler> klass = getClass();
112-
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
113-
(klass.getModifiers() & Modifier.STATIC) == 0) {
114-
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
115-
klass.getCanonicalName());
116-
}
117-
}
118-
119-
mLooper = Looper.myLooper();
120-
if (mLooper == null) {
121-
throw new RuntimeException(
122-
"Can't create handler inside thread that has not called Looper.prepare()");
123-
}
124-
mQueue = mLooper.mQueue;
125-
mCallback = null;
126-
mAsynchronous = false;
111+
this(null, false);
127112
}
128113

129114
/**
130-
* Constructor associates this handler with the queue for the
115+
* Constructor associates this handler with the {@link Looper} for the
131116
* current thread and takes a callback interface in which you can handle
132117
* messages.
118+
*
119+
* If this thread does not have a looper, this handler won't be able to receive messages
120+
* so an exception is thrown.
121+
*
122+
* @param callback The callback interface in which to handle messages, or null.
133123
*/
134124
public Handler(Callback callback) {
125+
this(callback, false);
126+
}
127+
128+
/**
129+
* Use the provided {@link Looper} instead of the default one.
130+
*
131+
* @param looper The looper, must not be null.
132+
*/
133+
public Handler(Looper looper) {
134+
this(looper, null, false);
135+
}
136+
137+
/**
138+
* Use the provided {@link Looper} instead of the default one and take a callback
139+
* interface in which to handle messages.
140+
*
141+
* @param looper The looper, must not be null.
142+
* @param callback The callback interface in which to handle messages, or null.
143+
*/
144+
public Handler(Looper looper, Callback callback) {
145+
this(looper, callback, false);
146+
}
147+
148+
/**
149+
* Use the {@link Looper} for the current thread
150+
* and set whether the handler should be asynchronous.
151+
*
152+
* Handlers are synchronous by default unless this constructor is used to make
153+
* one that is strictly asynchronous.
154+
*
155+
* Asynchronous messages represent interrupts or events that do not require global ordering
156+
* with represent to synchronous messages. Asynchronous messages are not subject to
157+
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
158+
*
159+
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
160+
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
161+
*
162+
* @hide
163+
*/
164+
public Handler(boolean async) {
165+
this(null, async);
166+
}
167+
168+
/**
169+
* Use the {@link Looper} for the current thread with the specified callback interface
170+
* and set whether the handler should be asynchronous.
171+
*
172+
* Handlers are synchronous by default unless this constructor is used to make
173+
* one that is strictly asynchronous.
174+
*
175+
* Asynchronous messages represent interrupts or events that do not require global ordering
176+
* with represent to synchronous messages. Asynchronous messages are not subject to
177+
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
178+
*
179+
* @param callback The callback interface in which to handle messages, or null.
180+
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
181+
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
182+
*
183+
* @hide
184+
*/
185+
public Handler(Callback callback, boolean async) {
135186
if (FIND_POTENTIAL_LEAKS) {
136187
final Class<? extends Handler> klass = getClass();
137188
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
@@ -148,32 +199,11 @@ public Handler(Callback callback) {
148199
}
149200
mQueue = mLooper.mQueue;
150201
mCallback = callback;
151-
mAsynchronous = false;
152-
}
153-
154-
/**
155-
* Use the provided queue instead of the default one.
156-
*/
157-
public Handler(Looper looper) {
158-
mLooper = looper;
159-
mQueue = looper.mQueue;
160-
mCallback = null;
161-
mAsynchronous = false;
162-
}
163-
164-
/**
165-
* Use the provided queue instead of the default one and take a callback
166-
* interface in which to handle messages.
167-
*/
168-
public Handler(Looper looper, Callback callback) {
169-
mLooper = looper;
170-
mQueue = looper.mQueue;
171-
mCallback = callback;
172-
mAsynchronous = false;
202+
mAsynchronous = async;
173203
}
174204

175205
/**
176-
* Use the provided queue instead of the default one and take a callback
206+
* Use the provided {@link Looper} instead of the default one and take a callback
177207
* interface in which to handle messages. Also set whether the handler
178208
* should be asynchronous.
179209
*
@@ -184,6 +214,8 @@ public Handler(Looper looper, Callback callback) {
184214
* with represent to synchronous messages. Asynchronous messages are not subject to
185215
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
186216
*
217+
* @param looper The looper, must not be null.
218+
* @param callback The callback interface in which to handle messages, or null.
187219
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
188220
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
189221
*

policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ public void keyguardDoneDrawing() {
971971
* interacts with the keyguard ui should be posted to this handler, rather
972972
* than called directly.
973973
*/
974-
private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
974+
private Handler mHandler = new Handler(true /*async*/) {
975975
@Override
976976
public void handleMessage(Message msg) {
977977
switch (msg.what) {

services/java/com/android/server/DockObserver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ private static boolean isScreenSaverActivatedOnDock(Context context) {
241241
SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK) != 0;
242242
}
243243

244-
private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
244+
private final Handler mHandler = new Handler(true /*async*/) {
245245
@Override
246246
public void handleMessage(Message msg) {
247247
switch (msg.what) {

services/java/com/android/server/input/InputManagerService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,10 @@ public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
14381438
* Private handler for the input manager.
14391439
*/
14401440
private final class InputManagerHandler extends Handler {
1441+
public InputManagerHandler() {
1442+
super(true /*async*/);
1443+
}
1444+
14411445
@Override
14421446
public void handleMessage(Message msg) {
14431447
switch (msg.what) {

services/java/com/android/server/power/DisplayPowerController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ public interface Callbacks {
11121112

11131113
private final class DisplayControllerHandler extends Handler {
11141114
public DisplayControllerHandler(Looper looper) {
1115-
super(looper);
1115+
super(looper, null, true /*async*/);
11161116
}
11171117

11181118
@Override

services/java/com/android/server/power/Notifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ public void onReceive(Context context, Intent intent) {
422422

423423
private final class NotifierHandler extends Handler {
424424
public NotifierHandler(Looper looper) {
425-
super(looper);
425+
super(looper, null, true /*async*/);
426426
}
427427

428428
@Override

services/java/com/android/server/power/PowerManagerService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1952,7 +1952,7 @@ public void onScreenOn() {
19521952
*/
19531953
private final class PowerManagerHandler extends Handler {
19541954
public PowerManagerHandler(Looper looper) {
1955-
super(looper);
1955+
super(looper, null, true /*async*/);
19561956
}
19571957

19581958
@Override

0 commit comments

Comments
 (0)