summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2009-10-05 13:58:17 -0700
committerDianne Hackborn <hackbod@google.com>2009-10-05 15:52:32 -0700
commit68d881cf2d2b252f6f795cd64d43e316a1d736e5 (patch)
tree3d0f7cb91e612df7a5663ceefec0b5439c907642
parent71060f29855745893c122e8b93cf7a723186931b (diff)
downloadframeworks_base-68d881cf2d2b252f6f795cd64d43e316a1d736e5.zip
frameworks_base-68d881cf2d2b252f6f795cd64d43e316a1d736e5.tar.gz
frameworks_base-68d881cf2d2b252f6f795cd64d43e316a1d736e5.tar.bz2
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
-rw-r--r--api/current.xml22
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java3
-rw-r--r--core/java/android/app/ActivityThread.java16
-rw-r--r--core/java/android/app/ApplicationThreadNative.java6
-rw-r--r--core/java/android/app/IApplicationThread.java2
-rw-r--r--core/java/android/app/PendingIntent.java2
-rw-r--r--core/java/android/content/BroadcastReceiver.java32
-rwxr-xr-xcore/java/android/content/IIntentReceiver.aidl2
-rw-r--r--core/java/android/content/IntentSender.java2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java21
-rw-r--r--services/java/com/android/server/am/BroadcastRecord.java11
-rw-r--r--services/java/com/android/server/am/PendingIntentRecord.java2
12 files changed, 92 insertions, 29 deletions
diff --git a/api/current.xml b/api/current.xml
index e764fa5..9b0ea3a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -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"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 0b4f25e..eca5af9 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -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;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b4ac159..2cd223f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -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() {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 928981d..a772a8f 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -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();
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 8dda898..89a52fd 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -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;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 18d9b92..be1dc4a 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -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;
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index b391c57..b63d026 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -384,6 +384,24 @@ public abstract class BroadcastReceiver {
}
/**
+ * 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.
*/
@@ -392,6 +410,14 @@ public abstract class BroadcastReceiver {
}
/**
+ * 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)
* Context.registerReceiver()}.
@@ -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;
}
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
index 443db2d..6f2f7c4 100755
--- a/core/java/android/content/IIntentReceiver.aidl
+++ b/core/java/android/content/IIntentReceiver.aidl
@@ -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);
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index c8f7aa9..e182021 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -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;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index cd39d0d..34302b1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -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);
}
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index da55049..db0a6cb 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -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;
}
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index a753d05..b3086d5 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -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) {
}
}