From c05f6adebc9c92f4586d1f498f75e0c12ccb80b7 Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Wed, 29 Jan 2020 19:43:27 +0000 Subject: [PATCH] Add unit tests for ToastUI Bug: 144754526 Fix: 147802103 Test: atest ToastUITest Change-Id: I277db0d8770da62fcfeaa794a7df44e500396733 --- .../com/android/systemui/toast/ToastUI.java | 18 +- .../android/systemui/toast/ToastUITest.java | 207 ++++++++++++++++++ 2 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java index dea8c5d49dfc5..edab4a72d8c8f 100644 --- a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java +++ b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java @@ -38,6 +38,7 @@ import android.widget.TextView; import android.widget.Toast; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.SystemUI; import com.android.systemui.statusbar.CommandQueue; @@ -67,12 +68,21 @@ 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)); + } + + @VisibleForTesting + ToastUI(Context context, CommandQueue commandQueue, WindowManager windowManager, + INotificationManager notificationManager, AccessibilityManager accessibilityManager) { super(context); mCommandQueue = commandQueue; - mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - mNotificationManager = INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - mAccessibilityManager = AccessibilityManager.getInstance(context); + mWindowManager = windowManager; + mNotificationManager = notificationManager; + mAccessibilityManager = accessibilityManager; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java new file mode 100644 index 0000000000000..d58f2c9c17917 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.toast; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.INotificationManager; +import android.app.ITransientNotificationCallback; +import android.os.Binder; +import android.testing.AndroidTestingRunner; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.widget.FrameLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.test.filters.SmallTest; + +import com.android.internal.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.CommandQueue; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class ToastUITest extends SysuiTestCase { + 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 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; + + @Mock private CommandQueue mCommandQueue; + @Mock private WindowManager mWindowManager; + @Mock private INotificationManager mNotificationManager; + @Mock private AccessibilityManager mAccessibilityManager; + @Mock private ITransientNotificationCallback mCallback; + @Captor private ArgumentCaptor mViewCaptor; + @Captor private ArgumentCaptor mParamsCaptor; + private ToastUI mToastUI; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mToastUI = new ToastUI(mContext, mCommandQueue, mWindowManager, mNotificationManager, + mAccessibilityManager); + } + + @Test + public void testStart_addToastUIAsCallbackToCommandQueue() throws Exception { + mToastUI.start(); + + verify(mCommandQueue).addCallback(mToastUI); + } + + @Test + public void testShowToast_addsCorrectViewToWindowManager() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null); + + verify(mWindowManager).addView(mViewCaptor.capture(), any()); + View view = mViewCaptor.getValue(); + assertThat(((TextView) view.findViewById(MESSAGE_RES_ID)).getText()).isEqualTo(TEXT); + } + + @Test + public void testShowToast_addsViewWithCorrectLayoutParamsToWindowManager() throws Exception { + mToastUI.showToast(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.getTitle()).isEqualTo("Toast"); + assertThat(windowParams.token).isEqualTo(WINDOW_TOKEN_1); + } + + @Test + public void testShowToast_callsCallback() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + mCallback); + + verify(mCallback).onToastShown(); + } + + @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); + + ArgumentCaptor eventCaptor = ArgumentCaptor.forClass( + AccessibilityEvent.class); + verify(mAccessibilityManager).sendAccessibilityEvent(eventCaptor.capture()); + AccessibilityEvent event = eventCaptor.getValue(); + assertThat(event.getEventType()).isEqualTo( + AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); + assertThat(event.getClassName()).isEqualTo(Toast.class.getName()); + assertThat(event.getPackageName()).isEqualTo(PACKAGE_NAME_1); + } + + @Test + public void testHideToast_removesView() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + mCallback); + View view = verifyWmAddViewAndAttachToParent(); + + mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1); + + verify(mWindowManager).removeViewImmediate(view); + } + + @Test + public void testHideToast_finishesToken() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + mCallback); + + mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1); + + verify(mNotificationManager).finishToken(PACKAGE_NAME_1, WINDOW_TOKEN_1); + } + + @Test + public void testHideToast_callsCallback() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + mCallback); + + mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1); + + verify(mCallback).onToastHidden(); + } + + @Test + public void testHideToast_whenNotCurrentToastToken_doesNotHideToast() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + mCallback); + + mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_2); + + verify(mCallback, never()).onToastHidden(); + } + + @Test + public void testHideToast_whenNotCurrentToastPackage_doesNotHideToast() throws Exception { + mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, + mCallback); + + mToastUI.hideToast(PACKAGE_NAME_2, TOKEN_1); + + verify(mCallback, never()).onToastHidden(); + } + + @Test + public void testShowToast_afterShowToast_hidesCurrentToast() throws Exception { + mToastUI.showToast(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); + + verify(mWindowManager).removeViewImmediate(view); + verify(mNotificationManager).finishToken(PACKAGE_NAME_1, WINDOW_TOKEN_1); + verify(mCallback).onToastHidden(); + } + + private View verifyWmAddViewAndAttachToParent() { + ArgumentCaptor viewCaptor = ArgumentCaptor.forClass(View.class); + verify(mWindowManager).addView(viewCaptor.capture(), any()); + View view = viewCaptor.getValue(); + // Simulate attaching to view hierarchy + ViewGroup parent = new FrameLayout(mContext); + parent.addView(view); + return view; + } +}