Fix issue #2166755: BroadcastReceiver trying to return result during a non-ordered broadcast

Tell the broadcast receiver whether it is getting an initial sticky value,
so it will be quiet about attempts to do ordered broadcast stuff.

Note that the original bug being reported was not actually a crash, just
an error log.  So all we are doing here is making the log quieter.

Change-Id: Iaf1b718d82093ec1197142410a64feff47eb3859
This commit is contained in:
Dianne Hackborn
2009-10-05 13:58:17 -07:00
parent 71060f2985
commit 68d881cf2d
12 changed files with 92 additions and 29 deletions

View File

@ -27787,6 +27787,28 @@
<parameter name="makeMap" type="boolean">
</parameter>
</method>
<method name="isInitialStickyBroadcast"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="true"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="isOrderedBroadcast"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="true"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="onReceive"
return="void"
abstract="true"

View File

@ -340,7 +340,8 @@ public class Am {
private boolean mFinished = false;
public synchronized void performReceive(
Intent intent, int rc, String data, Bundle ext, boolean ord) {
Intent intent, int rc, String data, Bundle ext, boolean ord,
boolean sticky) {
String line = "Broadcast completed: result=" + rc;
if (data != null) line = line + ", data=\"" + data + "\"";
if (ext != null) line = line + ", extras: " + ext;

View File

@ -653,7 +653,7 @@ public final class ActivityThread {
mStrongRef = strong ? rd : null;
}
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered) {
String data, Bundle extras, boolean ordered, boolean sticky) {
ReceiverDispatcher rd = mDispatcher.get();
if (DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
@ -661,7 +661,8 @@ public final class ActivityThread {
+ " to " + rd);
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras, ordered);
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky);
}
}
}
@ -681,6 +682,7 @@ public final class ActivityThread {
private String mCurData;
private Bundle mCurMap;
private boolean mCurOrdered;
private boolean mCurSticky;
public void run() {
BroadcastReceiver receiver = mReceiver;
@ -706,6 +708,7 @@ public final class ActivityThread {
receiver.setResult(mCurCode, mCurData, mCurMap);
receiver.clearAbortBroadcast();
receiver.setOrderedHint(mCurOrdered);
receiver.setInitialStickyHint(mCurSticky);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && mCurOrdered) {
@ -788,7 +791,7 @@ public final class ActivityThread {
}
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered) {
String data, Bundle extras, boolean ordered, boolean sticky) {
if (DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
@ -800,6 +803,7 @@ public final class ActivityThread {
args.mCurData = data;
args.mCurMap = extras;
args.mCurOrdered = ordered;
args.mCurSticky = sticky;
if (!mActivityThread.post(args)) {
if (mRegistered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
@ -1515,9 +1519,9 @@ public final class ActivityThread {
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered)
throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky) throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
}
public void scheduleLowMemory() {

View File

@ -317,8 +317,9 @@ public abstract class ApplicationThreadNative extends Binder
String dataStr = data.readString();
Bundle extras = data.readBundle();
boolean ordered = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
scheduleRegisteredReceiver(receiver, intent,
resultCode, dataStr, extras, ordered);
resultCode, dataStr, extras, ordered, sticky);
return true;
}
@ -716,7 +717,7 @@ class ApplicationThreadProxy implements IApplicationThread {
}
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered)
int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@ -726,6 +727,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeString(dataStr);
data.writeBundle(extras);
data.writeInt(ordered ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();

View File

@ -91,7 +91,7 @@ public interface IApplicationThread extends IInterface {
void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
throws RemoteException;
void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String data, Bundle extras, boolean ordered)
int resultCode, String data, Bundle extras, boolean ordered, boolean sticky)
throws RemoteException;
void scheduleLowMemory() throws RemoteException;
void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;

View File

@ -147,7 +147,7 @@ public final class PendingIntent implements Parcelable {
mHandler = handler;
}
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean serialized) {
String data, Bundle extras, boolean serialized, boolean sticky) {
mIntent = intent;
mResultCode = resultCode;
mResultData = data;

View File

@ -383,6 +383,24 @@ public abstract class BroadcastReceiver {
mAbortBroadcast = false;
}
/**
* Returns true if the receiver is currently processing an ordered
* broadcast.
*/
public final boolean isOrderedBroadcast() {
return mOrderedHint;
}
/**
* Returns true if the receiver is currently processing the initial
* value of a sticky broadcast -- that is, the value that was last
* broadcast and is currently held in the sticky cache, so this is
* not directly the result of a broadcast right now.
*/
public final boolean isInitialStickyBroadcast() {
return mInitialStickyHint;
}
/**
* For internal use, sets the hint about whether this BroadcastReceiver is
* running in ordered mode.
@ -391,6 +409,14 @@ public abstract class BroadcastReceiver {
mOrderedHint = isOrdered;
}
/**
* For internal use, sets the hint about whether this BroadcastReceiver is
* receiving the initial sticky broadcast value. @hide
*/
public final void setInitialStickyHint(boolean isInitialSticky) {
mInitialStickyHint = isInitialSticky;
}
/**
* Control inclusion of debugging help for mismatched
* calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
@ -414,7 +440,10 @@ public abstract class BroadcastReceiver {
}
void checkSynchronousHint() {
if (mOrderedHint) {
// Note that we don't assert when receiving the initial sticky value,
// since that may have come from an ordered broadcast. We'll catch
// them later when the real broadcast happens again.
if (mOrderedHint || mInitialStickyHint) {
return;
}
RuntimeException e = new RuntimeException(
@ -429,5 +458,6 @@ public abstract class BroadcastReceiver {
private boolean mAbortBroadcast;
private boolean mDebugUnregister;
private boolean mOrderedHint;
private boolean mInitialStickyHint;
}

View File

@ -28,6 +28,6 @@ import android.os.Bundle;
*/
oneway interface IIntentReceiver {
void performReceive(in Intent intent, int resultCode,
String data, in Bundle extras, boolean ordered);
String data, in Bundle extras, boolean ordered, boolean sticky);
}

View File

@ -113,7 +113,7 @@ public class IntentSender implements Parcelable {
mHandler = handler;
}
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean serialized) {
String data, Bundle extras, boolean serialized, boolean sticky) {
mIntent = intent;
mResultCode = resultCode;
mResultData = data;

View File

@ -8389,7 +8389,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (i == 0) {
finisher = new IIntentReceiver.Stub() {
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered)
String data, Bundle extras, boolean ordered,
boolean sticky)
throws RemoteException {
synchronized (ActivityManagerService.this) {
mDidUpdate = true;
@ -11571,7 +11572,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
Intent intent = (Intent)allSticky.get(i);
BroadcastRecord r = new BroadcastRecord(intent, null,
null, -1, -1, null, receivers, null, 0, null, null,
false);
false, true);
if (mParallelBroadcasts.size() == 0) {
scheduleBroadcastsLocked();
}
@ -11796,7 +11797,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered);
ordered, false);
if (DEBUG_BROADCAST) Log.v(
TAG, "Enqueueing parallel broadcast " + r
+ ": prev had " + mParallelBroadcasts.size());
@ -11875,7 +11876,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|| resultTo != null) {
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
receivers, resultTo, resultCode, resultData, map, ordered);
receivers, resultTo, resultCode, resultData, map, ordered, false);
if (DEBUG_BROADCAST) Log.v(
TAG, "Enqueueing ordered broadcast " + r
+ ": prev had " + mOrderedBroadcasts.size());
@ -12179,15 +12180,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data,
Bundle extras, boolean ordered) throws RemoteException {
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky) throws RemoteException {
if (app != null && app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered);
data, extras, ordered, sticky);
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered);
receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
}
}
@ -12251,7 +12252,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
performReceive(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, r.ordered);
r.resultData, r.resultExtras, r.ordered, r.sticky);
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
@ -12384,7 +12385,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
performReceive(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, false);
r.resultData, r.resultExtras, false, false);
} catch (RemoteException e) {
Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
}

View File

@ -39,7 +39,9 @@ class BroadcastRecord extends Binder {
final String callerPackage; // who sent this
final int callingPid; // the pid of who sent this
final int callingUid; // the uid of who sent this
String requiredPermission; // a permission the caller has required
final boolean ordered; // serialize the send to receivers?
final boolean sticky; // originated from existing sticky data?
final String requiredPermission; // a permission the caller has required
final List receivers; // contains BroadcastFilter and ResolveInfo
final IIntentReceiver resultTo; // who receives final result if non-null
long dispatchTime; // when dispatch started on this set of receivers
@ -48,7 +50,6 @@ class BroadcastRecord extends Binder {
String resultData; // current result data value.
Bundle resultExtras; // current result extra data values.
boolean resultAbort; // current result abortBroadcast value.
boolean ordered; // serialize the send to receivers?
int nextReceiver; // next receiver to be executed.
IBinder receiver; // who is currently running, null if none.
int state;
@ -86,7 +87,7 @@ class BroadcastRecord extends Binder {
+ " resultCode=" + resultCode + " resultData=" + resultData);
pw.println(prefix + "resultExtras=" + resultExtras);
pw.println(prefix + "resultAbort=" + resultAbort
+ " ordered=" + ordered);
+ " ordered=" + ordered + " sticky=" + sticky);
pw.println(prefix + "nextReceiver=" + nextReceiver
+ " receiver=" + receiver);
pw.println(prefix + "curFilter=" + curFilter);
@ -122,7 +123,8 @@ class BroadcastRecord extends Binder {
BroadcastRecord(Intent _intent, ProcessRecord _callerApp, String _callerPackage,
int _callingPid, int _callingUid, String _requiredPermission,
List _receivers, IIntentReceiver _resultTo, int _resultCode,
String _resultData, Bundle _resultExtras, boolean _serialized) {
String _resultData, Bundle _resultExtras, boolean _serialized,
boolean _sticky) {
intent = _intent;
callerApp = _callerApp;
callerPackage = _callerPackage;
@ -135,6 +137,7 @@ class BroadcastRecord extends Binder {
resultData = _resultData;
resultExtras = _resultExtras;
ordered = _serialized;
sticky = _sticky;
nextReceiver = 0;
state = IDLE;
}

View File

@ -248,7 +248,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
if (sendFinish) {
try {
finishedReceiver.performReceive(new Intent(finalIntent), 0,
null, null, false);
null, null, false, false);
} catch (RemoteException e) {
}
}