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

Commit 1aedcce9 authored by Joe Onorato's avatar Joe Onorato
Browse files

Fix StatusBarService deadlock for real this time.

The lock is now only held long enough to swap the queue with a new ArrayList.

Bug: 2542233
Change-Id: I8c1c3d4d0b5b53166cc239fc0069d69929b43f91
parent 2911e8ef
Loading
Loading
Loading
Loading
+81 −80
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ public class StatusBarService extends IStatusBar.Stub
    StatusBarView mStatusBarView;
    int mPixelFormat;
    H mHandler = new H();
    Object mQueueLock = new Object();
    ArrayList<PendingOp> mQueue = new ArrayList<PendingOp>();
    NotificationCallbacks mNotificationCallbacks;
    
@@ -440,7 +441,7 @@ public class StatusBarService extends IStatusBar.Stub
    }

    private void addPendingOp(int code, IBinder key, IconData data, NotificationData n, int i) {
        synchronized (mQueue) {
        synchronized (mQueueLock) {
            PendingOp op = new PendingOp();
            op.key = key;
            op.code = code;
@@ -455,7 +456,7 @@ public class StatusBarService extends IStatusBar.Stub
    }

    private void addPendingOp(int code, IBinder key, boolean visible) {
        synchronized (mQueue) {
        synchronized (mQueueLock) {
            PendingOp op = new PendingOp();
            op.key = key;
            op.code = code;
@@ -468,7 +469,7 @@ public class StatusBarService extends IStatusBar.Stub
    }

    private void addPendingOp(int code, int integer) {
        synchronized (mQueue) {
        synchronized (mQueueLock) {
            PendingOp op = new PendingOp();
            op.code = code;
            op.integer = integer;
@@ -557,20 +558,24 @@ public class StatusBarService extends IStatusBar.Stub
                doRevealAnimation();
                return;
            }
            boolean expand = false;
            boolean doExpand = false;
            boolean doDisable = false;
            int disableWhat = 0;

            synchronized (mQueue) {
            ArrayList<PendingOp> queue;
            synchronized (mQueueLock) {
                queue = mQueue;
                mQueue = new ArrayList<PendingOp>();
            }

            boolean wasExpanded = mExpanded;

            // for each one in the queue, find all of the ones with the same key
            // and collapse that down into a final op and/or call to setVisibility, etc
                expand = wasExpanded;
                int N = mQueue.size();
            boolean expand = wasExpanded;
            boolean doExpand = false;
            boolean doDisable = false;
            int disableWhat = 0;
            int N = queue.size();
            while (N > 0) {
                    PendingOp op = mQueue.get(0);
                PendingOp op = queue.get(0);
                boolean doOp = false;
                boolean visible = false;
                boolean doVisibility = false;
@@ -593,7 +598,7 @@ public class StatusBarService extends IStatusBar.Stub
                if (alwaysHandle(op.code)) {
                    // coalesce these
                    for (int i=1; i<N; i++) {
                            PendingOp o = mQueue.get(i);
                        PendingOp o = queue.get(i);
                        if (!alwaysHandle(o.code) && o.key == op.key) {
                            if (o.code == OP_SET_VISIBLE) {
                                visible = o.visible;
@@ -608,14 +613,14 @@ public class StatusBarService extends IStatusBar.Stub
                                op.iconData = o.iconData;
                                op.notificationData = o.notificationData;
                            }
                                mQueue.remove(i);
                            queue.remove(i);
                            i--;
                            N--;
                        }
                    }
                }

                    mQueue.remove(0);
                queue.remove(0);
                N--;

                if (doOp) {
@@ -638,13 +643,9 @@ public class StatusBarService extends IStatusBar.Stub
                }
            }

                if (mQueue.size() != 0) {
                    throw new RuntimeException("Assertion failed: mQueue.size=" + mQueue.size());
                }
            if (queue.size() != 0) {
                throw new RuntimeException("Assertion failed: queue.size=" + queue.size());
            }
            // This must be done outside the synchronized block above to prevent a deadlock where
            // we call into the NotificationManagerService and it is in turn attempting to post a
            // message to our queue.
            if (doExpand) {
                // this is last so that we capture all of the pending changes before doing it
                if (expand) {
@@ -1397,7 +1398,7 @@ public class StatusBarService extends IStatusBar.Stub
            return;
        }
        
        synchronized (mQueue) {
        synchronized (mQueueLock) {
            pw.println("Current Status Bar state:");
            pw.println("  mExpanded=" + mExpanded
                    + ", mExpandedVisible=" + mExpandedVisible);