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

Commit 016c9c8c authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

[DO NOT MERGE] Prevent crash from early Toast surface destruction.

To understand this change it's first helpful to review Toasts.
The ViewRoot is constructed on the client side, but it's added,
to a window token controlled by the NotificationManagerService.
When we call NotificationManagerService#cancelToast, the system
will remove this window token. With the window token removed,
the WindowManager needs to destroy the surface to prevent orphaned
windows. If we destroy the Surface before removing the toast on the
client side however, we've never asked the ViewRoot to stop rendering
and we could have a crash. To solve this we just have to ensure we call
removeView before cancelToast.

Bug: 31547288
Bug: 30150688

Change-Id: Ic7e8914a7fb2134a8b9e0c2f3810d7f075c8391e
parent cbfb58c9
Loading
Loading
Loading
Loading
+43 −18
Original line number Original line Diff line number Diff line
@@ -100,7 +100,7 @@ public class Toast {
     */
     */
    public Toast(Context context) {
    public Toast(Context context) {
        mContext = context;
        mContext = context;
        mTN = new TN();
        mTN = new TN(context.getPackageName());
        mTN.mY = context.getResources().getDimensionPixelSize(
        mTN.mY = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.toast_y_offset);
                com.android.internal.R.dimen.toast_y_offset);
        mTN.mGravity = context.getResources().getInteger(
        mTN.mGravity = context.getResources().getInteger(
@@ -133,13 +133,7 @@ public class Toast {
     * after the appropriate duration.
     * after the appropriate duration.
     */
     */
    public void cancel() {
    public void cancel() {
        mTN.hide();
        mTN.cancel();

        try {
            getService().cancelToast(mContext.getPackageName(), mTN);
        } catch (RemoteException e) {
            // Empty
        }
    }
    }


    /**
    /**
@@ -331,18 +325,40 @@ public class Toast {
        final Runnable mHide = new Runnable() {
        final Runnable mHide = new Runnable() {
            @Override
            @Override
            public void run() {
            public void run() {
                handleHide();
                // Don't do this in handleHide() because it is also invoked by handleShow()
                mNextView = null;
            }
            }
        };
        };


        private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
        private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();

        private static final int SHOW = 0;
        private static final int HIDE = 1;
        private static final int CANCEL = 2;
        final Handler mHandler = new Handler() {
        final Handler mHandler = new Handler() {
            @Override
            @Override
            public void handleMessage(Message msg) {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case SHOW: {
                        IBinder token = (IBinder) msg.obj;
                        IBinder token = (IBinder) msg.obj;
                        handleShow(token);
                        handleShow(token);
                        break;
                    }
                    case HIDE: {
                        handleHide();
                        // Don't do this in handleHide() because it is also invoked by handleShow()
                        mNextView = null;
                        break;
                    }
                    case CANCEL: {
                        handleHide();
                        // Don't do this in handleHide() because it is also invoked by handleShow()
                        mNextView = null;
                        try {
                            getService().cancelToast(mPackageName, TN.this);
                        } catch (RemoteException e) {
                        }
                        break;
                    }
                }
            }
            }
        };
        };


@@ -358,10 +374,12 @@ public class Toast {


        WindowManager mWM;
        WindowManager mWM;


        String mPackageName;

        static final long SHORT_DURATION_TIMEOUT = 5000;
        static final long SHORT_DURATION_TIMEOUT = 5000;
        static final long LONG_DURATION_TIMEOUT = 1000;
        static final long LONG_DURATION_TIMEOUT = 1000;


        TN() {
        TN(String packageName) {
            // XXX This should be changed to use a Dialog, with a Theme.Toast
            // XXX This should be changed to use a Dialog, with a Theme.Toast
            // defined that sets up the layout params appropriately.
            // defined that sets up the layout params appropriately.
            final WindowManager.LayoutParams params = mParams;
            final WindowManager.LayoutParams params = mParams;
@@ -374,6 +392,8 @@ public class Toast {
            params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

            mPackageName = packageName;
        }
        }


        /**
        /**
@@ -382,7 +402,7 @@ public class Toast {
        @Override
        @Override
        public void show(IBinder windowToken) {
        public void show(IBinder windowToken) {
            if (localLOGV) Log.v(TAG, "SHOW: " + this);
            if (localLOGV) Log.v(TAG, "SHOW: " + this);
            mHandler.obtainMessage(0, windowToken).sendToTarget();
            mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
        }
        }


        /**
        /**
@@ -391,7 +411,12 @@ public class Toast {
        @Override
        @Override
        public void hide() {
        public void hide() {
            if (localLOGV) Log.v(TAG, "HIDE: " + this);
            if (localLOGV) Log.v(TAG, "HIDE: " + this);
            mHandler.post(mHide);
            mHandler.obtainMessage(HIDE).sendToTarget();
        }

        public void cancel() {
            if (localLOGV) Log.v(TAG, "CANCEL: " + this);
            mHandler.obtainMessage(CANCEL).sendToTarget();
        }
        }


        public void handleShow(IBinder windowToken) {
        public void handleShow(IBinder windowToken) {