Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22ba86cf authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am ca25d2c3: am 4d94a766: Fixed some timeout and lock reentrance issues with broadcasts.

Merge commit 'ca25d2c3'

* commit 'ca25d2c3':
  Fixed some timeout and lock reentrance issues with broadcasts.
parents e9d51c4e ca25d2c3
Loading
Loading
Loading
Loading
+129 −75
Original line number Diff line number Diff line
@@ -565,6 +565,11 @@ public final class ActivityManagerService extends ActivityManagerNative
     */
    private final StringBuilder mStrictModeBuffer = new StringBuilder();

    /**
     * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
     */
    private boolean mPendingBroadcastTimeoutMessage;

    /**
     * Intent broadcast that we have tried to start, but are
     * waiting for its application's process to be created.  We only
@@ -1071,17 +1076,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                processNextBroadcast(true);
            } break;
            case BROADCAST_TIMEOUT_MSG: {
                if (mDidDexOpt) {
                    mDidDexOpt = false;
                    Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
                    mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
                    return;
                }
                // Only process broadcast timeouts if the system is ready. That way
                // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
                // to do heavy lifting for system up
                if (mProcessesReady) {
                    broadcastTimeout();
                synchronized (ActivityManagerService.this) {
                    broadcastTimeoutLocked(true);
                }
            } break;
            case SERVICE_TIMEOUT_MSG: {
@@ -2810,6 +2806,21 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }

    private final class AppNotResponding implements Runnable {
        private final ProcessRecord mApp;
        private final String mAnnotation;

        public AppNotResponding(ProcessRecord app, String annotation) {
            mApp = app;
            mAnnotation = annotation;
        }

        @Override
        public void run() {
            appNotResponding(mApp, null, null, mAnnotation);
        }
    }

    final void appNotResponding(ProcessRecord app, ActivityRecord activity,
            ActivityRecord parent, final String annotation) {
        ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
@@ -3678,7 +3689,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                Slog.w(TAG, "Exception in new application when starting receiver "
                      + br.curComponent.flattenToShortString(), e);
                badApp = true;
                logBroadcastReceiverDiscard(br);
                logBroadcastReceiverDiscardLocked(br);
                finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
                        br.resultExtras, br.resultAbort, true);
                scheduleBroadcastsLocked();
@@ -6406,7 +6417,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            // The current broadcast is waiting for this app's receiver
            // to be finished.  Looks like that's not going to happen, so
            // let the broadcast continue.
            logBroadcastReceiverDiscard(r);
            logBroadcastReceiverDiscardLocked(r);
            finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
                    r.resultExtras, r.resultAbort, true);
            reschedule = true;
@@ -6415,7 +6426,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        if (r != null && r.curApp == app) {
            if (DEBUG_BROADCAST) Slog.v(TAG,
                    "skip & discard pending app " + r);
            logBroadcastReceiverDiscard(r);
            logBroadcastReceiverDiscardLocked(r);
            finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
                    r.resultExtras, r.resultAbort, true);
            reschedule = true;
@@ -10633,7 +10644,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        Binder.restoreCallingIdentity(origId);
    }

    private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
    private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
        if (r.nextReceiver > 0) {
            Object curReceiver = r.receivers.get(r.nextReceiver-1);
            if (curReceiver instanceof BroadcastFilter) {
@@ -10661,26 +10672,63 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }

    private final void broadcastTimeout() {
        ProcessRecord app = null;
        String anrMessage = null;
    private final void setBroadcastTimeoutLocked(long timeoutTime) {
        if (! mPendingBroadcastTimeoutMessage) {
            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
            mHandler.sendMessageAtTime(msg, timeoutTime);
            mPendingBroadcastTimeoutMessage = true;
        }
    }

    private final void cancelBroadcastTimeoutLocked() {
        if (mPendingBroadcastTimeoutMessage) {
            mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
            mPendingBroadcastTimeoutMessage = false;
        }
    }

    private final void broadcastTimeoutLocked(boolean fromMsg) {
        if (fromMsg) {
            mPendingBroadcastTimeoutMessage = false;
        }

        synchronized (this) {
        if (mOrderedBroadcasts.size() == 0) {
            return;
        }

        long now = SystemClock.uptimeMillis();
        BroadcastRecord r = mOrderedBroadcasts.get(0);
            if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
        if (fromMsg) {
            if (mDidDexOpt) {
                // Delay timeouts until dexopt finishes.
                mDidDexOpt = false;
                long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
                setBroadcastTimeoutLocked(timeoutTime);
                return;
            }
            if (! mProcessesReady) {
                // Only process broadcast timeouts if the system is ready. That way
                // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
                // to do heavy lifting for system up.
                return;
            }

            long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
            if (timeoutTime > now) {
                // We can observe premature timeouts because we do not cancel and reset the
                // broadcast timeout message after each receiver finishes.  Instead, we set up
                // an initial timeout then kick it down the road a little further as needed
                // when it expires.
                if (DEBUG_BROADCAST) Slog.v(TAG,
                        "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
                        + (r.receiverTime + BROADCAST_TIMEOUT));
                Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
                mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
                        + timeoutTime);
                setBroadcastTimeoutLocked(timeoutTime);
                return;
            }
        }

            Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
        Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
                + ", started " + (now - r.receiverTime) + "ms ago");
        r.receiverTime = now;
        r.anrCount++;

@@ -10690,9 +10738,12 @@ public final class ActivityManagerService extends ActivityManagerNative
            return;
        }

        ProcessRecord app = null;
        String anrMessage = null;

        Object curReceiver = r.receivers.get(r.nextReceiver-1);
        Slog.w(TAG, "Receiver during timeout: " + curReceiver);
            logBroadcastReceiverDiscard(r);
        logBroadcastReceiverDiscardLocked(r);
        if (curReceiver instanceof BroadcastFilter) {
            BroadcastFilter bf = (BroadcastFilter)curReceiver;
            if (bf.receiverList.pid != 0
@@ -10718,10 +10769,11 @@ public final class ActivityManagerService extends ActivityManagerNative
        finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
                r.resultExtras, r.resultAbort, true);
        scheduleBroadcastsLocked();
        }

        if (anrMessage != null) {
            appNotResponding(app, null, null, anrMessage);
            // Post the ANR to the handler since we do not want to process ANRs while
            // potentially holding our lock.
            mHandler.post(new AppNotResponding(app, anrMessage));
        }
    }

@@ -10763,9 +10815,10 @@ public final class ActivityManagerService extends ActivityManagerNative

    }

    static void performReceive(ProcessRecord app, IIntentReceiver receiver,
    static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky) throws RemoteException {
        // Send the intent to the receiver asynchronously using one-way binder calls.
        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.
@@ -10776,7 +10829,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    
    private final void deliverToRegisteredReceiver(BroadcastRecord r,
    private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered) {
        boolean skip = false;
        if (filter.requiredPermission != null) {
@@ -10834,7 +10887,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    Slog.i(TAG, "Delivering to " + filter
                            + " (seq=" + seq + "): " + r);
                }
                performReceive(filter.receiverList.app, filter.receiverList.receiver,
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode,
                    r.resultData, r.resultExtras, r.ordered, r.initialSticky);
                if (ordered) {
@@ -10891,7 +10944,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    if (DEBUG_BROADCAST)  Slog.v(TAG,
                            "Delivering non-ordered to registered "
                            + target + ": " + r);
                    deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
@@ -10947,7 +11000,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                // and continue to make progress.
                //
                // This is only done if the system is ready so that PRE_BOOT_COMPLETED
                // receivers don't get executed with with timeouts. They're intended for
                // receivers don't get executed with timeouts. They're intended for
                // one time heavy lifting after system upgrades and can take
                // significant amounts of time.
                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
@@ -10963,7 +11016,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                                + " numReceivers=" + numReceivers
                                + " nextReceiver=" + r.nextReceiver
                                + " state=" + r.state);
                        broadcastTimeout(); // forcibly finish this broadcast
                        broadcastTimeoutLocked(false); // forcibly finish this broadcast
                        forceReceive = true;
                        r.state = BroadcastRecord.IDLE;
                    }
@@ -10987,7 +11040,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                                Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
                                        + " seq=" + seq + " app=" + r.callerApp);
                            }
                            performReceive(r.callerApp, r.resultTo,
                            performReceiveLocked(r.callerApp, r.resultTo,
                                new Intent(r.intent), r.resultCode,
                                r.resultData, r.resultExtras, false, false);
                        } catch (RemoteException e) {
@@ -10996,7 +11049,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    }
                    
                    if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
                    mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
                    cancelBroadcastTimeoutLocked();

                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
                            + r);
@@ -11021,11 +11074,12 @@ public final class ActivityManagerService extends ActivityManagerNative

                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
                        + r);
            }
            if (! mPendingBroadcastTimeoutMessage) {
                long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
                if (DEBUG_BROADCAST) Slog.v(TAG,
                        "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
                        + (r.receiverTime + BROADCAST_TIMEOUT));
                Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
                mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
                        "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
                setBroadcastTimeoutLocked(timeoutTime);
            }

            Object nextReceiver = r.receivers.get(recIdx);
@@ -11036,7 +11090,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (DEBUG_BROADCAST)  Slog.v(TAG,
                        "Delivering ordered to registered "
                        + filter + ": " + r);
                deliverToRegisteredReceiver(r, filter, r.ordered);
                deliverToRegisteredReceiverLocked(r, filter, r.ordered);
                if (r.receiver == null || !r.ordered) {
                    // The receiver has already finished, so schedule to
                    // process the next one.
@@ -11144,7 +11198,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                        + info.activityInfo.applicationInfo.packageName + "/"
                        + info.activityInfo.applicationInfo.uid + " for broadcast "
                        + r.intent + ": process is bad");
                logBroadcastReceiverDiscard(r);
                logBroadcastReceiverDiscardLocked(r);
                finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
                        r.resultExtras, r.resultAbort, true);
                scheduleBroadcastsLocked();