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

Commit 02d4bc63 authored by Iavor-Valentin Iftime's avatar Iavor-Valentin Iftime Committed by Automerger Merge Worker
Browse files

Merge "Fix Toast memory leaks" into udc-dev am: 6488edd6

parents 7653ff43 6488edd6
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import com.android.internal.annotations.GuardedBy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

@@ -205,7 +206,7 @@ public class Toast {
        INotificationManager service = getService();
        String pkg = mContext.getOpPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;
        tn.mNextView = new WeakReference<>(mNextView);
        final boolean isUiContext = mContext.isUiContext();
        final int displayId = mContext.getDisplayId();

@@ -622,7 +623,7 @@ public class Toast {
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
        View mView;
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
        View mNextView;
        WeakReference<View> mNextView;
        int mDuration;

        WindowManager mWM;
@@ -632,7 +633,7 @@ public class Toast {
        private final ToastPresenter mPresenter;

        @GuardedBy("mCallbacks")
        private final List<Callback> mCallbacks;
        private final WeakReference<List<Callback>> mCallbacks;

        /**
         * Creates a {@link ITransientNotification} object.
@@ -649,7 +650,7 @@ public class Toast {
            mParams = mPresenter.getLayoutParams();
            mPackageName = packageName;
            mToken = token;
            mCallbacks = callbacks;
            mCallbacks = new WeakReference<>(callbacks);

            mHandler = new Handler(looper, null) {
                @Override
@@ -685,7 +686,11 @@ public class Toast {

        private List<Callback> getCallbacks() {
            synchronized (mCallbacks) {
                return new ArrayList<>(mCallbacks);
                if (mCallbacks.get() != null) {
                    return new ArrayList<>(mCallbacks.get());
                } else {
                    return new ArrayList<>();
                }
            }
        }

@@ -721,15 +726,17 @@ public class Toast {
            if (mHandler.hasMessages(CANCEL) || mHandler.hasMessages(HIDE)) {
                return;
            }
            if (mView != mNextView) {
            if (mNextView != null && mView != mNextView.get()) {
                // remove the old view if necessary
                handleHide();
                mView = mNextView;
                mView = mNextView.get();
                if (mView != null) {
                    mPresenter.show(mView, mToken, windowToken, mDuration, mGravity, mX, mY,
                            mHorizontalMargin, mVerticalMargin,
                            new CallbackBinder(getCallbacks(), mHandler));
                }
            }
        }

        @UnsupportedAppUsage
        public void handleHide() {
+31 −19
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.lang.ref.WeakReference;

/**
 * Class responsible for toast presentation inside app's process and in system UI.
 *
@@ -87,25 +89,33 @@ public class ToastPresenter {
        return view;
    }

    private final Context mContext;
    private final Resources mResources;
    private final WindowManager mWindowManager;
    private final IAccessibilityManager mAccessibilityManager;
    private final WeakReference<WindowManager> mWindowManager;
    private final WeakReference<AccessibilityManager> mAccessibilityManager;
    private final INotificationManager mNotificationManager;
    private final String mPackageName;
    private final String mContextPackageName;
    private final WindowManager.LayoutParams mParams;
    @Nullable private View mView;
    @Nullable private IBinder mToken;

    public ToastPresenter(Context context, IAccessibilityManager accessibilityManager,
            INotificationManager notificationManager, String packageName) {
        mContext = context;
        mResources = context.getResources();
        mWindowManager = context.getSystemService(WindowManager.class);
        mWindowManager = new WeakReference<>(context.getSystemService(WindowManager.class));
        mNotificationManager = notificationManager;
        mPackageName = packageName;
        mAccessibilityManager = accessibilityManager;
        mContextPackageName = context.getPackageName();
        mParams = createLayoutParams();

        // We obtain AccessibilityManager manually via its constructor instead of using method
        // AccessibilityManager.getInstance() for 2 reasons:
        //   1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
        //   2. getInstance() caches the instance for the process even if we pass a different
        //      context to it. This is problematic for multi-user because callers can pass a context
        //      created via Context.createContextAsUser().
        mAccessibilityManager = new WeakReference<>(
                new AccessibilityManager(context, accessibilityManager, context.getUserId()));
    }

    public String getPackageName() {
@@ -173,7 +183,7 @@ public class ToastPresenter {
        params.y = yOffset;
        params.horizontalMargin = horizontalMargin;
        params.verticalMargin = verticalMargin;
        params.packageName = mContext.getPackageName();
        params.packageName = mContextPackageName;
        params.hideTimeoutMilliseconds =
                (duration == Toast.LENGTH_LONG) ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
        params.token = windowToken;
@@ -270,8 +280,9 @@ public class ToastPresenter {
    public void hide(@Nullable ITransientNotificationCallback callback) {
        checkState(mView != null, "No toast to hide.");

        if (mView.getParent() != null) {
            mWindowManager.removeViewImmediate(mView);
        final WindowManager windowManager = mWindowManager.get();
        if (mView.getParent() != null && windowManager != null) {
            windowManager.removeViewImmediate(mView);
        }
        try {
            mNotificationManager.finishToken(mPackageName, mToken);
@@ -295,14 +306,11 @@ public class ToastPresenter {
     * enabled.
     */
    public void trySendAccessibilityEvent(View view, String packageName) {
        // We obtain AccessibilityManager manually via its constructor instead of using method
        // AccessibilityManager.getInstance() for 2 reasons:
        //   1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
        //   2. getInstance() caches the instance for the process even if we pass a different
        //      context to it. This is problematic for multi-user because callers can pass a context
        //      created via Context.createContextAsUser().
        final AccessibilityManager accessibilityManager =
                new AccessibilityManager(mContext, mAccessibilityManager, mContext.getUserId());
        final AccessibilityManager accessibilityManager = mAccessibilityManager.get();
        if (accessibilityManager == null) {
            return;
        }

        if (!accessibilityManager.isEnabled()) {
            accessibilityManager.removeClient();
            return;
@@ -320,11 +328,15 @@ public class ToastPresenter {
    }

    private void addToastView() {
        final WindowManager windowManager = mWindowManager.get();
        if (windowManager == null) {
            return;
        }
        if (mView.getParent() != null) {
            mWindowManager.removeView(mView);
            windowManager.removeView(mView);
        }
        try {
            mWindowManager.addView(mView, mParams);
            windowManager.addView(mView, mParams);
        } catch (WindowManager.BadTokenException e) {
            // Since the notification manager service cancels the token right after it notifies us
            // to cancel the toast there is an inherent race and we may attempt to add a window