Merge "Fix waitForBroadcastIdle()"

This commit is contained in:
TreeHugger Robot
2019-02-14 01:15:35 +00:00
committed by Android (Google) Code Review
3 changed files with 84 additions and 15 deletions

View File

@@ -18100,8 +18100,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!queue.isIdle()) {
final String msg = "Waiting for queue " + queue + " to become idle...";
pw.println(msg);
pw.println(queue.describeState());
pw.flush();
Slog.v(TAG, msg);
queue.cancelDeferrals();
idle = false;
}
}

View File

@@ -65,6 +65,14 @@ public class BroadcastDispatcher {
broadcasts.add(br);
}
int size() {
return broadcasts.size();
}
boolean isEmpty() {
return broadcasts.isEmpty();
}
void writeToProto(ProtoOutputStream proto, long fieldId) {
for (BroadcastRecord br : broadcasts) {
br.writeToProto(proto, fieldId);
@@ -252,22 +260,48 @@ public class BroadcastDispatcher {
synchronized (mLock) {
return mCurrentBroadcast == null
&& mOrderedBroadcasts.isEmpty()
&& mDeferredBroadcasts.isEmpty()
&& mAlarmBroadcasts.isEmpty();
&& isDeferralsListEmpty(mDeferredBroadcasts)
&& isDeferralsListEmpty(mAlarmBroadcasts);
}
}
/**
* Not quite the traditional size() measurement; includes any in-process but
* not yet retired active outbound broadcast.
*/
public int totalUndelivered() {
synchronized (mLock) {
return mAlarmBroadcasts.size()
+ mDeferredBroadcasts.size()
+ mOrderedBroadcasts.size()
+ (mCurrentBroadcast == null ? 0 : 1);
private static int pendingInDeferralsList(ArrayList<Deferrals> list) {
int pending = 0;
final int numEntries = list.size();
for (int i = 0; i < numEntries; i++) {
pending += list.get(i).size();
}
return pending;
}
private static boolean isDeferralsListEmpty(ArrayList<Deferrals> list) {
return pendingInDeferralsList(list) == 0;
}
/**
* Strictly for logging, describe the currently pending contents in a human-
* readable way
*/
public String describeStateLocked() {
final StringBuilder sb = new StringBuilder(128);
if (mCurrentBroadcast != null) {
sb.append("1 in flight, ");
}
sb.append(mOrderedBroadcasts.size());
sb.append(" ordered");
int n = pendingInDeferralsList(mAlarmBroadcasts);
if (n > 0) {
sb.append(", ");
sb.append(n);
sb.append(" deferrals in alarm recipients");
}
n = pendingInDeferralsList(mDeferredBroadcasts);
if (n > 0) {
sb.append(", ");
sb.append(n);
sb.append(" deferred");
}
return sb.toString();
}
// ----------------------------------
@@ -579,6 +613,26 @@ public class BroadcastDispatcher {
}
}
/**
* Cancel all current deferrals; that is, make all currently-deferred broadcasts
* immediately deliverable. Used by the wait-for-broadcast-idle mechanism.
*/
public void cancelDeferrals() {
synchronized (mLock) {
zeroDeferralTimes(mAlarmBroadcasts);
zeroDeferralTimes(mDeferredBroadcasts);
}
}
private static void zeroDeferralTimes(ArrayList<Deferrals> list) {
final int num = list.size();
for (int i = 0; i < num; i++) {
Deferrals d = list.get(i);
// Safe to do this in-place because it won't break ordering
d.deferUntil = d.deferredBy = 0;
}
}
// ----------------------------------
/**

View File

@@ -928,8 +928,8 @@ public final class BroadcastQueue {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
+ mQueueName + "]: "
+ mParallelBroadcasts.size() + " parallel broadcasts, "
+ mDispatcher.totalUndelivered() + " ordered broadcasts");
+ mParallelBroadcasts.size() + " parallel broadcasts; "
+ mDispatcher.describeStateLocked());
mService.updateCpuStats();
@@ -1827,11 +1827,24 @@ public final class BroadcastQueue {
record.intent == null ? "" : record.intent.getAction());
}
final boolean isIdle() {
boolean isIdle() {
return mParallelBroadcasts.isEmpty() && mDispatcher.isEmpty()
&& (mPendingBroadcast == null);
}
// Used by wait-for-broadcast-idle : fast-forward all current deferrals to
// be immediately deliverable.
void cancelDeferrals() {
mDispatcher.cancelDeferrals();
}
String describeState() {
synchronized (mService) {
return mParallelBroadcasts.size() + " parallel; "
+ mDispatcher.describeStateLocked();
}
}
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(BroadcastQueueProto.QUEUE_NAME, mQueueName);