Loading api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -6522,6 +6522,7 @@ package android.content { field public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 32; // 0x20 field public static final int FLAG_PERSIST_GRANT_URI_PERMISSION = 64; // 0x40 field public static final int FLAG_RECEIVER_FOREGROUND = 268435456; // 0x10000000 field public static final int FLAG_RECEIVER_NO_ABORT = 134217728; // 0x8000000 field public static final int FLAG_RECEIVER_REGISTERED_ONLY = 1073741824; // 0x40000000 field public static final int FLAG_RECEIVER_REPLACE_PENDING = 536870912; // 0x20000000 field public static final java.lang.String METADATA_DOCK_HOME = "android.dock_home"; Loading Loading @@ -31609,6 +31610,8 @@ package android.widget { ctor public NumberPicker(android.content.Context); ctor public NumberPicker(android.content.Context, android.util.AttributeSet); ctor public NumberPicker(android.content.Context, android.util.AttributeSet, int); method public int computeVerticalScrollOffset(); method public int computeVerticalScrollRange(); method public java.lang.String[] getDisplayedValues(); method public int getMaxValue(); method public int getMinValue(); core/java/android/content/Intent.java +8 −2 Original line number Diff line number Diff line Loading @@ -3587,6 +3587,12 @@ public class Intent implements Parcelable, Cloneable { * background priority class. */ public static final int FLAG_RECEIVER_FOREGROUND = 0x10000000; /** * If this is an ordered broadcast, don't allow receivers to abort the broadcast. * They can still propagate results through to later receivers, but they can not prevent * later receivers from seeing the broadcast. */ public static final int FLAG_RECEIVER_NO_ABORT = 0x08000000; /** * If set, when sending a broadcast <i>before boot has completed</i> only * registered receivers will be called -- no BroadcastReceiver components Loading @@ -3600,14 +3606,14 @@ public class Intent implements Parcelable, Cloneable { * * @hide */ public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x08000000; public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x04000000; /** * Set when this broadcast is for a boot upgrade, a special mode that * allows the broadcast to be sent before the system is ready and launches * the app process with no providers running in it. * @hide */ public static final int FLAG_RECEIVER_BOOT_UPGRADE = 0x04000000; public static final int FLAG_RECEIVER_BOOT_UPGRADE = 0x02000000; /** * @hide Flags that can't be changed with PendingIntent. Loading services/java/com/android/server/am/ActiveServices.java +14 −1 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ public final class ActiveServices { * Information about services for a single user. */ class ServiceMap extends Handler { final int mUserId; final ArrayMap<ComponentName, ServiceRecord> mServicesByName = new ArrayMap<ComponentName, ServiceRecord>(); final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent Loading @@ -165,6 +166,10 @@ public final class ActiveServices { static final int MSG_BG_START_TIMEOUT = 1; ServiceMap(int userId) { mUserId = userId; } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading Loading @@ -224,6 +229,9 @@ public final class ActiveServices { Message msg = obtainMessage(MSG_BG_START_TIMEOUT); sendMessageAtTime(msg, when); } if (mStartingBackground.size() < mMaxStartingBackground) { mAm.backgroundServicesFinishedLocked(mUserId); } } } Loading @@ -239,10 +247,15 @@ public final class ActiveServices { return getServiceMap(callingUser).mServicesByName.get(name); } boolean hasBackgroundServices(int callingUser) { ServiceMap smap = mServiceMap.get(callingUser); return smap != null ? smap.mStartingBackground.size() >= mMaxStartingBackground : false; } private ServiceMap getServiceMap(int callingUser) { ServiceMap smap = mServiceMap.get(callingUser); if (smap == null) { smap = new ServiceMap(); smap = new ServiceMap(callingUser); mServiceMap.put(callingUser, smap); } return smap; Loading services/java/com/android/server/am/ActivityManagerService.java +17 −12 Original line number Diff line number Diff line Loading @@ -1903,8 +1903,8 @@ public final class ActivityManagerService extends ActivityManagerNative private ActivityManagerService() { Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT); mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT); mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; Loading Loading @@ -4910,6 +4910,7 @@ public final class ActivityManagerService extends ActivityManagerNative final int userId = mStartedUsers.keyAt(i); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); broadcastIntentLocked(null, null, intent, null, new IIntentReceiver.Stub() { @Override Loading @@ -4924,7 +4925,7 @@ public final class ActivityManagerService extends ActivityManagerNative }, 0, null, null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, false, false, MY_PID, Process.SYSTEM_UID, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, userId); } } Loading Loading @@ -12578,14 +12579,13 @@ public final class ActivityManagerService extends ActivityManagerNative boolean doTrim = false; synchronized(this) { ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl != null) { if (rl.curBroadcast != null) { BroadcastRecord r = rl.curBroadcast; final boolean doNext = finishReceiverLocked( receiver.asBinder(), r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort); if (doNext) { doTrim = true; r.queue.processNextBroadcast(false); Loading Loading @@ -13212,16 +13212,20 @@ public final class ActivityManagerService extends ActivityManagerNative } private final boolean finishReceiverLocked(IBinder receiver, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean explicit) { String resultData, Bundle resultExtras, boolean resultAbort) { final BroadcastRecord r = broadcastRecordForReceiverLocked(receiver); if (r == null) { Slog.w(TAG, "finishReceiver called but not found on queue"); return false; } return r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, explicit); return r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, false); } void backgroundServicesFinishedLocked(int userId) { for (BroadcastQueue queue : mBroadcastQueues) { queue.backgroundServicesFinishedLocked(userId); } } public void finishReceiver(IBinder who, int resultCode, String resultData, Loading @@ -13236,7 +13240,7 @@ public final class ActivityManagerService extends ActivityManagerNative final long origId = Binder.clearCallingIdentity(); try { boolean doNext = false; BroadcastRecord r = null; BroadcastRecord r; synchronized(this) { r = broadcastRecordForReceiverLocked(who); Loading Loading @@ -15704,10 +15708,11 @@ public final class ActivityManagerService extends ActivityManagerNative final int userId = uss.mHandle.getIdentifier(); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, false, false, MY_PID, Process.SYSTEM_UID, userId); true, false, MY_PID, Process.SYSTEM_UID, userId); } int num = mUserLru.size(); int i = 0; services/java/com/android/server/am/BroadcastQueue.java +76 −31 Original line number Diff line number Diff line Loading @@ -54,8 +54,9 @@ public final class BroadcastQueue { static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT; static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU; static final int MAX_BROADCAST_HISTORY = 25; static final int MAX_BROADCAST_SUMMARY_HISTORY = 100; static final int MAX_BROADCAST_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 10 : 25; static final int MAX_BROADCAST_SUMMARY_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 25 : 100; final ActivityManagerService mService; Loading @@ -69,6 +70,12 @@ public final class BroadcastQueue { */ final long mTimeoutPeriod; /** * If true, we can delay broadcasts while waiting services to finish in the previous * receiver's process. */ final boolean mDelayBehindServices; /** * Lists of all active broadcasts that are to be executed immediately * (without waiting for another broadcast to finish). Currently this only Loading @@ -76,8 +83,8 @@ public final class BroadcastQueue { * a bunch of processes to execute IntentReceiver components. Background- * and foreground-priority broadcasts are queued separately. */ final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>(); final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>(); /** * List of all active broadcasts that are to be executed one at a time. * The object at the top of the list is the currently activity broadcasts; Loading @@ -85,20 +92,17 @@ public final class BroadcastQueue { * broadcasts, separate background- and foreground-priority queues are * maintained. */ final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>(); final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>(); /** * Historical data of past broadcasts, for debugging. */ final BroadcastRecord[] mBroadcastHistory = new BroadcastRecord[MAX_BROADCAST_HISTORY]; final BroadcastRecord[] mBroadcastHistory = new BroadcastRecord[MAX_BROADCAST_HISTORY]; /** * Summary of historical data of past broadcasts, for debugging. */ final Intent[] mBroadcastSummaryHistory = new Intent[MAX_BROADCAST_SUMMARY_HISTORY]; final Intent[] mBroadcastSummaryHistory = new Intent[MAX_BROADCAST_SUMMARY_HISTORY]; /** * Set when we current have a BROADCAST_INTENT_MSG in flight. Loading Loading @@ -128,10 +132,6 @@ public final class BroadcastQueue { static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1; final Handler mHandler = new Handler() { //public Handler() { // if (localLOGV) Slog.v(TAG, "Handler started!"); //} public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { Loading Loading @@ -163,10 +163,12 @@ public final class BroadcastQueue { } } BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod) { BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod, boolean allowDelayBehindServices) { mService = service; mQueueName = name; mTimeoutPeriod = timeoutPeriod; mDelayBehindServices = allowDelayBehindServices; } public boolean isPendingBroadcastProcessLocked(int pid) { Loading Loading @@ -260,7 +262,7 @@ public final class BroadcastQueue { + br.curComponent.flattenToShortString(), e); logBroadcastReceiverDiscardLocked(br); finishReceiverLocked(br, br.resultCode, br.resultData, br.resultExtras, br.resultAbort, true); br.resultExtras, br.resultAbort, false); scheduleBroadcastsLocked(); // We need to reset the state if we failed to start the receiver. br.state = BroadcastRecord.IDLE; Loading Loading @@ -289,7 +291,7 @@ public final class BroadcastQueue { // let the broadcast continue. logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); reschedule = true; } Loading @@ -299,7 +301,7 @@ public final class BroadcastQueue { "[" + mQueueName + "] skip & discard pending app " + r); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); reschedule = true; } if (reschedule) { Loading Loading @@ -330,15 +332,12 @@ public final class BroadcastQueue { } public boolean finishReceiverLocked(BroadcastRecord r, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean explicit) { int state = r.state; String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) { final int state = r.state; r.state = BroadcastRecord.IDLE; if (state == BroadcastRecord.IDLE) { if (explicit) { Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE"); } } r.receiver = null; r.intent.setComponent(null); if (r.curApp != null) { Loading @@ -348,15 +347,35 @@ public final class BroadcastQueue { r.curFilter.receiverList.curBroadcast = null; } r.curFilter = null; r.curApp = null; r.curComponent = null; r.curReceiver = null; r.curApp = null; mPendingBroadcast = null; r.resultCode = resultCode; r.resultData = resultData; r.resultExtras = resultExtras; if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) { r.resultAbort = resultAbort; } else { r.resultAbort = false; } if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices && r.queue.mOrderedBroadcasts.size() > 0 && r.queue.mOrderedBroadcasts.get(0) == r) { // In this case, we are ready to process the next receiver for the current broadcast, // but are on a queue that would like to wait for services to finish before moving // on. If there are background services currently starting, then we will go into a // special state where we hold off on continuing this broadcast until they are done. if (mService.mServices.hasBackgroundServices(r.userId)) { Slog.i(ActivityManagerService.TAG, "Delay finish: " + r.curComponent.flattenToShortString()); r.state = BroadcastRecord.WAITING_SERVICES; return false; } } r.curComponent = null; // We will process the next receiver right now if this is finishing // an app receiver (which is always asynchronous) or after we have Loading @@ -365,6 +384,18 @@ public final class BroadcastQueue { || state == BroadcastRecord.CALL_DONE_RECEIVE; } public void backgroundServicesFinishedLocked(int userId) { if (mOrderedBroadcasts.size() > 0) { BroadcastRecord br = mOrderedBroadcasts.get(0); if (br.userId == userId && br.state == BroadcastRecord.WAITING_SERVICES) { Slog.i(ActivityManagerService.TAG, "Resuming delayed broadcast"); br.curComponent = null; br.state = BroadcastRecord.IDLE; processNextBroadcast(false); } } } private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { Loading Loading @@ -821,7 +852,7 @@ public final class BroadcastQueue { // sent the broadcast. logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); // We need to reset the state if we failed to start the receiver. r.state = BroadcastRecord.IDLE; Loading Loading @@ -850,7 +881,7 @@ public final class BroadcastQueue { + r.intent + ": process is bad"); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return; Loading Loading @@ -917,6 +948,20 @@ public final class BroadcastQueue { } } BroadcastRecord br = mOrderedBroadcasts.get(0); if (br.state == BroadcastRecord.WAITING_SERVICES) { // In this case the broadcast had already finished, but we had decided to wait // for started services to finish as well before going on. So if we have actually // waited long enough time timeout the broadcast, let's give up on the whole thing // and just move on to the next. Slog.i(ActivityManagerService.TAG, "Waited long enough for: " + (br.curComponent != null ? br.curComponent.flattenToShortString() : "(null)")); br.curComponent = null; br.state = BroadcastRecord.IDLE; processNextBroadcast(false); return; } Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r. receiver + ", started " + (now - r.receiverTime) + "ms ago"); r.receiverTime = now; Loading Loading @@ -957,7 +1002,7 @@ public final class BroadcastQueue { // Move on to the next receiver. finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); if (anrMessage != null) { Loading Loading
api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -6522,6 +6522,7 @@ package android.content { field public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 32; // 0x20 field public static final int FLAG_PERSIST_GRANT_URI_PERMISSION = 64; // 0x40 field public static final int FLAG_RECEIVER_FOREGROUND = 268435456; // 0x10000000 field public static final int FLAG_RECEIVER_NO_ABORT = 134217728; // 0x8000000 field public static final int FLAG_RECEIVER_REGISTERED_ONLY = 1073741824; // 0x40000000 field public static final int FLAG_RECEIVER_REPLACE_PENDING = 536870912; // 0x20000000 field public static final java.lang.String METADATA_DOCK_HOME = "android.dock_home"; Loading Loading @@ -31609,6 +31610,8 @@ package android.widget { ctor public NumberPicker(android.content.Context); ctor public NumberPicker(android.content.Context, android.util.AttributeSet); ctor public NumberPicker(android.content.Context, android.util.AttributeSet, int); method public int computeVerticalScrollOffset(); method public int computeVerticalScrollRange(); method public java.lang.String[] getDisplayedValues(); method public int getMaxValue(); method public int getMinValue();
core/java/android/content/Intent.java +8 −2 Original line number Diff line number Diff line Loading @@ -3587,6 +3587,12 @@ public class Intent implements Parcelable, Cloneable { * background priority class. */ public static final int FLAG_RECEIVER_FOREGROUND = 0x10000000; /** * If this is an ordered broadcast, don't allow receivers to abort the broadcast. * They can still propagate results through to later receivers, but they can not prevent * later receivers from seeing the broadcast. */ public static final int FLAG_RECEIVER_NO_ABORT = 0x08000000; /** * If set, when sending a broadcast <i>before boot has completed</i> only * registered receivers will be called -- no BroadcastReceiver components Loading @@ -3600,14 +3606,14 @@ public class Intent implements Parcelable, Cloneable { * * @hide */ public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x08000000; public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x04000000; /** * Set when this broadcast is for a boot upgrade, a special mode that * allows the broadcast to be sent before the system is ready and launches * the app process with no providers running in it. * @hide */ public static final int FLAG_RECEIVER_BOOT_UPGRADE = 0x04000000; public static final int FLAG_RECEIVER_BOOT_UPGRADE = 0x02000000; /** * @hide Flags that can't be changed with PendingIntent. Loading
services/java/com/android/server/am/ActiveServices.java +14 −1 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ public final class ActiveServices { * Information about services for a single user. */ class ServiceMap extends Handler { final int mUserId; final ArrayMap<ComponentName, ServiceRecord> mServicesByName = new ArrayMap<ComponentName, ServiceRecord>(); final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent Loading @@ -165,6 +166,10 @@ public final class ActiveServices { static final int MSG_BG_START_TIMEOUT = 1; ServiceMap(int userId) { mUserId = userId; } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading Loading @@ -224,6 +229,9 @@ public final class ActiveServices { Message msg = obtainMessage(MSG_BG_START_TIMEOUT); sendMessageAtTime(msg, when); } if (mStartingBackground.size() < mMaxStartingBackground) { mAm.backgroundServicesFinishedLocked(mUserId); } } } Loading @@ -239,10 +247,15 @@ public final class ActiveServices { return getServiceMap(callingUser).mServicesByName.get(name); } boolean hasBackgroundServices(int callingUser) { ServiceMap smap = mServiceMap.get(callingUser); return smap != null ? smap.mStartingBackground.size() >= mMaxStartingBackground : false; } private ServiceMap getServiceMap(int callingUser) { ServiceMap smap = mServiceMap.get(callingUser); if (smap == null) { smap = new ServiceMap(); smap = new ServiceMap(callingUser); mServiceMap.put(callingUser, smap); } return smap; Loading
services/java/com/android/server/am/ActivityManagerService.java +17 −12 Original line number Diff line number Diff line Loading @@ -1903,8 +1903,8 @@ public final class ActivityManagerService extends ActivityManagerNative private ActivityManagerService() { Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT); mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT); mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; Loading Loading @@ -4910,6 +4910,7 @@ public final class ActivityManagerService extends ActivityManagerNative final int userId = mStartedUsers.keyAt(i); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); broadcastIntentLocked(null, null, intent, null, new IIntentReceiver.Stub() { @Override Loading @@ -4924,7 +4925,7 @@ public final class ActivityManagerService extends ActivityManagerNative }, 0, null, null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, false, false, MY_PID, Process.SYSTEM_UID, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, userId); } } Loading Loading @@ -12578,14 +12579,13 @@ public final class ActivityManagerService extends ActivityManagerNative boolean doTrim = false; synchronized(this) { ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl != null) { if (rl.curBroadcast != null) { BroadcastRecord r = rl.curBroadcast; final boolean doNext = finishReceiverLocked( receiver.asBinder(), r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort); if (doNext) { doTrim = true; r.queue.processNextBroadcast(false); Loading Loading @@ -13212,16 +13212,20 @@ public final class ActivityManagerService extends ActivityManagerNative } private final boolean finishReceiverLocked(IBinder receiver, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean explicit) { String resultData, Bundle resultExtras, boolean resultAbort) { final BroadcastRecord r = broadcastRecordForReceiverLocked(receiver); if (r == null) { Slog.w(TAG, "finishReceiver called but not found on queue"); return false; } return r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, explicit); return r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, false); } void backgroundServicesFinishedLocked(int userId) { for (BroadcastQueue queue : mBroadcastQueues) { queue.backgroundServicesFinishedLocked(userId); } } public void finishReceiver(IBinder who, int resultCode, String resultData, Loading @@ -13236,7 +13240,7 @@ public final class ActivityManagerService extends ActivityManagerNative final long origId = Binder.clearCallingIdentity(); try { boolean doNext = false; BroadcastRecord r = null; BroadcastRecord r; synchronized(this) { r = broadcastRecordForReceiverLocked(who); Loading Loading @@ -15704,10 +15708,11 @@ public final class ActivityManagerService extends ActivityManagerNative final int userId = uss.mHandle.getIdentifier(); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, false, false, MY_PID, Process.SYSTEM_UID, userId); true, false, MY_PID, Process.SYSTEM_UID, userId); } int num = mUserLru.size(); int i = 0;
services/java/com/android/server/am/BroadcastQueue.java +76 −31 Original line number Diff line number Diff line Loading @@ -54,8 +54,9 @@ public final class BroadcastQueue { static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT; static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU; static final int MAX_BROADCAST_HISTORY = 25; static final int MAX_BROADCAST_SUMMARY_HISTORY = 100; static final int MAX_BROADCAST_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 10 : 25; static final int MAX_BROADCAST_SUMMARY_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 25 : 100; final ActivityManagerService mService; Loading @@ -69,6 +70,12 @@ public final class BroadcastQueue { */ final long mTimeoutPeriod; /** * If true, we can delay broadcasts while waiting services to finish in the previous * receiver's process. */ final boolean mDelayBehindServices; /** * Lists of all active broadcasts that are to be executed immediately * (without waiting for another broadcast to finish). Currently this only Loading @@ -76,8 +83,8 @@ public final class BroadcastQueue { * a bunch of processes to execute IntentReceiver components. Background- * and foreground-priority broadcasts are queued separately. */ final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>(); final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>(); /** * List of all active broadcasts that are to be executed one at a time. * The object at the top of the list is the currently activity broadcasts; Loading @@ -85,20 +92,17 @@ public final class BroadcastQueue { * broadcasts, separate background- and foreground-priority queues are * maintained. */ final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>(); final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>(); /** * Historical data of past broadcasts, for debugging. */ final BroadcastRecord[] mBroadcastHistory = new BroadcastRecord[MAX_BROADCAST_HISTORY]; final BroadcastRecord[] mBroadcastHistory = new BroadcastRecord[MAX_BROADCAST_HISTORY]; /** * Summary of historical data of past broadcasts, for debugging. */ final Intent[] mBroadcastSummaryHistory = new Intent[MAX_BROADCAST_SUMMARY_HISTORY]; final Intent[] mBroadcastSummaryHistory = new Intent[MAX_BROADCAST_SUMMARY_HISTORY]; /** * Set when we current have a BROADCAST_INTENT_MSG in flight. Loading Loading @@ -128,10 +132,6 @@ public final class BroadcastQueue { static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1; final Handler mHandler = new Handler() { //public Handler() { // if (localLOGV) Slog.v(TAG, "Handler started!"); //} public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { Loading Loading @@ -163,10 +163,12 @@ public final class BroadcastQueue { } } BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod) { BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod, boolean allowDelayBehindServices) { mService = service; mQueueName = name; mTimeoutPeriod = timeoutPeriod; mDelayBehindServices = allowDelayBehindServices; } public boolean isPendingBroadcastProcessLocked(int pid) { Loading Loading @@ -260,7 +262,7 @@ public final class BroadcastQueue { + br.curComponent.flattenToShortString(), e); logBroadcastReceiverDiscardLocked(br); finishReceiverLocked(br, br.resultCode, br.resultData, br.resultExtras, br.resultAbort, true); br.resultExtras, br.resultAbort, false); scheduleBroadcastsLocked(); // We need to reset the state if we failed to start the receiver. br.state = BroadcastRecord.IDLE; Loading Loading @@ -289,7 +291,7 @@ public final class BroadcastQueue { // let the broadcast continue. logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); reschedule = true; } Loading @@ -299,7 +301,7 @@ public final class BroadcastQueue { "[" + mQueueName + "] skip & discard pending app " + r); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); reschedule = true; } if (reschedule) { Loading Loading @@ -330,15 +332,12 @@ public final class BroadcastQueue { } public boolean finishReceiverLocked(BroadcastRecord r, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean explicit) { int state = r.state; String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) { final int state = r.state; r.state = BroadcastRecord.IDLE; if (state == BroadcastRecord.IDLE) { if (explicit) { Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE"); } } r.receiver = null; r.intent.setComponent(null); if (r.curApp != null) { Loading @@ -348,15 +347,35 @@ public final class BroadcastQueue { r.curFilter.receiverList.curBroadcast = null; } r.curFilter = null; r.curApp = null; r.curComponent = null; r.curReceiver = null; r.curApp = null; mPendingBroadcast = null; r.resultCode = resultCode; r.resultData = resultData; r.resultExtras = resultExtras; if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) { r.resultAbort = resultAbort; } else { r.resultAbort = false; } if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices && r.queue.mOrderedBroadcasts.size() > 0 && r.queue.mOrderedBroadcasts.get(0) == r) { // In this case, we are ready to process the next receiver for the current broadcast, // but are on a queue that would like to wait for services to finish before moving // on. If there are background services currently starting, then we will go into a // special state where we hold off on continuing this broadcast until they are done. if (mService.mServices.hasBackgroundServices(r.userId)) { Slog.i(ActivityManagerService.TAG, "Delay finish: " + r.curComponent.flattenToShortString()); r.state = BroadcastRecord.WAITING_SERVICES; return false; } } r.curComponent = null; // We will process the next receiver right now if this is finishing // an app receiver (which is always asynchronous) or after we have Loading @@ -365,6 +384,18 @@ public final class BroadcastQueue { || state == BroadcastRecord.CALL_DONE_RECEIVE; } public void backgroundServicesFinishedLocked(int userId) { if (mOrderedBroadcasts.size() > 0) { BroadcastRecord br = mOrderedBroadcasts.get(0); if (br.userId == userId && br.state == BroadcastRecord.WAITING_SERVICES) { Slog.i(ActivityManagerService.TAG, "Resuming delayed broadcast"); br.curComponent = null; br.state = BroadcastRecord.IDLE; processNextBroadcast(false); } } } private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { Loading Loading @@ -821,7 +852,7 @@ public final class BroadcastQueue { // sent the broadcast. logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); // We need to reset the state if we failed to start the receiver. r.state = BroadcastRecord.IDLE; Loading Loading @@ -850,7 +881,7 @@ public final class BroadcastQueue { + r.intent + ": process is bad"); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return; Loading Loading @@ -917,6 +948,20 @@ public final class BroadcastQueue { } } BroadcastRecord br = mOrderedBroadcasts.get(0); if (br.state == BroadcastRecord.WAITING_SERVICES) { // In this case the broadcast had already finished, but we had decided to wait // for started services to finish as well before going on. So if we have actually // waited long enough time timeout the broadcast, let's give up on the whole thing // and just move on to the next. Slog.i(ActivityManagerService.TAG, "Waited long enough for: " + (br.curComponent != null ? br.curComponent.flattenToShortString() : "(null)")); br.curComponent = null; br.state = BroadcastRecord.IDLE; processNextBroadcast(false); return; } Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r. receiver + ", started " + (now - r.receiverTime) + "ms ago"); r.receiverTime = now; Loading Loading @@ -957,7 +1002,7 @@ public final class BroadcastQueue { // Move on to the next receiver. finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); if (anrMessage != null) { Loading