diff options
| author | 2023-08-02 20:47:44 +0000 | |
|---|---|---|
| committer | 2023-08-02 20:47:44 +0000 | |
| commit | df8581f33155c1615b2eba93a39dd83050e04054 (patch) | |
| tree | 62e199105997d05f4c8de4fb411904af14875d07 | |
| parent | 20fd792af6c64aba4295c2a5fa15dfda6e93ebb6 (diff) | |
| parent | 54ebde46f75de147548c715e993e03932f3fcc86 (diff) | |
Merge "Revert "Do less on the main thread"" into udc-qpr-dev
6 files changed, 5 insertions, 544 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index 80f5d1939ac0..a4e8c2ece894 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -21,16 +21,12 @@ import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENAB import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.notification.NotificationUtils.logKey; -import android.net.Uri; -import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; @@ -75,10 +71,6 @@ import javax.inject.Named; @NotificationRowScope public class ExpandableNotificationRowController implements NotifViewController { private static final String TAG = "NotifRowController"; - - static final Uri BUBBLES_SETTING_URI = - Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BUBBLES); - private static final String BUBBLES_SETTING_ENABLED_VALUE = "1"; private final ExpandableNotificationRow mView; private final NotificationListContainer mListContainer; private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory; @@ -112,23 +104,6 @@ public class ExpandableNotificationRowController implements NotifViewController private final ExpandableNotificationRowDragController mDragController; private final NotificationDismissibilityProvider mDismissibilityProvider; private final IStatusBarService mStatusBarService; - - private final NotificationSettingsController mSettingsController; - - @VisibleForTesting - final NotificationSettingsController.Listener mSettingsListener = - new NotificationSettingsController.Listener() { - @Override - public void onSettingChanged(Uri setting, int userId, String value) { - if (BUBBLES_SETTING_URI.equals(setting)) { - final int viewUserId = mView.getEntry().getSbn().getUserId(); - if (viewUserId == UserHandle.USER_ALL || viewUserId == userId) { - mView.getPrivateLayout().setBubblesEnabledForUser( - BUBBLES_SETTING_ENABLED_VALUE.equals(value)); - } - } - } - }; private final ExpandableNotificationRow.ExpandableNotificationRowLogger mLoggerCallback = new ExpandableNotificationRow.ExpandableNotificationRowLogger() { @Override @@ -226,7 +201,6 @@ public class ExpandableNotificationRowController implements NotifViewController FeatureFlags featureFlags, PeopleNotificationIdentifier peopleNotificationIdentifier, Optional<BubblesManager> bubblesManagerOptional, - NotificationSettingsController settingsController, ExpandableNotificationRowDragController dragController, NotificationDismissibilityProvider dismissibilityProvider, IStatusBarService statusBarService) { @@ -255,7 +229,6 @@ public class ExpandableNotificationRowController implements NotifViewController mFeatureFlags = featureFlags; mPeopleNotificationIdentifier = peopleNotificationIdentifier; mBubblesManagerOptional = bubblesManagerOptional; - mSettingsController = settingsController; mDragController = dragController; mMetricsLogger = metricsLogger; mChildrenContainerLogger = childrenContainerLogger; @@ -325,14 +298,12 @@ public class ExpandableNotificationRowController implements NotifViewController NotificationMenuRowPlugin.class, false /* Allow multiple */); mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD); mStatusBarStateController.addCallback(mStatusBarStateListener); - mSettingsController.addCallback(BUBBLES_SETTING_URI, mSettingsListener); } @Override public void onViewDetachedFromWindow(View v) { mPluginManager.removePluginListener(mView); mStatusBarStateController.removeCallback(mStatusBarStateListener); - mSettingsController.removeCallback(BUBBLES_SETTING_URI, mSettingsListener); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 7b6802f95cda..20f4429f294b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -44,7 +44,6 @@ import android.widget.LinearLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; -import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.SmartReplyController; @@ -66,6 +65,7 @@ import com.android.systemui.statusbar.policy.SmartReplyStateInflaterKt; import com.android.systemui.statusbar.policy.SmartReplyView; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.Compile; +import com.android.systemui.wmshell.BubblesManager; import java.io.PrintWriter; import java.util.ArrayList; @@ -134,7 +134,6 @@ public class NotificationContentView extends FrameLayout implements Notification private PeopleNotificationIdentifier mPeopleIdentifier; private RemoteInputViewSubcomponent.Factory mRemoteInputSubcomponentFactory; private IStatusBarService mStatusBarService; - private boolean mBubblesEnabledForUser; /** * List of listeners for when content views become inactive (i.e. not the showing view). @@ -1441,17 +1440,12 @@ public class NotificationContentView extends FrameLayout implements Notification } } - @Background - public void setBubblesEnabledForUser(boolean enabled) { - mBubblesEnabledForUser = enabled; - } - @VisibleForTesting boolean shouldShowBubbleButton(NotificationEntry entry) { boolean isPersonWithShortcut = mPeopleIdentifier.getPeopleNotificationType(entry) >= PeopleNotificationIdentifier.TYPE_FULL_PERSON; - return mBubblesEnabledForUser + return BubblesManager.areBubblesEnabled(mContext, entry.getSbn().getUser()) && isPersonWithShortcut && entry.getBubbleMetadata() != null; } @@ -2085,7 +2079,6 @@ public class NotificationContentView extends FrameLayout implements Notification pw.print("null"); } pw.println(); - pw.println("mBubblesEnabledForUser: " + mBubblesEnabledForUser); pw.print("RemoteInputViews { "); pw.print(" visibleType: " + mVisibleType); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSettingsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSettingsController.java deleted file mode 100644 index 585ff523b9a0..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSettingsController.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2023 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.statusbar.notification.row; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.HandlerExecutor; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.systemui.Dumpable; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Background; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.util.settings.SecureSettings; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; - -import javax.inject.Inject; - -/** - * Centralized controller for listening to Secure Settings changes and informing in-process - * listeners, on a background thread. - */ -@SysUISingleton -public class NotificationSettingsController implements Dumpable { - - private final static String TAG = "NotificationSettingsController"; - private final UserTracker mUserTracker; - private final UserTracker.Callback mCurrentUserTrackerCallback; - private final Handler mHandler; - private final ContentObserver mContentObserver; - private final SecureSettings mSecureSettings; - private final HashMap<Uri, ArrayList<Listener>> mListeners = new HashMap<>(); - - @Inject - public NotificationSettingsController(UserTracker userTracker, - @Background Handler handler, - SecureSettings secureSettings, - DumpManager dumpManager) { - mUserTracker = userTracker; - mHandler = handler; - mSecureSettings = secureSettings; - mContentObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - synchronized (mListeners) { - if (mListeners.containsKey(uri)) { - for (Listener listener : mListeners.get(uri)) { - notifyListener(listener, uri); - } - } - } - } - }; - - mCurrentUserTrackerCallback = new UserTracker.Callback() { - @Override - public void onUserChanged(int newUser, Context userContext) { - synchronized (mListeners) { - if (mListeners.size() > 0) { - mSecureSettings.unregisterContentObserver(mContentObserver); - for (Uri uri : mListeners.keySet()) { - mSecureSettings.registerContentObserverForUser( - uri, false, mContentObserver, newUser); - } - } - } - } - }; - mUserTracker.addCallback(mCurrentUserTrackerCallback, new HandlerExecutor(handler)); - - dumpManager.registerNormalDumpable(TAG, this); - } - - /** - * Register callback whenever the given secure settings changes. - * - * On registration, will call back on the provided handler with the current value of - * the setting. - */ - public void addCallback(@NonNull Uri uri, @NonNull Listener listener) { - if (uri == null || listener == null) { - return; - } - synchronized (mListeners) { - ArrayList<Listener> currentListeners = mListeners.get(uri); - if (currentListeners == null) { - currentListeners = new ArrayList<>(); - } - if (!currentListeners.contains(listener)) { - currentListeners.add(listener); - } - mListeners.put(uri, currentListeners); - if (currentListeners.size() == 1) { - mSecureSettings.registerContentObserverForUser( - uri, false, mContentObserver, mUserTracker.getUserId()); - } - } - mHandler.post(() -> notifyListener(listener, uri)); - - } - - public void removeCallback(Uri uri, Listener listener) { - synchronized (mListeners) { - ArrayList<Listener> currentListeners = mListeners.get(uri); - - if (currentListeners != null) { - currentListeners.remove(listener); - } - if (currentListeners == null || currentListeners.size() == 0) { - mListeners.remove(uri); - } - - if (mListeners.size() == 0) { - mSecureSettings.unregisterContentObserver(mContentObserver); - } - } - } - - @Override - public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { - synchronized (mListeners) { - pw.println("Settings Uri Listener List:"); - for (Uri uri : mListeners.keySet()) { - pw.println(" Uri=" + uri); - for (Listener listener : mListeners.get(uri)) { - pw.println(" Listener=" + listener.getClass().getName()); - } - } - } - } - - private void notifyListener(Listener listener, Uri uri) { - final String setting = uri == null ? null : uri.getLastPathSegment(); - int userId = mUserTracker.getUserId(); - listener.onSettingChanged(uri, userId, mSecureSettings.getStringForUser(setting, userId)); - } - - /** - * Listener invoked whenever settings are changed. - */ - public interface Listener { - void onSettingChanged(@NonNull Uri setting, int userId, @Nullable String value); - } -}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt index 4d4d319a3540..2e68cec1fe63 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt @@ -17,10 +17,6 @@ package com.android.systemui.statusbar.notification.row -import android.app.Notification -import android.net.Uri -import android.os.UserHandle -import android.os.UserHandle.USER_ALL import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest @@ -32,17 +28,13 @@ import com.android.systemui.flags.FeatureFlags import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.PluginManager import com.android.systemui.plugins.statusbar.StatusBarStateController -import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.statusbar.SmartReplyController -import com.android.systemui.statusbar.notification.collection.NotificationEntry -import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider import com.android.systemui.statusbar.notification.collection.render.FakeNodeController import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager import com.android.systemui.statusbar.notification.logging.NotificationLogger import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier -import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController.BUBBLES_SETTING_URI import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger import com.android.systemui.statusbar.notification.stack.NotificationListContainer @@ -53,9 +45,9 @@ import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock -import com.android.systemui.util.mockito.withArgCaptor import com.android.systemui.util.time.SystemClock import com.android.systemui.wmshell.BubblesManager +import java.util.Optional import junit.framework.Assert import org.junit.After import org.junit.Before @@ -63,10 +55,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito import org.mockito.Mockito.anyBoolean -import org.mockito.Mockito.mock import org.mockito.Mockito.never -import org.mockito.Mockito.verify -import java.util.* import org.mockito.Mockito.`when` as whenever @SmallTest @@ -103,10 +92,10 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() { private val featureFlags: FeatureFlags = mock() private val peopleNotificationIdentifier: PeopleNotificationIdentifier = mock() private val bubblesManager: BubblesManager = mock() - private val settingsController: NotificationSettingsController = mock() private val dragController: ExpandableNotificationRowDragController = mock() private val dismissibilityProvider: NotificationDismissibilityProvider = mock() private val statusBarService: IStatusBarService = mock() + private lateinit var controller: ExpandableNotificationRowController @Before @@ -143,16 +132,11 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() { featureFlags, peopleNotificationIdentifier, Optional.of(bubblesManager), - settingsController, dragController, dismissibilityProvider, statusBarService ) whenever(view.childrenContainer).thenReturn(childrenContainer) - - val notification = Notification.Builder(mContext).build() - val sbn = SbnBuilder().setNotification(notification).build() - whenever(view.entry).thenReturn(NotificationEntryBuilder().setSbn(sbn).build()) } @After @@ -220,74 +204,4 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() { Mockito.verify(view).removeChildNotification(eq(childView)) Mockito.verify(listContainer).notifyGroupChildRemoved(eq(childView), eq(childrenContainer)) } - - @Test - fun registerSettingsListener_forBubbles() { - controller.init(mock(NotificationEntry::class.java)) - val viewStateObserver = withArgCaptor { - verify(view).addOnAttachStateChangeListener(capture()); - } - viewStateObserver.onViewAttachedToWindow(view); - verify(settingsController).addCallback(any(), any()); - } - - @Test - fun unregisterSettingsListener_forBubbles() { - controller.init(mock(NotificationEntry::class.java)) - val viewStateObserver = withArgCaptor { - verify(view).addOnAttachStateChangeListener(capture()); - } - viewStateObserver.onViewDetachedFromWindow(view); - verify(settingsController).removeCallback(any(), any()); - } - - @Test - fun settingsListener_invalidUri() { - controller.mSettingsListener.onSettingChanged(Uri.EMPTY, view.entry.sbn.userId, "1") - - verify(view, never()).getPrivateLayout() - } - - @Test - fun settingsListener_invalidUserId() { - controller.mSettingsListener.onSettingChanged(BUBBLES_SETTING_URI, -1000, "1") - controller.mSettingsListener.onSettingChanged(BUBBLES_SETTING_URI, -1000, null) - - verify(view, never()).getPrivateLayout() - } - - @Test - fun settingsListener_validUserId() { - val childView: NotificationContentView = mock() - whenever(view.privateLayout).thenReturn(childView) - - controller.mSettingsListener.onSettingChanged( - BUBBLES_SETTING_URI, view.entry.sbn.userId, "1") - verify(childView).setBubblesEnabledForUser(true) - - controller.mSettingsListener.onSettingChanged( - BUBBLES_SETTING_URI, view.entry.sbn.userId, "9") - verify(childView).setBubblesEnabledForUser(false) - } - - @Test - fun settingsListener_userAll() { - val childView: NotificationContentView = mock() - whenever(view.privateLayout).thenReturn(childView) - - val notification = Notification.Builder(mContext).build() - val sbn = SbnBuilder().setNotification(notification) - .setUser(UserHandle.of(USER_ALL)) - .build() - whenever(view.entry).thenReturn(NotificationEntryBuilder() - .setSbn(sbn) - .setUser(UserHandle.of(USER_ALL)) - .build()) - - controller.mSettingsListener.onSettingChanged(BUBBLES_SETTING_URI, 9, "1") - verify(childView).setBubblesEnabledForUser(true) - - controller.mSettingsListener.onSettingChanged(BUBBLES_SETTING_URI, 1, "0") - verify(childView).setBubblesEnabledForUser(false) - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt index ba6c7fd50bc5..0b90ebec3ec6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt @@ -250,9 +250,6 @@ class NotificationContentViewTest : SysuiTestCase() { .thenReturn(actionListMarginTarget) view.setContainingNotification(mockContainingNotification) - // Given: controller says bubbles are enabled for the user - view.setBubblesEnabledForUser(true); - // When: call NotificationContentView.setExpandedChild() to set the expandedChild view.expandedChild = mockExpandedChild @@ -304,9 +301,6 @@ class NotificationContentViewTest : SysuiTestCase() { view.expandedChild = mockExpandedChild assertEquals(notificationContentMargin, getMarginBottom(actionListMarginTarget)) - // Given: controller says bubbles are enabled for the user - view.setBubblesEnabledForUser(true); - // When: call NotificationContentView.onNotificationUpdated() to update the // NotificationEntry, which should show bubble button view.onNotificationUpdated(createMockNotificationEntry(true)) @@ -411,6 +405,7 @@ class NotificationContentViewTest : SysuiTestCase() { val userMock: UserHandle = mock() whenever(this.sbn).thenReturn(sbnMock) whenever(sbnMock.user).thenReturn(userMock) + doReturn(showButton).whenever(view).shouldShowBubbleButton(this) } private fun createLinearLayoutWithBottomMargin(bottomMargin: Int): LinearLayout { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSettingsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSettingsControllerTest.kt deleted file mode 100644 index 2bccdcafbb6e..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSettingsControllerTest.kt +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2023 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.statusbar.notification.row - -import android.app.ActivityManager -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler -import android.provider.Settings.Secure -import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.dump.DumpManager -import com.android.systemui.settings.UserTracker -import com.android.systemui.statusbar.notification.row.NotificationSettingsController.Listener -import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.capture -import com.android.systemui.util.mockito.eq -import com.android.systemui.util.mockito.mock -import com.android.systemui.util.mockito.whenever -import com.android.systemui.util.settings.SecureSettings -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.ArgumentMatchers -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.ArgumentMatchers.anyString -import org.mockito.Captor -import org.mockito.Mock -import org.mockito.Mockito -import org.mockito.Mockito.anyBoolean -import org.mockito.Mockito.never -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations - -@SmallTest -@RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper -class NotificationSettingsControllerTest : SysuiTestCase() { - - val setting1: String = Secure.NOTIFICATION_BUBBLES - val setting2: String = Secure.ACCESSIBILITY_ENABLED - val settingUri1: Uri = Secure.getUriFor(setting1) - val settingUri2: Uri = Secure.getUriFor(setting2) - - @Mock - private lateinit var userTracker: UserTracker - private lateinit var handler: Handler - private lateinit var testableLooper: TestableLooper - @Mock - private lateinit var secureSettings: SecureSettings - @Mock - private lateinit var dumpManager: DumpManager - - @Captor - private lateinit var userTrackerCallbackCaptor: ArgumentCaptor<UserTracker.Callback> - @Captor - private lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver> - - private lateinit var controller: NotificationSettingsController - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - testableLooper = TestableLooper.get(this) - handler = Handler(testableLooper.looper) - allowTestableLooperAsMainThread() - controller = - NotificationSettingsController( - userTracker, - handler, - secureSettings, - dumpManager - ) - } - - @After - fun tearDown() { - disallowTestableLooperAsMainThread() - } - - @Test - fun creationRegistersCallbacks() { - verify(userTracker).addCallback(any(), any()) - verify(dumpManager).registerNormalDumpable(anyString(), eq(controller)) - } - @Test - fun updateContentObserverRegistration_onUserChange_noSettingsListeners() { - verify(userTracker).addCallback(capture(userTrackerCallbackCaptor), any()) - val userCallback = userTrackerCallbackCaptor.value - val userId = 9 - - // When: User is changed - userCallback.onUserChanged(userId, context) - - // Validate: Nothing to do, since we aren't monitoring settings - verify(secureSettings, never()).unregisterContentObserver(any()) - verify(secureSettings, never()).registerContentObserverForUser( - any(Uri::class.java), anyBoolean(), any(), anyInt()) - } - @Test - fun updateContentObserverRegistration_onUserChange_withSettingsListeners() { - // When: someone is listening to a setting - controller.addCallback(settingUri1, - Mockito.mock(Listener::class.java)) - - verify(userTracker).addCallback(capture(userTrackerCallbackCaptor), any()) - val userCallback = userTrackerCallbackCaptor.value - val userId = 9 - - // Then: User is changed - userCallback.onUserChanged(userId, context) - - // Validate: The tracker is unregistered and re-registered with the new user - verify(secureSettings).unregisterContentObserver(any()) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri1), eq(false), any(), eq(userId)) - } - - @Test - fun addCallback_onlyFirstForUriRegistersObserver() { - controller.addCallback(settingUri1, - Mockito.mock(Listener::class.java)) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri1), eq(false), any(), eq(ActivityManager.getCurrentUser())) - - controller.addCallback(settingUri1, - Mockito.mock(Listener::class.java)) - verify(secureSettings).registerContentObserverForUser( - any(Uri::class.java), anyBoolean(), any(), anyInt()) - } - - @Test - fun addCallback_secondUriRegistersObserver() { - controller.addCallback(settingUri1, - Mockito.mock(Listener::class.java)) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri1), eq(false), any(), eq(ActivityManager.getCurrentUser())) - - controller.addCallback(settingUri2, - Mockito.mock(Listener::class.java)) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri2), eq(false), any(), eq(ActivityManager.getCurrentUser())) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri1), anyBoolean(), any(), anyInt()) - } - - @Test - fun removeCallback_lastUnregistersObserver() { - val listenerSetting1 : Listener = mock() - val listenerSetting2 : Listener = mock() - controller.addCallback(settingUri1, listenerSetting1) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri1), eq(false), any(), eq(ActivityManager.getCurrentUser())) - - controller.addCallback(settingUri2, listenerSetting2) - verify(secureSettings).registerContentObserverForUser( - eq(settingUri2), anyBoolean(), any(), anyInt()) - - controller.removeCallback(settingUri2, listenerSetting2) - verify(secureSettings, never()).unregisterContentObserver(any()) - - controller.removeCallback(settingUri1, listenerSetting1) - verify(secureSettings).unregisterContentObserver(any()) - } - - @Test - fun addCallback_updatesCurrentValue() { - whenever(secureSettings.getStringForUser( - setting1, ActivityManager.getCurrentUser())).thenReturn("9") - whenever(secureSettings.getStringForUser( - setting2, ActivityManager.getCurrentUser())).thenReturn("5") - - val listenerSetting1a : Listener = mock() - val listenerSetting1b : Listener = mock() - val listenerSetting2 : Listener = mock() - - controller.addCallback(settingUri1, listenerSetting1a) - controller.addCallback(settingUri1, listenerSetting1b) - controller.addCallback(settingUri2, listenerSetting2) - - testableLooper.processAllMessages() - - verify(listenerSetting1a).onSettingChanged( - settingUri1, ActivityManager.getCurrentUser(), "9") - verify(listenerSetting1b).onSettingChanged( - settingUri1, ActivityManager.getCurrentUser(), "9") - verify(listenerSetting2).onSettingChanged( - settingUri2, ActivityManager.getCurrentUser(), "5") - } - - @Test - fun removeCallback_noMoreUpdates() { - whenever(secureSettings.getStringForUser( - setting1, ActivityManager.getCurrentUser())).thenReturn("9") - - val listenerSetting1a : Listener = mock() - val listenerSetting1b : Listener = mock() - - // First, register - controller.addCallback(settingUri1, listenerSetting1a) - controller.addCallback(settingUri1, listenerSetting1b) - testableLooper.processAllMessages() - - verify(secureSettings).registerContentObserverForUser( - any(Uri::class.java), anyBoolean(), capture(settingsObserverCaptor), anyInt()) - verify(listenerSetting1a).onSettingChanged( - settingUri1, ActivityManager.getCurrentUser(), "9") - verify(listenerSetting1b).onSettingChanged( - settingUri1, ActivityManager.getCurrentUser(), "9") - Mockito.clearInvocations(listenerSetting1b) - Mockito.clearInvocations(listenerSetting1a) - - // Remove one of them - controller.removeCallback(settingUri1, listenerSetting1a) - - // On update, only remaining listener should get the callback - settingsObserverCaptor.value.onChange(false, settingUri1) - testableLooper.processAllMessages() - - verify(listenerSetting1a, never()).onSettingChanged( - settingUri1, ActivityManager.getCurrentUser(), "9") - verify(listenerSetting1b).onSettingChanged( - settingUri1, ActivityManager.getCurrentUser(), "9") - } - -}
\ No newline at end of file |