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

Commit 4cd6a2ad authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Fix SysUI crash when locking while showing the Media Output Group dialog

This CL fixes a bug introduced by http://ag/15663086: When locking the
phone while showing the Media Output Group dialog, SystemUI would crash
because of a mismatch between MediaOutputAdapter.currentActivePosition
and MediaOutputController.mMediaDevices. That mismatch came from the
sharing of the controller between the 2 dialogs, that are now shown at
the same time (even though one is hidden).

Starting from this CL, both dialogs now use a separate instance of
MediaOutputController to avoid this kind of race condition. This CL also
adds a safeguard in MediaOutputBaseDialog to ensure that we notify an
item change within bounds, which would otherwise throw and crash.

Bug: 200781817
Test: Show media output group dialog then lock phone.
Change-Id: I7749cc963a5e145467b32aa3a9efb1e80009f324
parent 97a5f472
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -175,7 +175,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
        }
        if (!mAdapter.isDragging() && !mAdapter.isAnimating()) {
            int currentActivePosition = mAdapter.getCurrentActivePosition();
            if (currentActivePosition >= 0) {
            if (currentActivePosition >= 0 && currentActivePosition < mAdapter.getItemCount()) {
                mAdapter.notifyItemChanged(currentActivePosition);
            } else {
                mAdapter.notifyDataSetChanged();
+7 −23
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
    private final String mPackageName;
    private final Context mContext;
    private final MediaSessionManager mMediaSessionManager;
    private final LocalBluetoothManager mLocalBluetoothManager;
    private final ShadeController mShadeController;
    private final ActivityStarter mActivityStarter;
    private final DialogLaunchAnimator mDialogLaunchAnimator;
@@ -85,7 +86,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
    private MediaController mMediaController;
    @VisibleForTesting
    Callback mCallback;
    Callback mPreviousCallback;
    @VisibleForTesting
    LocalMediaManager mLocalMediaManager;

@@ -101,6 +101,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
        mContext = context;
        mPackageName = packageName;
        mMediaSessionManager = mediaSessionManager;
        mLocalBluetoothManager = lbm;
        mShadeController = shadeController;
        mActivityStarter = starter;
        mAboveStatusbar = aboveStatusbar;
@@ -135,19 +136,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
            }
            return;
        }

        if (mPreviousCallback != null) {
            Log.w(TAG,
                    "Callback started when mPreviousCallback is not null, which is unexpected");
            mPreviousCallback.dismissDialog();
        }

        // If we start the output group dialog when the output dialog is shown, we need to keep a
        // reference to the output dialog to set it back as the callback once we dismiss the output
        // group dialog.
        mPreviousCallback = mCallback;
        mCallback = cb;

        mLocalMediaManager.unregisterCallback(this);
        mLocalMediaManager.stopScan();
        mLocalMediaManager.registerCallback(this);
@@ -163,15 +152,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
            mLocalMediaManager.stopScan();
        }
        mMediaDevices.clear();

        // If there was a previous callback, i.e. we just dismissed the output group dialog and are
        // now back on the output dialog, then we reset the callback to its previous value.
        mCallback = null;
        Callback previous = mPreviousCallback;
        mPreviousCallback = null;
        if (previous != null) {
            start(previous);
        }
    }

    @Override
@@ -480,7 +460,11 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {

    void launchMediaOutputGroupDialog(View mediaOutputDialog) {
        // We show the output group dialog from the output dialog.
        MediaOutputGroupDialog dialog = new MediaOutputGroupDialog(mContext, mAboveStatusbar, this);
        MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
                mAboveStatusbar, mMediaSessionManager, mLocalBluetoothManager, mShadeController,
                mActivityStarter, mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
        MediaOutputGroupDialog dialog = new MediaOutputGroupDialog(mContext, mAboveStatusbar,
                controller);
        mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
    }