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

Commit 70f0d229 authored by Robert Carr's avatar Robert Carr
Browse files

Add WindowManager side timeout for toasts.

If the thread a toast is shown on is shut down,
the attempt to post the hide message to it's handler
will fail and it will never request removal. If this was
only some application background thread we will also not
receive a death notification. It seems best to use a timeout
to ensure we don't need the clients cooperation, espescially
as toasts can keep the screen on.

Bug: 21693547
Change-Id: I1d6e54ded5b9e2050daedc4d263e2e21fbe69862
parent fd580f7d
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1726,6 +1726,16 @@ public interface WindowManager extends ViewManager {
         */
        public CharSequence accessibilityTitle;

        /**
         * Sets a timeout in milliseconds before which the window will be removed
         * by the window manager. Useful for transient notifications like toasts
         * so we don't have to rely on client cooperation to ensure the window
         * is removed. Must be specified at window creation time.
         *
         * @hide
         */
        public long removeTimeoutMilliseconds = -1;

        public LayoutParams() {
            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            type = TYPE_APPLICATION;
@@ -1847,6 +1857,7 @@ public interface WindowManager extends ViewManager {
            out.writeInt(needsMenuKey);
            out.writeInt(accessibilityIdOfAnchor);
            TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
            out.writeLong(removeTimeoutMilliseconds);
        }

        public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1900,6 +1911,7 @@ public interface WindowManager extends ViewManager {
            needsMenuKey = in.readInt();
            accessibilityIdOfAnchor = in.readInt();
            accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
            removeTimeoutMilliseconds = in.readLong();
        }

        @SuppressWarnings({"PointlessBitwiseExpression"})
@@ -2120,6 +2132,9 @@ public interface WindowManager extends ViewManager {
                changes |= ACCESSIBILITY_TITLE_CHANGED;
            }

            // This can't change, it's only set at window creation time.
            removeTimeoutMilliseconds = o.removeTimeoutMilliseconds;

            return changes;
        }

+8 −1
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ public class Toast {
     */
    public void setDuration(@Duration int duration) {
        mDuration = duration;
        mTN.mDuration = duration;
    }

    /**
@@ -352,9 +353,13 @@ public class Toast {

        View mView;
        View mNextView;
        int mDuration;

        WindowManager mWM;

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

        TN() {
            // XXX This should be changed to use a Dialog, with a Theme.Toast
            // defined that sets up the layout params appropriately.
@@ -417,6 +422,8 @@ public class Toast {
                mParams.verticalMargin = mVerticalMargin;
                mParams.horizontalMargin = mHorizontalMargin;
                mParams.packageName = packageName;
                mParams.removeTimeoutMilliseconds = mDuration ==
                    Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
                if (mView.getParent() != null) {
                    if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                    mWM.removeView(mView);
+18 −1
Original line number Diff line number Diff line
@@ -2107,6 +2107,11 @@ public class WindowManagerService extends IWindowManager.Stub
            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                reportNewConfig = true;
            }
            if (attrs.removeTimeoutMilliseconds > 0) {
                mH.sendMessageDelayed(
                        mH.obtainMessage(H.WINDOW_REMOVE_TIMEOUT, win),
                        attrs.removeTimeoutMilliseconds);
            }
        }

        if (reportNewConfig) {
@@ -7782,8 +7787,8 @@ public class WindowManagerService extends IWindowManager.Stub
        public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
        public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
        public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;

        public static final int UPDATE_ANIMATION_SCALE = 51;
        public static final int WINDOW_REMOVE_TIMEOUT = 52;

        /**
         * Used to denote that an integer field in a message will not be used.
@@ -8396,6 +8401,18 @@ public class WindowManagerService extends IWindowManager.Stub
                    mAmInternal.notifyStartingWindowDrawn();
                }
                break;
                case WINDOW_REMOVE_TIMEOUT: {
                    final WindowState window = (WindowState) msg.obj;
                    synchronized(mWindowMap) {
                        // It's counterintuitive that we check that "mWindowRemovalAllowed"
                        // is false. But in fact if it's true, it means a remove has already
                        // been requested and we better just not do anything.
                        if (!window.mRemoved && !window.mWindowRemovalAllowed) {
                            removeWindowLocked(window);
                        }
                    }
                }
                break;
            }
            if (DEBUG_WINDOW_TRACE) {
                Slog.v(TAG_WM, "handleMessage: exit");