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

Commit 0a7ced1d authored by Bernardo Rufino's avatar Bernardo Rufino
Browse files

Show toasts from system/sysUI to all users

The package name test is safe:
* If it's used by Toast class in an app, apps have access to layout
  params anyway via getWindowParams() and applied flag is already
  protected by INTERNAL_SYSTEM_WINDOW permission.
* If it's used by ToastUI class in sys UI on behalf of another app,
  sys UI is trusted domain and can't be messed up by another app. It
  also has INTERNAL_SYSTEM_WINDOW permission.

Bug: 149408635
Test: atest ToastUITest android.widget.cts.ToastTest
      android.widget.cts29.ToastTest android.server.wm.ToastTest
Test: Change phone to vibration/silent in secondary user and observe
      toast is displayed.

Change-Id: I227e9f74166300fcb3ba8f3871b464afe6ec6a28
Merged-In: I227e9f74166300fcb3ba8f3871b464afe6ec6a28
(cherry picked from commit caef507a)
parent f9de0572
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -651,7 +651,7 @@ public class Toast {
                }
            };

            presenter.startLayoutParams(mParams);
            presenter.startLayoutParams(mParams, packageName);
        }

        private List<Callback> getCallbacks() {
+33 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.widget;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
@@ -28,6 +29,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;

import com.android.internal.R;
import com.android.internal.util.ArrayUtils;

/**
 * Class responsible for toast presentation inside app's process and in system UI.
@@ -39,17 +41,19 @@ public class ToastPresenter {
    private static final long LONG_DURATION_TIMEOUT = 7000;

    private final Context mContext;
    private final Resources mResources;
    private final AccessibilityManager mAccessibilityManager;

    public ToastPresenter(Context context, AccessibilityManager accessibilityManager) {
        mContext = context;
        mResources = context.getResources();
        mAccessibilityManager = accessibilityManager;
    }

    /**
     * Initializes {@code params} with default values for toasts.
     */
    public void startLayoutParams(WindowManager.LayoutParams params) {
    public void startLayoutParams(WindowManager.LayoutParams params, String packageName) {
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
@@ -60,6 +64,7 @@ public class ToastPresenter {
        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        setShowForAllUsersIfApplicable(params, packageName);
    }

    /**
@@ -69,7 +74,7 @@ public class ToastPresenter {
    public void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken,
            int duration, int gravity, int xOffset, int yOffset, float horizontalMargin,
            float verticalMargin) {
        Configuration config = mContext.getResources().getConfiguration();
        Configuration config = mResources.getConfiguration();
        int absGravity = Gravity.getAbsoluteGravity(gravity, config.getLayoutDirection());
        params.gravity = absGravity;
        if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
@@ -88,6 +93,32 @@ public class ToastPresenter {
        params.token = windowToken;
    }

    /**
     * Sets {@link WindowManager.LayoutParams#SYSTEM_FLAG_SHOW_FOR_ALL_USERS} flag if {@code
     * packageName} is a cross-user package.
     *
     * Implementation note:
     *     This code is safe to be executed in SystemUI and the app's process:
     *         <li>SystemUI: It's running on a trusted domain so apps can't tamper with it. SystemUI
     *             has the permission INTERNAL_SYSTEM_WINDOW needed by the flag, so SystemUI can add
     *             the flag on behalf of those packages, which all contain INTERNAL_SYSTEM_WINDOW
     *             permission.
     *         <li>App: The flag being added is protected behind INTERNAL_SYSTEM_WINDOW permission
     *             and any app can already add that flag via getWindowParams() if it has that
     *             permission, so we are just doing this automatically for cross-user packages.
     */
    private void setShowForAllUsersIfApplicable(WindowManager.LayoutParams params,
            String packageName) {
        if (isCrossUserPackage(packageName)) {
            params.privateFlags = WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
        }
    }

    private boolean isCrossUserPackage(String packageName) {
        String[] packages = mResources.getStringArray(R.array.config_toastCrossUserPackages);
        return ArrayUtils.contains(packages, packageName);
    }

    /**
     * Returns the default text toast view for message {@code text}.
     */
+9 −0
Original line number Diff line number Diff line
@@ -4410,4 +4410,13 @@

    <!-- Whether to default to an expanded list of users on the lock screen user switcher. -->
    <bool name="config_expandLockScreenUserSwitcher">false</bool>

    <!-- Toasts posted from these packages will be shown to the current user, regardless of the user
         the process belongs to. This is useful for packages that run under a single user but serve
         multiple users, e.g. the system.
         These packages MUST be able to add flag SYSTEM_FLAG_SHOW_FOR_ALL_USERS to a window. -->
    <string-array name="config_toastCrossUserPackages" translatable="false">
        <item>android</item>
        <item>com.android.systemui</item>
    </string-array>
</resources>
+2 −0
Original line number Diff line number Diff line
@@ -3903,4 +3903,6 @@
  <java-symbol type="bool" name="config_expandLockScreenUserSwitcher" />

  <java-symbol type="string" name="loading" />

  <java-symbol type="array" name="config_toastCrossUserPackages" />
</resources>
+3 −3
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
            hideCurrentToast();
        }
        View view = mPresenter.getTextToastView(text);
        LayoutParams params = getLayoutParams(windowToken, duration);
        LayoutParams params = getLayoutParams(packageName, windowToken, duration);
        mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback);
        try {
            mWindowManager.addView(view, params);
@@ -145,9 +145,9 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
        mCurrentToast = null;
    }

    private LayoutParams getLayoutParams(IBinder windowToken, int duration) {
    private LayoutParams getLayoutParams(String packageName, IBinder windowToken, int duration) {
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        mPresenter.startLayoutParams(params);
        mPresenter.startLayoutParams(params, packageName);
        int gravity = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_toastDefaultGravity);
        int yOffset = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);
Loading