Show toasts from system/sysUI to all users am: 0a7ced1dd3

Change-Id: Iad91e5ecdad2f1ae542c69fe9d03e64ba39adc71
This commit is contained in:
Automerger Merge Worker
2020-02-28 21:44:37 +00:00
6 changed files with 75 additions and 6 deletions

View File

@@ -651,7 +651,7 @@ public class Toast {
} }
}; };
presenter.startLayoutParams(mParams); presenter.startLayoutParams(mParams, packageName);
} }
private List<Callback> getCallbacks() { private List<Callback> getCallbacks() {

View File

@@ -18,6 +18,7 @@ package android.widget;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.os.IBinder; import android.os.IBinder;
import android.view.Gravity; import android.view.Gravity;
@@ -28,6 +29,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
/** /**
* Class responsible for toast presentation inside app's process and in system UI. * 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 static final long LONG_DURATION_TIMEOUT = 7000;
private final Context mContext; private final Context mContext;
private final Resources mResources;
private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager mAccessibilityManager;
public ToastPresenter(Context context, AccessibilityManager accessibilityManager) { public ToastPresenter(Context context, AccessibilityManager accessibilityManager) {
mContext = context; mContext = context;
mResources = context.getResources();
mAccessibilityManager = accessibilityManager; mAccessibilityManager = accessibilityManager;
} }
/** /**
* Initializes {@code params} with default values for toasts. * 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.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.format = PixelFormat.TRANSLUCENT; params.format = PixelFormat.TRANSLUCENT;
@@ -60,6 +64,7 @@ public class ToastPresenter {
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;
setShowForAllUsersIfApplicable(params, packageName);
} }
/** /**
@@ -69,7 +74,7 @@ public class ToastPresenter {
public void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken, public void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken,
int duration, int gravity, int xOffset, int yOffset, float horizontalMargin, int duration, int gravity, int xOffset, int yOffset, float horizontalMargin,
float verticalMargin) { float verticalMargin) {
Configuration config = mContext.getResources().getConfiguration(); Configuration config = mResources.getConfiguration();
int absGravity = Gravity.getAbsoluteGravity(gravity, config.getLayoutDirection()); int absGravity = Gravity.getAbsoluteGravity(gravity, config.getLayoutDirection());
params.gravity = absGravity; params.gravity = absGravity;
if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
@@ -88,6 +93,32 @@ public class ToastPresenter {
params.token = windowToken; 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}. * Returns the default text toast view for message {@code text}.
*/ */

View File

@@ -4410,4 +4410,13 @@
<!-- Whether to default to an expanded list of users on the lock screen user switcher. --> <!-- Whether to default to an expanded list of users on the lock screen user switcher. -->
<bool name="config_expandLockScreenUserSwitcher">false</bool> <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> </resources>

View File

@@ -3903,4 +3903,6 @@
<java-symbol type="bool" name="config_expandLockScreenUserSwitcher" /> <java-symbol type="bool" name="config_expandLockScreenUserSwitcher" />
<java-symbol type="string" name="loading" /> <java-symbol type="string" name="loading" />
<java-symbol type="array" name="config_toastCrossUserPackages" />
</resources> </resources>

View File

@@ -95,7 +95,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
hideCurrentToast(); hideCurrentToast();
} }
View view = mPresenter.getTextToastView(text); View view = mPresenter.getTextToastView(text);
LayoutParams params = getLayoutParams(windowToken, duration); LayoutParams params = getLayoutParams(packageName, windowToken, duration);
mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback); mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback);
try { try {
mWindowManager.addView(view, params); mWindowManager.addView(view, params);
@@ -145,9 +145,9 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
mCurrentToast = null; mCurrentToast = null;
} }
private LayoutParams getLayoutParams(IBinder windowToken, int duration) { private LayoutParams getLayoutParams(String packageName, IBinder windowToken, int duration) {
WindowManager.LayoutParams params = new WindowManager.LayoutParams(); WindowManager.LayoutParams params = new WindowManager.LayoutParams();
mPresenter.startLayoutParams(params); mPresenter.startLayoutParams(params, packageName);
int gravity = mContext.getResources().getInteger( int gravity = mContext.getResources().getInteger(
com.android.internal.R.integer.config_toastDefaultGravity); com.android.internal.R.integer.config_toastDefaultGravity);
int yOffset = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset); int yOffset = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);

View File

@@ -105,6 +105,33 @@ public class ToastUITest extends SysuiTestCase {
assertThat(windowParams.packageName).isEqualTo(mContext.getPackageName()); assertThat(windowParams.packageName).isEqualTo(mContext.getPackageName());
assertThat(windowParams.getTitle()).isEqualTo("Toast"); assertThat(windowParams.getTitle()).isEqualTo("Toast");
assertThat(windowParams.token).isEqualTo(WINDOW_TOKEN_1); assertThat(windowParams.token).isEqualTo(WINDOW_TOKEN_1);
assertThat(windowParams.privateFlags
& WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isEqualTo(0);
}
@Test
public void testShowToast_forAndroidPackage_addsAllUserFlag() throws Exception {
mToastUI.showToast("android", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
verify(mWindowManager).addView(any(), mParamsCaptor.capture());
ViewGroup.LayoutParams params = mParamsCaptor.getValue();
assertThat(params).isInstanceOf(WindowManager.LayoutParams.class);
WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
assertThat(windowParams.privateFlags
& WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isNotEqualTo(0);
}
@Test
public void testShowToast_forSystemUiPackage_addsAllUserFlag() throws Exception {
mToastUI.showToast("com.android.systemui", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
null);
verify(mWindowManager).addView(any(), mParamsCaptor.capture());
ViewGroup.LayoutParams params = mParamsCaptor.getValue();
assertThat(params).isInstanceOf(WindowManager.LayoutParams.class);
WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
assertThat(windowParams.privateFlags
& WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isNotEqualTo(0);
} }
@Test @Test