I am reading this page about how to program Android to talk to a USB accessory. One of the steps involves registering a BroadcastReceiver
to obtain permission from the user:
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
where mUsbReceiver
is defined as:
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(accessory != null){
//call method to set up accessory communication
}
}
else {
Log.d(TAG, "permission denied for accessory " + accessory);
}
}
}
}
};
What puzzles me is why synchronized (this)
is used? onReceive()
will be called on the UI thread and that's it. This block of code does not seem to touch any data which may be accessed by other threads, unless the object accessory
counts (and there's nothing on the page that suggests it is).
I searched on the web, and there does not seem to be much emphasis on thread-safety in onReceive()
(it's called by a very specific thread after all). Am I missing something?
Update: I want to stress that I know what synchronized (this)
does, because some comments below seem to suggest I don't. What I don't understand is why it was used in the above code fragment, which seems unnecessary.
onReceive()
will not always be called on a UI thread. If BroadcastReceiver
is registered using an overload of registerReceiver()
which accepts a Handler scheduler
param, then onReceive()
callback will be executed on a thread, that handler has been attached to. From docs:
Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
Register to receive intent broadcasts, to run in the context of scheduler. scheduler is a handler identifying the thread that will receive the
Intent
. If null, the main thread of the process will be used.
Nevertheless, particularly in the case outlined in the docs there is no need to wrap any code into a synchronized
block, because the BroadcastReceiver
is registered using standard registerReceiver(BroadcastReceiver, IntentFilter)
overload, which is guarantees to fire onReceive()
callback on UI thread.
I think that's merely a showcase code, that demonstrates how to correctly write an onReceive()
implementation, taking care of all the edge cases. If the author of that doc hadn't written synchronized
block I wouldn't know, that it's possible to make onReceive()
to be executed on a thread other than UI thread.