diff options
author | Bernardo Rufino <brufino@google.com> | 2020-04-06 21:59:20 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-04-06 21:59:20 +0000 |
commit | 2de79fb6fdfe421dfa6d55bed37da746e7cc6137 (patch) | |
tree | b066701a483df9a6fde3387140106b703b3c2ead | |
parent | 7e9bfdfd638e167ff94bbfc2ec977dfaf83b08f0 (diff) | |
parent | 78f5d83ac8bfe91829709c6dfc5850325f24efa7 (diff) |
Merge "Wire user info and use user context for text toasts" into rvc-dev
13 files changed, 155 insertions, 84 deletions
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 08b32930971a..fb962103990c 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -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; diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java index e9d4aa668891..2679c69be4f6 100644 --- a/core/java/android/widget/ToastPresenter.java +++ b/core/java/android/widget/ToastPresenter.java @@ -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(); } diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 5b79b184b6a4..38f5f3279c8e 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -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}. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 94afde786e78..24195156d8cf 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 @@ 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; diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java index 9ccb9bf5b62b..9b465ae15478 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.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); } 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 65fbe79b5e9f..0a10ab2fbf02 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.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,7 +148,8 @@ 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); + mToastUI.showToast(ANDROID_UID, "android", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + null); verify(mWindowManager).addView(any(), mParamsCaptor.capture()); ViewGroup.LayoutParams params = mParamsCaptor.getValue(); @@ -123,8 +161,8 @@ public class ToastUITest extends SysuiTestCase { @Test public void testShowToast_forSystemUiPackage_addsAllUserFlag() throws Exception { - mToastUI.showToast("com.android.systemui", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, - null); + 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(); @@ -136,7 +174,7 @@ public class ToastUITest extends SysuiTestCase { @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); - - mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null); + // 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(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; + }; + } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index ed3b9f1fc265..776db63ced73 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 @@ 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); 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 aca6f4853597..2b91a00f9da5 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.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() + "}"; 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 3c231b445f62..544520edc7fc 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.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() + "}"; 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 ef75a6f5dd7b..7915f7013227 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 @@ 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; diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index d88dccb9afeb..26497d8b0290 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 @@ 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); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 78ef68c09988..d7a0c9871b48 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 @@ 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) { } } } 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 f9596b53407f..15220e1ff54a 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 @@ 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 |