Merge "Wire user info and use user context for text toasts" into rvc-dev
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 08b3293..fb96210 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -43,7 +43,7 @@
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 @@
*/
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;
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index e9d4aa6..2679c69 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -27,6 +27,7 @@
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.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 @@
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 @@
@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();
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 5b79b18..38f5f32 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -204,8 +204,8 @@
/**
* 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}.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 94afde78..2419515 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -322,10 +322,10 @@
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 @@
}
@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 @@
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 @@
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;
diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
index 9ccb9bf..9b465ae 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
+++ b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
@@ -24,10 +24,10 @@
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 @@
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 @@
@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 @@
@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);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
index 65fbe79..0a10ab2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
@@ -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.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 @@
@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 @@
@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 @@
@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());
@@ -135,8 +160,21 @@
}
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
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;
+ };
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ed3b9f1..776db63 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2745,15 +2745,15 @@
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 @@
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);
diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
index aca6f48..2b91a00 100644
--- a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
@@ -23,6 +23,7 @@
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 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 String toString() {
return "CustomToastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ + " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid)
+ " token=" + token
- + " packageName=" + pkg
+ " callback=" + callback
+ " duration=" + getDuration()
+ "}";
diff --git a/services/core/java/com/android/server/notification/toast/TextToastRecord.java b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
index 3c231b4..544520e 100644
--- a/services/core/java/com/android/server/notification/toast/TextToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
@@ -23,6 +23,7 @@
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 @@
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 @@
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 String toString() {
return "TextToastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ + " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid)
+ " token=" + token
- + " packageName=" + pkg
+ " text=" + text
+ " duration=" + getDuration()
+ "}";
diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java
index ef75a6f..7915f70 100644
--- a/services/core/java/com/android/server/notification/toast/ToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java
@@ -28,6 +28,7 @@
* 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 @@
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;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index d88dccb..26497d8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -131,7 +131,7 @@
* @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);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 78ef68c..d7a0c987 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -502,12 +502,12 @@
}
@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) { }
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index f9596b5..15220e1 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4791,7 +4791,7 @@
// 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