DO NOT MERGE: More tests for CurrentUserContextTracker

Reworks some of the CurrentUserContextTracker and test its
functionality, and consequently fixes some NotificationConversationInfo
tests

Test: atest CurrentUserContextTrackerTest NotificationConversationInfoTest
Bug: 151843296
Fixes: 154332812
Change-Id: I0e3d4b1c64cba2cab581abca4ce9377a7c4676de
This commit is contained in:
Evan Laird
2020-04-16 12:26:07 -04:00
parent 31ca547400
commit 03c444586e
6 changed files with 189 additions and 49 deletions

View File

@@ -18,8 +18,10 @@ package com.android.systemui.settings
import android.content.Context
import android.os.UserHandle
import androidx.annotation.VisibleForTesting
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.util.Assert
import java.lang.IllegalStateException
import javax.inject.Inject
import javax.inject.Singleton
@@ -32,7 +34,16 @@ class CurrentUserContextTracker @Inject constructor(
broadcastDispatcher: BroadcastDispatcher
) {
private val userTracker: CurrentUserTracker
var currentUserContext: Context
private var initialized = false
private var _curUserContext: Context? = null
val currentUserContext: Context
get() {
if (!initialized) {
throw IllegalStateException("Must initialize before getting context")
}
return _curUserContext!!
}
init {
userTracker = object : CurrentUserTracker(broadcastDispatcher) {
@@ -40,21 +51,21 @@ class CurrentUserContextTracker @Inject constructor(
handleUserSwitched(newUserId)
}
}
currentUserContext = makeUserContext(userTracker.currentUserId)
}
fun initialize() {
initialized = true
_curUserContext = makeUserContext(userTracker.currentUserId)
userTracker.startTracking()
}
private fun handleUserSwitched(newUserId: Int) {
currentUserContext = makeUserContext(newUserId)
@VisibleForTesting
fun handleUserSwitched(newUserId: Int) {
_curUserContext = makeUserContext(newUserId)
}
private fun makeUserContext(uid: Int): Context {
Assert.isMainThread()
return sysuiContext.createContextAsUser(
UserHandle.getUserHandleForUid(userTracker.currentUserId), 0)
return sysuiContext.createContextAsUser(UserHandle.of(uid), 0)
}
}

View File

@@ -378,6 +378,7 @@ public final class NotificationEntry extends ListEntry {
/**
* Returns the data needed for a bubble for this notification, if it exists.
*/
@Nullable
public Notification.BubbleMetadata getBubbleMetadata() {
return mBubbleMetadata;
}
@@ -385,7 +386,7 @@ public final class NotificationEntry extends ListEntry {
/**
* Sets bubble metadata for this notification.
*/
public void setBubbleMetadata(Notification.BubbleMetadata metadata) {
public void setBubbleMetadata(@Nullable Notification.BubbleMetadata metadata) {
mBubbleMetadata = metadata;
}

View File

@@ -31,6 +31,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -98,7 +99,7 @@ public class NotificationConversationInfo extends LinearLayout implements
private ShortcutInfo mShortcutInfo;
private String mConversationId;
private StatusBarNotification mSbn;
private Notification.BubbleMetadata mBubbleMetadata;
@Nullable private Notification.BubbleMetadata mBubbleMetadata;
private Context mUserContext;
private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
private boolean mIsDeviceProvisioned;
@@ -203,6 +204,7 @@ public class NotificationConversationInfo extends LinearLayout implements
String pkg,
NotificationChannel notificationChannel,
NotificationEntry entry,
Notification.BubbleMetadata bubbleMetadata,
OnSettingsClickListener onSettingsClick,
OnSnoozeClickListener onSnoozeClickListener,
ConversationIconFactory conversationIconFactory,
@@ -224,7 +226,7 @@ public class NotificationConversationInfo extends LinearLayout implements
mOnSnoozeClickListener = onSnoozeClickListener;
mIconFactory = conversationIconFactory;
mUserContext = userContext;
mBubbleMetadata = entry.getBubbleMetadata();
mBubbleMetadata = bubbleMetadata;
mBuilderProvider = builderProvider;
mShortcutManager = shortcutManager;
@@ -538,7 +540,8 @@ public class NotificationConversationInfo extends LinearLayout implements
Log.e(TAG, "Could not check conversation senders", e);
}
boolean showAsBubble = mBubbleMetadata.getAutoExpandBubble()
boolean showAsBubble = mBubbleMetadata != null
&& mBubbleMetadata.getAutoExpandBubble()
&& Settings.Global.getInt(mContext.getContentResolver(),
NOTIFICATION_BUBBLES, 0) == 1;

View File

@@ -366,7 +366,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
final ExpandableNotificationRow row,
NotificationConversationInfo notificationInfoView) throws Exception {
NotificationGuts guts = row.getGuts();
StatusBarNotification sbn = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
StatusBarNotification sbn = entry.getSbn();
String packageName = sbn.getPackageName();
// Settings link is only valid for notifications that specify a non-system user
NotificationConversationInfo.OnSettingsClickListener onSettingsClick = null;
@@ -407,8 +408,9 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mNotificationManager,
mVisualStabilityManager,
packageName,
row.getEntry().getChannel(),
row.getEntry(),
entry.getChannel(),
entry,
entry.getBubbleMetadata(),
onSettingsClick,
onSnoozeClickListener,
iconFactoryLoader,

View File

@@ -0,0 +1,92 @@
/*
* 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.settings
import android.content.Context
import android.content.ContextWrapper
import android.os.UserHandle
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class CurrentUserContextTrackerTest : SysuiTestCase() {
private lateinit var tracker: CurrentUserContextTracker
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
allowTestableLooperAsMainThread()
// wrap Context so that tests don't throw for missing package errors
val wrapped = object : ContextWrapper(context) {
override fun createContextAsUser(user: UserHandle, flags: Int): Context {
val mockContext = mock(Context::class.java)
`when`(mockContext.user).thenReturn(user)
`when`(mockContext.userId).thenReturn(user.identifier)
return mockContext
}
}
tracker = CurrentUserContextTracker(wrapped, broadcastDispatcher)
tracker.initialize()
}
@Test
fun testContextExistsAfterInit_noCrash() {
tracker.currentUserContext
}
@Test
fun testUserContextIsCorrectAfterUserSwitch() {
// We always start out with system ui test
assertTrue("Starting userId should be 0", tracker.currentUserContext.userId == 0)
// WHEN user changes
tracker.handleUserSwitched(1)
// THEN user context should have the correct userId
assertTrue("User has changed to userId 1, the context should reflect that",
tracker.currentUserContext.userId == 1)
}
@Suppress("UNUSED_PARAMETER")
@Test(expected = IllegalStateException::class)
fun testContextTrackerThrowsExceptionWhenNotInitialized() {
// GIVEN an uninitialized CurrentUserContextTracker
val userTracker = CurrentUserContextTracker(context, broadcastDispatcher)
// WHEN client asks for a context
val userContext = userTracker.currentUserContext
// THEN an exception is thrown
}
}

View File

@@ -48,9 +48,9 @@ import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
@@ -91,6 +91,7 @@ import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Answer;
@@ -147,14 +148,15 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
private ShadeController mShadeController;
@Mock
private ConversationIconFactory mIconFactory;
@Mock
private Context mUserContext;
@Mock(answer = Answers.RETURNS_SELF)
private PriorityOnboardingDialogController.Builder mBuilder;
private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider = () -> mBuilder;
@Mock
private Notification.BubbleMetadata mBubbleMetadata;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
@@ -228,6 +230,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
when(mMockINotificationManager.getConversationNotificationChannel(anyString(), anyInt(),
anyString(), eq(TEST_CHANNEL), eq(false), eq(CONVERSATION_ID)))
.thenReturn(mConversationChannel);
when(mMockINotificationManager.getConsolidatedNotificationPolicy())
.thenReturn(mock(NotificationManager.Policy.class));
when(mBuilder.build()).thenReturn(mock(PriorityOnboardingDialogController.class));
}
@Test
@@ -240,10 +247,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final ImageView view = mNotificationInfo.findViewById(R.id.conversation_icon);
@@ -261,10 +269,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
@@ -283,7 +292,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
mBubbleMetadata,
null,
null,
null,
true);
@@ -308,10 +318,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
@@ -331,10 +342,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
@@ -353,10 +365,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
@@ -382,10 +395,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
entry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
@@ -404,13 +418,14 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mConversationChannel, c);
latch.countDown();
},
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -430,10 +445,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -451,13 +467,14 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
},
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
false);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -476,10 +493,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
View view = mNotificationInfo.findViewById(R.id.silence);
@@ -501,10 +519,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
View view = mNotificationInfo.findViewById(R.id.default_behavior);
@@ -529,10 +548,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
View view = mNotificationInfo.findViewById(R.id.default_behavior);
@@ -556,10 +576,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -596,10 +617,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -635,10 +657,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -675,10 +698,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -709,10 +733,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -741,10 +766,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -774,10 +800,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -807,10 +834,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -839,10 +867,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -870,10 +899,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -892,10 +922,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mContext,
mBuilderProvider,
true);
@@ -910,13 +941,12 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
// GIVEN the priority onboarding screen is present
PriorityOnboardingDialogController.Builder b =
new PriorityOnboardingDialogController.Builder();
mock(PriorityOnboardingDialogController.Builder.class, Answers.RETURNS_SELF);
PriorityOnboardingDialogController controller =
mock(PriorityOnboardingDialogController.class);
when(b.build()).thenReturn(controller);
// GIVEN the user is changing conversation settings
when(mBuilderProvider.get()).thenReturn(b);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
@@ -925,11 +955,12 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mBuilderProvider,
mContext,
() -> b,
true);
// WHEN user clicks "priority"
@@ -945,12 +976,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_PRIORITY_ONBOARDING, true);
PriorityOnboardingDialogController.Builder b =
new PriorityOnboardingDialogController.Builder();
mock(PriorityOnboardingDialogController.Builder.class, Answers.RETURNS_SELF);
PriorityOnboardingDialogController controller =
mock(PriorityOnboardingDialogController.class);
when(b.build()).thenReturn(controller);
when(mBuilderProvider.get()).thenReturn(b);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
@@ -959,11 +989,12 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
mBubbleMetadata,
null,
null,
mIconFactory,
mUserContext,
mBuilderProvider,
mContext,
() -> b,
true);
// WHEN user clicks "priority"