diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index 3329f549d3816..030c96e3dba6c 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -261,11 +261,15 @@ public class ConditionProviders extends ManagedServices { } } - private Condition[] removeDuplicateConditions(String pkg, Condition[] conditions) { + private Condition[] getValidConditions(String pkg, Condition[] conditions) { if (conditions == null || conditions.length == 0) return null; final int N = conditions.length; final ArrayMap valid = new ArrayMap(N); for (int i = 0; i < N; i++) { + if (conditions[i] == null) { + Slog.w(TAG, "Ignoring null condition from " + pkg); + continue; + } final Uri id = conditions[i].id; if (valid.containsKey(id)) { Slog.w(TAG, "Ignoring condition from " + pkg + " for duplicate id: " + id); @@ -303,7 +307,7 @@ public class ConditionProviders extends ManagedServices { synchronized(mMutex) { if (DEBUG) Slog.d(TAG, "notifyConditions pkg=" + pkg + " info=" + info + " conditions=" + (conditions == null ? null : Arrays.asList(conditions))); - conditions = removeDuplicateConditions(pkg, conditions); + conditions = getValidConditions(pkg, conditions); if (conditions == null || conditions.length == 0) return; final int N = conditions.length; for (int i = 0; i < N; i++) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java new file mode 100644 index 0000000000000..b94ed012c385d --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java @@ -0,0 +1,134 @@ +/* + * 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.server.notification; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.content.ComponentName; +import android.content.ServiceConnection; +import android.content.pm.IPackageManager; +import android.net.Uri; +import android.os.IInterface; +import android.service.notification.Condition; + +import com.android.server.UiServiceTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class ConditionProvidersTest extends UiServiceTestCase { + + private ConditionProviders mProviders; + + @Mock + private IPackageManager mIpm; + @Mock + private ManagedServices.UserProfiles mUserProfiles; + @Mock + private ConditionProviders.Callback mCallback; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mProviders = new ConditionProviders(mContext, mUserProfiles, mIpm); + mProviders.setCallback(mCallback); + } + + @Test + public void notifyConditions_findCondition() { + ComponentName cn = new ComponentName("package", "cls"); + ManagedServices.ManagedServiceInfo msi = mProviders.new ManagedServiceInfo( + mock(IInterface.class), cn, 0, false, mock(ServiceConnection.class), 33, 100); + Condition[] conditions = new Condition[] { + new Condition(Uri.parse("a"), "summary", Condition.STATE_TRUE), + new Condition(Uri.parse("b"), "summary2", Condition.STATE_TRUE) + }; + + mProviders.notifyConditions("package", msi, conditions); + + assertThat(mProviders.findCondition(cn, Uri.parse("a"))).isEqualTo(conditions[0]); + assertThat(mProviders.findCondition(cn, Uri.parse("b"))).isEqualTo(conditions[1]); + assertThat(mProviders.findCondition(null, Uri.parse("a"))).isNull(); + assertThat(mProviders.findCondition(cn, null)).isNull(); + } + + @Test + public void notifyConditions_callbackOnConditionChanged() { + ManagedServices.ManagedServiceInfo msi = mProviders.new ManagedServiceInfo( + mock(IInterface.class), new ComponentName("package", "cls"), 0, false, + mock(ServiceConnection.class), 33, 100); + Condition[] conditionsToNotify = new Condition[] { + new Condition(Uri.parse("a"), "summary", Condition.STATE_TRUE), + new Condition(Uri.parse("b"), "summary2", Condition.STATE_TRUE), + new Condition(Uri.parse("c"), "summary3", Condition.STATE_TRUE) + }; + + mProviders.notifyConditions("package", msi, conditionsToNotify); + + verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0])); + verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[1])); + verify(mCallback).onConditionChanged(eq(Uri.parse("c")), eq(conditionsToNotify[2])); + verifyNoMoreInteractions(mCallback); + } + + @Test + public void notifyConditions_duplicateIds_ignored() { + ManagedServices.ManagedServiceInfo msi = mProviders.new ManagedServiceInfo( + mock(IInterface.class), new ComponentName("package", "cls"), 0, false, + mock(ServiceConnection.class), 33, 100); + Condition[] conditionsToNotify = new Condition[] { + new Condition(Uri.parse("a"), "summary", Condition.STATE_TRUE), + new Condition(Uri.parse("b"), "summary2", Condition.STATE_TRUE), + new Condition(Uri.parse("a"), "summary3", Condition.STATE_FALSE), + new Condition(Uri.parse("a"), "summary4", Condition.STATE_FALSE) + }; + + mProviders.notifyConditions("package", msi, conditionsToNotify); + + verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0])); + verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[1])); + + verifyNoMoreInteractions(mCallback); + } + + @Test + public void notifyConditions_nullItems_ignored() { + ManagedServices.ManagedServiceInfo msi = mProviders.new ManagedServiceInfo( + mock(IInterface.class), new ComponentName("package", "cls"), 0, false, + mock(ServiceConnection.class), 33, 100); + Condition[] conditionsToNotify = new Condition[] { + new Condition(Uri.parse("a"), "summary", Condition.STATE_TRUE), + null, + null, + new Condition(Uri.parse("b"), "summary", Condition.STATE_TRUE) + }; + + mProviders.notifyConditions("package", msi, conditionsToNotify); + + verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0])); + verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[3])); + verifyNoMoreInteractions(mCallback); + } +}