Merge "Wire user info and use user context for text toasts" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2de79fb6fd
@@ -43,7 +43,7 @@ import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
@@ -610,10 +610,10 @@ public class Toast {
|
||||
*/
|
||||
TN(Context context, String packageName, Binder token, List<Callback> callbacks,
|
||||
@Nullable Looper looper) {
|
||||
WindowManager windowManager = context.getSystemService(WindowManager.class);
|
||||
AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(context);
|
||||
mPresenter = new ToastPresenter(context, windowManager, accessibilityManager,
|
||||
getService(), packageName);
|
||||
IAccessibilityManager accessibilityManager = IAccessibilityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
|
||||
mPresenter = new ToastPresenter(context, accessibilityManager, getService(),
|
||||
packageName);
|
||||
mParams = mPresenter.getLayoutParams();
|
||||
mPackageName = packageName;
|
||||
mToken = token;
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.content.res.Resources;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -34,8 +35,10 @@ import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
/**
|
||||
@@ -49,12 +52,14 @@ public class ToastPresenter {
|
||||
private static final long SHORT_DURATION_TIMEOUT = 4000;
|
||||
private static final long LONG_DURATION_TIMEOUT = 7000;
|
||||
|
||||
@VisibleForTesting
|
||||
public static final int TEXT_TOAST_LAYOUT = R.layout.transient_notification;
|
||||
|
||||
/**
|
||||
* Returns the default text toast view for message {@code text}.
|
||||
*/
|
||||
public static View getTextToastView(Context context, CharSequence text) {
|
||||
View view = LayoutInflater.from(context).inflate(
|
||||
R.layout.transient_notification, null);
|
||||
View view = LayoutInflater.from(context).inflate(TEXT_TOAST_LAYOUT, null);
|
||||
TextView textView = view.findViewById(com.android.internal.R.id.message);
|
||||
textView.setText(text);
|
||||
return view;
|
||||
@@ -70,15 +75,23 @@ public class ToastPresenter {
|
||||
@Nullable private View mView;
|
||||
@Nullable private IBinder mToken;
|
||||
|
||||
public ToastPresenter(Context context, WindowManager windowManager,
|
||||
AccessibilityManager accessibilityManager,
|
||||
public ToastPresenter(Context context, IAccessibilityManager accessibilityManager,
|
||||
INotificationManager notificationManager, String packageName) {
|
||||
mContext = context;
|
||||
mResources = context.getResources();
|
||||
mWindowManager = windowManager;
|
||||
mAccessibilityManager = accessibilityManager;
|
||||
mWindowManager = context.getSystemService(WindowManager.class);
|
||||
mNotificationManager = notificationManager;
|
||||
mPackageName = 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().
|
||||
mAccessibilityManager = new AccessibilityManager(context, accessibilityManager,
|
||||
UserHandle.getCallingUserId());
|
||||
|
||||
mParams = createLayoutParams();
|
||||
}
|
||||
|
||||
|
||||
@@ -204,8 +204,8 @@ oneway interface IStatusBar
|
||||
/**
|
||||
* Displays a text toast.
|
||||
*/
|
||||
void showToast(String packageName, IBinder token, CharSequence text, IBinder windowToken,
|
||||
int duration, @nullable ITransientNotificationCallback callback);
|
||||
void showToast(int uid, String packageName, IBinder token, CharSequence text,
|
||||
IBinder windowToken, int duration, @nullable ITransientNotificationCallback callback);
|
||||
|
||||
/**
|
||||
* Cancels toast with token {@code token} in {@code packageName}.
|
||||
|
||||
@@ -322,10 +322,10 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
|
||||
default void suppressAmbientDisplay(boolean suppress) { }
|
||||
|
||||
/**
|
||||
* @see IStatusBar#showToast(String, IBinder, CharSequence, IBinder, int,
|
||||
* @see IStatusBar#showToast(int, String, IBinder, CharSequence, IBinder, int,
|
||||
* ITransientNotificationCallback)
|
||||
*/
|
||||
default void showToast(String packageName, IBinder token, CharSequence text,
|
||||
default void showToast(int uid, String packageName, IBinder token, CharSequence text,
|
||||
IBinder windowToken, int duration,
|
||||
@Nullable ITransientNotificationCallback callback) { }
|
||||
|
||||
@@ -798,7 +798,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showToast(String packageName, IBinder token, CharSequence text,
|
||||
public void showToast(int uid, String packageName, IBinder token, CharSequence text,
|
||||
IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) {
|
||||
synchronized (mLock) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
@@ -807,7 +807,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
|
||||
args.arg3 = text;
|
||||
args.arg4 = windowToken;
|
||||
args.arg5 = callback;
|
||||
args.argi1 = duration;
|
||||
args.argi1 = uid;
|
||||
args.argi2 = duration;
|
||||
mHandler.obtainMessage(MSG_SHOW_TOAST, args).sendToTarget();
|
||||
}
|
||||
}
|
||||
@@ -1276,9 +1277,10 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
|
||||
IBinder windowToken = (IBinder) args.arg4;
|
||||
ITransientNotificationCallback callback =
|
||||
(ITransientNotificationCallback) args.arg5;
|
||||
int duration = args.argi1;
|
||||
int uid = args.argi1;
|
||||
int duration = args.argi2;
|
||||
for (Callbacks callbacks : mCallbacks) {
|
||||
callbacks.showToast(packageName, token, text, windowToken, duration,
|
||||
callbacks.showToast(uid, packageName, token, text, windowToken, duration,
|
||||
callback);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -24,10 +24,10 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.IBinder;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
import android.widget.ToastPresenter;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -48,9 +48,8 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
|
||||
private static final String TAG = "ToastUI";
|
||||
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final WindowManager mWindowManager;
|
||||
private final INotificationManager mNotificationManager;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
private final IAccessibilityManager mAccessibilityManager;
|
||||
private final int mGravity;
|
||||
private final int mY;
|
||||
@Nullable private ToastPresenter mPresenter;
|
||||
@@ -59,18 +58,17 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
|
||||
@Inject
|
||||
public ToastUI(Context context, CommandQueue commandQueue) {
|
||||
this(context, commandQueue,
|
||||
(WindowManager) context.getSystemService(Context.WINDOW_SERVICE),
|
||||
INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE)),
|
||||
AccessibilityManager.getInstance(context));
|
||||
IAccessibilityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ToastUI(Context context, CommandQueue commandQueue, WindowManager windowManager,
|
||||
INotificationManager notificationManager, AccessibilityManager accessibilityManager) {
|
||||
ToastUI(Context context, CommandQueue commandQueue, INotificationManager notificationManager,
|
||||
@Nullable IAccessibilityManager accessibilityManager) {
|
||||
super(context);
|
||||
mCommandQueue = commandQueue;
|
||||
mWindowManager = windowManager;
|
||||
mNotificationManager = notificationManager;
|
||||
mAccessibilityManager = accessibilityManager;
|
||||
Resources resources = mContext.getResources();
|
||||
@@ -85,15 +83,16 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
|
||||
|
||||
@Override
|
||||
@MainThread
|
||||
public void showToast(String packageName, IBinder token, CharSequence text,
|
||||
public void showToast(int uid, String packageName, IBinder token, CharSequence text,
|
||||
IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) {
|
||||
if (mPresenter != null) {
|
||||
hideCurrentToast();
|
||||
}
|
||||
View view = ToastPresenter.getTextToastView(mContext, text);
|
||||
Context context = mContext.createContextAsUser(UserHandle.getUserHandleForUid(uid), 0);
|
||||
View view = ToastPresenter.getTextToastView(context, text);
|
||||
mCallback = callback;
|
||||
mPresenter = new ToastPresenter(mContext, mWindowManager, mAccessibilityManager,
|
||||
mNotificationManager, packageName);
|
||||
mPresenter = new ToastPresenter(context, mAccessibilityManager, mNotificationManager,
|
||||
packageName);
|
||||
mPresenter.show(view, token, windowToken, duration, mGravity, 0, mY, 0, 0, mCallback);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,29 +16,43 @@
|
||||
|
||||
package com.android.systemui.toast;
|
||||
|
||||
import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
|
||||
import static android.widget.ToastPresenter.TEXT_TOAST_LAYOUT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.INotificationManager;
|
||||
import android.app.ITransientNotificationCallback;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToastPresenter;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.IntPair;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
|
||||
@@ -49,32 +63,53 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class ToastUITest extends SysuiTestCase {
|
||||
private static final int ANDROID_UID = 1000;
|
||||
private static final int SYSTEMUI_UID = 10140;
|
||||
|
||||
private static final int UID_1 = 10255;
|
||||
private static final String PACKAGE_NAME_1 = "com.example1.test";
|
||||
private static final Binder TOKEN_1 = new Binder();
|
||||
private static final Binder WINDOW_TOKEN_1 = new Binder();
|
||||
|
||||
private static final int UID_2 = 10256;
|
||||
private static final String PACKAGE_NAME_2 = "com.example2.test";
|
||||
private static final Binder TOKEN_2 = new Binder();
|
||||
private static final Binder WINDOW_TOKEN_2 = new Binder();
|
||||
|
||||
private static final String TEXT = "Hello World";
|
||||
private static final int MESSAGE_RES_ID = R.id.message;
|
||||
|
||||
private Context mContextSpy;
|
||||
private ToastUI mToastUI;
|
||||
@Mock private LayoutInflater mLayoutInflater;
|
||||
@Mock private CommandQueue mCommandQueue;
|
||||
@Mock private WindowManager mWindowManager;
|
||||
@Mock private INotificationManager mNotificationManager;
|
||||
@Mock private AccessibilityManager mAccessibilityManager;
|
||||
@Mock private IAccessibilityManager mAccessibilityManager;
|
||||
@Mock private ITransientNotificationCallback mCallback;
|
||||
@Captor private ArgumentCaptor<View> mViewCaptor;
|
||||
@Captor private ArgumentCaptor<ViewGroup.LayoutParams> mParamsCaptor;
|
||||
private ToastUI mToastUI;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mToastUI = new ToastUI(mContext, mCommandQueue, mWindowManager, mNotificationManager,
|
||||
|
||||
// This is because inflate will result in WindowManager (WM) calls, which will fail since we
|
||||
// are mocking it, so we mock LayoutInflater with the view obtained before mocking WM.
|
||||
View view = ToastPresenter.getTextToastView(mContext, TEXT);
|
||||
when(mLayoutInflater.inflate(eq(TEXT_TOAST_LAYOUT), any())).thenReturn(view);
|
||||
mContext.addMockSystemService(LayoutInflater.class, mLayoutInflater);
|
||||
|
||||
mContext.addMockSystemService(WindowManager.class, mWindowManager);
|
||||
mContextSpy = spy(mContext);
|
||||
doReturn(mContextSpy).when(mContextSpy).createContextAsUser(any(), anyInt());
|
||||
|
||||
mToastUI = new ToastUI(mContextSpy, mCommandQueue, mNotificationManager,
|
||||
mAccessibilityManager);
|
||||
}
|
||||
|
||||
@@ -87,7 +122,8 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowToast_addsCorrectViewToWindowManager() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
null);
|
||||
|
||||
verify(mWindowManager).addView(mViewCaptor.capture(), any());
|
||||
View view = mViewCaptor.getValue();
|
||||
@@ -96,13 +132,14 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowToast_addsViewWithCorrectLayoutParamsToWindowManager() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, 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.packageName).isEqualTo(mContext.getPackageName());
|
||||
assertThat(windowParams.packageName).isEqualTo(mContextSpy.getPackageName());
|
||||
assertThat(windowParams.getTitle()).isEqualTo("Toast");
|
||||
assertThat(windowParams.token).isEqualTo(WINDOW_TOKEN_1);
|
||||
assertThat(windowParams.privateFlags
|
||||
@@ -111,19 +148,7 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@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,
|
||||
mToastUI.showToast(ANDROID_UID, "android", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
null);
|
||||
|
||||
verify(mWindowManager).addView(any(), mParamsCaptor.capture());
|
||||
@@ -134,9 +159,22 @@ public class ToastUITest extends SysuiTestCase {
|
||||
& WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isNotEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowToast_forSystemUiPackage_addsAllUserFlag() throws Exception {
|
||||
mToastUI.showToast(SYSTEMUI_UID, "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
|
||||
public void testShowToast_callsCallback() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
|
||||
verify(mCallback).onToastShown();
|
||||
@@ -144,14 +182,24 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowToast_sendsAccessibilityEvent() throws Exception {
|
||||
when(mAccessibilityManager.isEnabled()).thenReturn(true);
|
||||
// Enable accessibility
|
||||
when(mAccessibilityManager.addClient(any(), anyInt())).thenReturn(
|
||||
IntPair.of(STATE_FLAG_ACCESSIBILITY_ENABLED, AccessibilityEvent.TYPES_ALL_MASK));
|
||||
// AccessibilityManager recycles the event that goes over the wire after making the binder
|
||||
// call to the service. Since we are mocking the service, that call is local, so if we use
|
||||
// ArgumentCaptor or ArgumentMatcher it will retain a reference to the recycled event, which
|
||||
// will already have its state reset by the time we verify its contents. So, instead, we
|
||||
// serialize it at call-time and later on deserialize it to verity its contents.
|
||||
Parcel eventParcel = Parcel.obtain();
|
||||
doAnswer(writeArgumentToParcel(0, eventParcel)).when(
|
||||
mAccessibilityManager).sendAccessibilityEvent(any(), anyInt());
|
||||
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
null);
|
||||
|
||||
ArgumentCaptor<AccessibilityEvent> eventCaptor = ArgumentCaptor.forClass(
|
||||
AccessibilityEvent.class);
|
||||
verify(mAccessibilityManager).sendAccessibilityEvent(eventCaptor.capture());
|
||||
AccessibilityEvent event = eventCaptor.getValue();
|
||||
eventParcel.setDataPosition(0);
|
||||
assertThat(eventParcel.dataSize()).isGreaterThan(0);
|
||||
AccessibilityEvent event = AccessibilityEvent.CREATOR.createFromParcel(eventParcel);
|
||||
assertThat(event.getEventType()).isEqualTo(
|
||||
AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
|
||||
assertThat(event.getClassName()).isEqualTo(Toast.class.getName());
|
||||
@@ -160,7 +208,7 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testHideToast_removesView() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
View view = verifyWmAddViewAndAttachToParent();
|
||||
|
||||
@@ -171,7 +219,7 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testHideToast_finishesToken() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
|
||||
mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1);
|
||||
@@ -181,7 +229,7 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testHideToast_callsCallback() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
|
||||
mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1);
|
||||
@@ -191,7 +239,7 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testHideToast_whenNotCurrentToastToken_doesNotHideToast() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
|
||||
mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_2);
|
||||
@@ -201,7 +249,7 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testHideToast_whenNotCurrentToastPackage_doesNotHideToast() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
|
||||
mToastUI.hideToast(PACKAGE_NAME_2, TOKEN_1);
|
||||
@@ -211,11 +259,12 @@ public class ToastUITest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowToast_afterShowToast_hidesCurrentToast() throws Exception {
|
||||
mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
|
||||
mCallback);
|
||||
View view = verifyWmAddViewAndAttachToParent();
|
||||
|
||||
mToastUI.showToast(PACKAGE_NAME_2, TOKEN_2, TEXT, WINDOW_TOKEN_2, Toast.LENGTH_LONG, null);
|
||||
mToastUI.showToast(UID_2, PACKAGE_NAME_2, TOKEN_2, TEXT, WINDOW_TOKEN_2, Toast.LENGTH_LONG,
|
||||
null);
|
||||
|
||||
verify(mWindowManager).removeViewImmediate(view);
|
||||
verify(mNotificationManager).finishToken(PACKAGE_NAME_1, TOKEN_1);
|
||||
@@ -227,8 +276,15 @@ public class ToastUITest extends SysuiTestCase {
|
||||
verify(mWindowManager).addView(viewCaptor.capture(), any());
|
||||
View view = viewCaptor.getValue();
|
||||
// Simulate attaching to view hierarchy
|
||||
ViewGroup parent = new FrameLayout(mContext);
|
||||
ViewGroup parent = new FrameLayout(mContextSpy);
|
||||
parent.addView(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
private Answer<Void> writeArgumentToParcel(int i, Parcel dest) {
|
||||
return inv -> {
|
||||
inv.<Parcelable>getArgument(i).writeToParcel(dest, 0);
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2745,15 +2745,15 @@ public class NotificationManagerService extends SystemService {
|
||||
return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
|
||||
}
|
||||
|
||||
private ToastRecord getToastRecord(int pid, String packageName, IBinder token,
|
||||
private ToastRecord getToastRecord(int uid, int pid, String packageName, IBinder token,
|
||||
@Nullable CharSequence text, @Nullable ITransientNotification callback, int duration,
|
||||
Binder windowToken, int displayId,
|
||||
@Nullable ITransientNotificationCallback textCallback) {
|
||||
if (callback == null) {
|
||||
return new TextToastRecord(this, mStatusBar, pid, packageName, token, text, duration,
|
||||
windowToken, displayId, textCallback);
|
||||
return new TextToastRecord(this, mStatusBar, uid, pid, packageName, token, text,
|
||||
duration, windowToken, displayId, textCallback);
|
||||
} else {
|
||||
return new CustomToastRecord(this, pid, packageName, token, callback, duration,
|
||||
return new CustomToastRecord(this, uid, pid, packageName, token, callback, duration,
|
||||
windowToken, displayId);
|
||||
}
|
||||
}
|
||||
@@ -2878,8 +2878,8 @@ public class NotificationManagerService extends SystemService {
|
||||
|
||||
Binder windowToken = new Binder();
|
||||
mWindowManagerInternal.addWindowToken(windowToken, TYPE_TOAST, displayId);
|
||||
record = getToastRecord(callingPid, pkg, token, text, callback, duration,
|
||||
windowToken, displayId, textCallback);
|
||||
record = getToastRecord(callingUid, callingPid, pkg, token, text, callback,
|
||||
duration, windowToken, displayId, textCallback);
|
||||
mToastQueue.add(record);
|
||||
index = mToastQueue.size() - 1;
|
||||
keepProcessAliveForToastIfNeededLocked(callingPid);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.app.ITransientNotification;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.notification.NotificationManagerService;
|
||||
@@ -35,11 +36,10 @@ public class CustomToastRecord extends ToastRecord {
|
||||
|
||||
public final ITransientNotification callback;
|
||||
|
||||
public CustomToastRecord(
|
||||
NotificationManagerService notificationManager, int pid, String packageName,
|
||||
IBinder token, ITransientNotification callback, int duration, Binder windowToken,
|
||||
int displayId) {
|
||||
super(notificationManager, pid, packageName, token, duration, windowToken, displayId);
|
||||
public CustomToastRecord(NotificationManagerService notificationManager, int uid, int pid,
|
||||
String packageName, IBinder token, ITransientNotification callback, int duration,
|
||||
Binder windowToken, int displayId) {
|
||||
super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId);
|
||||
this.callback = checkNotNull(callback);
|
||||
}
|
||||
|
||||
@@ -74,8 +74,8 @@ public class CustomToastRecord extends ToastRecord {
|
||||
public String toString() {
|
||||
return "CustomToastRecord{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid)
|
||||
+ " token=" + token
|
||||
+ " packageName=" + pkg
|
||||
+ " callback=" + callback
|
||||
+ " duration=" + getDuration()
|
||||
+ "}";
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
|
||||
import android.app.ITransientNotificationCallback;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.notification.NotificationManagerService;
|
||||
@@ -41,10 +42,10 @@ public class TextToastRecord extends ToastRecord {
|
||||
private final ITransientNotificationCallback mCallback;
|
||||
|
||||
public TextToastRecord(NotificationManagerService notificationManager,
|
||||
@Nullable StatusBarManagerInternal statusBarManager, int pid, String packageName,
|
||||
IBinder token, CharSequence text, int duration, Binder windowToken, int displayId,
|
||||
@Nullable ITransientNotificationCallback callback) {
|
||||
super(notificationManager, pid, packageName, token, duration, windowToken, displayId);
|
||||
@Nullable StatusBarManagerInternal statusBarManager, int uid, int pid,
|
||||
String packageName, IBinder token, CharSequence text, int duration, Binder windowToken,
|
||||
int displayId, @Nullable ITransientNotificationCallback callback) {
|
||||
super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId);
|
||||
mStatusBar = statusBarManager;
|
||||
mCallback = callback;
|
||||
this.text = checkNotNull(text);
|
||||
@@ -59,7 +60,7 @@ public class TextToastRecord extends ToastRecord {
|
||||
Slog.w(TAG, "StatusBar not available to show text toast for package " + pkg);
|
||||
return false;
|
||||
}
|
||||
mStatusBar.showToast(pkg, token, text, windowToken, getDuration(), mCallback);
|
||||
mStatusBar.showToast(uid, pkg, token, text, windowToken, getDuration(), mCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,8 +76,8 @@ public class TextToastRecord extends ToastRecord {
|
||||
public String toString() {
|
||||
return "TextToastRecord{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid)
|
||||
+ " token=" + token
|
||||
+ " packageName=" + pkg
|
||||
+ " text=" + text
|
||||
+ " duration=" + getDuration()
|
||||
+ "}";
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.PrintWriter;
|
||||
* Represents a toast, a transient notification.
|
||||
*/
|
||||
public abstract class ToastRecord {
|
||||
public final int uid;
|
||||
public final int pid;
|
||||
public final String pkg;
|
||||
public final IBinder token;
|
||||
@@ -36,11 +37,10 @@ public abstract class ToastRecord {
|
||||
protected final NotificationManagerService mNotificationManager;
|
||||
private int mDuration;
|
||||
|
||||
protected ToastRecord(
|
||||
NotificationManagerService notificationManager,
|
||||
int pid, String pkg, IBinder token, int duration,
|
||||
Binder windowToken, int displayId) {
|
||||
protected ToastRecord(NotificationManagerService notificationManager, int uid, int pid,
|
||||
String pkg, IBinder token, int duration, Binder windowToken, int displayId) {
|
||||
this.mNotificationManager = notificationManager;
|
||||
this.uid = uid;
|
||||
this.pid = pid;
|
||||
this.pkg = pkg;
|
||||
this.token = token;
|
||||
|
||||
@@ -131,7 +131,7 @@ public interface StatusBarManagerInternal {
|
||||
* @see com.android.internal.statusbar.IStatusBar#showToast(String, IBinder, CharSequence,
|
||||
* IBinder, int, ITransientNotificationCallback)
|
||||
*/
|
||||
void showToast(String packageName, IBinder token, CharSequence text,
|
||||
void showToast(int uid, String packageName, IBinder token, CharSequence text,
|
||||
IBinder windowToken, int duration,
|
||||
@Nullable ITransientNotificationCallback textCallback);
|
||||
|
||||
|
||||
@@ -502,12 +502,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showToast(String packageName, IBinder token, CharSequence text,
|
||||
public void showToast(int uid, String packageName, IBinder token, CharSequence text,
|
||||
IBinder windowToken, int duration,
|
||||
@Nullable ITransientNotificationCallback callback) {
|
||||
if (mBar != null) {
|
||||
try {
|
||||
mBar.showToast(packageName, token, text, windowToken, duration, callback);
|
||||
mBar.showToast(uid, packageName, token, text, windowToken, duration, callback);
|
||||
} catch (RemoteException ex) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4791,7 +4791,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
// enqueue toast -> no toasts enqueued
|
||||
((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
|
||||
"Text", 2000, 0, null);
|
||||
verify(mStatusBar).showToast(any(), any(), any(), any(), anyInt(), any());
|
||||
verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user