Loading services/core/java/com/android/server/notification/NotificationManagerService.java +2 −1 Original line number Diff line number Diff line Loading @@ -1952,7 +1952,8 @@ public class NotificationManagerService extends SystemService { mRankingHandler, mZenModeHelper, new NotificationChannelLoggerImpl(), mAppOps); mAppOps, new SysUiStatsEvent.BuilderFactory()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, Loading services/core/java/com/android/server/notification/PreferencesHelper.java +7 −4 Original line number Diff line number Diff line Loading @@ -140,6 +140,7 @@ public class PreferencesHelper implements RankingConfig { * fields. */ private static final int DEFAULT_LOCKED_APP_FIELDS = 0; private final SysUiStatsEvent.BuilderFactory mStatsEventBuilderFactory; /** * All user-lockable fields for a given application. Loading Loading @@ -171,13 +172,15 @@ public class PreferencesHelper implements RankingConfig { public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler, ZenModeHelper zenHelper, NotificationChannelLogger notificationChannelLogger, AppOpsManager appOpsManager) { AppOpsManager appOpsManager, SysUiStatsEvent.BuilderFactory statsEventBuilderFactory) { mContext = context; mZenModeHelper = zenHelper; mRankingHandler = rankingHandler; mPm = pm; mNotificationChannelLogger = notificationChannelLogger; mAppOps = appOpsManager; mStatsEventBuilderFactory = statsEventBuilderFactory; updateBadgingEnabled(); updateBubblesEnabled(); Loading Loading @@ -1898,7 +1901,7 @@ public class PreferencesHelper implements RankingConfig { if (i > NOTIFICATION_PREFERENCES_PULL_LIMIT) { break; } StatsEvent.Builder event = StatsEvent.newBuilder() SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES); final PackagePreferences r = mPackagePreferences.valueAt(i); event.writeInt(r.uid); Loading Loading @@ -1927,7 +1930,7 @@ public class PreferencesHelper implements RankingConfig { if (++totalChannelsPulled > NOTIFICATION_CHANNEL_PULL_LIMIT) { break; } StatsEvent.Builder event = StatsEvent.newBuilder() SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES); event.writeInt(r.uid); event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); Loading Loading @@ -1962,7 +1965,7 @@ public class PreferencesHelper implements RankingConfig { if (++totalGroupsPulled > NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT) { break; } StatsEvent.Builder event = StatsEvent.newBuilder() SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES); event.writeInt(r.uid); event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); Loading services/core/java/com/android/server/notification/SysUiStatsEvent.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * 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.server.notification; import android.util.StatsEvent; /** * Wrapper for StatsEvent that enables unit testing. */ public class SysUiStatsEvent { static class Builder { private final StatsEvent.Builder mBuilder; protected Builder(StatsEvent.Builder builder) { mBuilder = builder; } public StatsEvent build() { return mBuilder.build(); } public Builder setAtomId(int atomId) { mBuilder.setAtomId(atomId); return this; } public Builder writeInt(int value) { mBuilder.writeInt(value); return this; } public Builder addBooleanAnnotation(byte annotation, boolean value) { mBuilder.addBooleanAnnotation(annotation, value); return this; } public Builder writeString(String value) { mBuilder.writeString(value); return this; } public Builder writeBoolean(boolean value) { mBuilder.writeBoolean(value); return this; } } static class BuilderFactory { Builder newBuilder() { return new Builder(StatsEvent.newBuilder()); } } } services/tests/uiservicestests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ android_test { "mockito-target-inline-minus-junit4", "platform-test-annotations", "platformprotosnano", "statsdprotolite", "hamcrest-library", "testables", "truth-prebuilt", Loading services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +178 −42 Original line number Diff line number Diff line Loading @@ -29,6 +29,16 @@ import static android.app.NotificationManager.IMPORTANCE_MAX; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID; import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_ID_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_NAME_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IMPORTANCE_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_CONVERSATION_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DELETED_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DEMOTED_CONVERSATION_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_IMPORTANT_CONVERSATION_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.UID_FIELD_NUMBER; import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE; import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT; import static com.android.server.notification.PreferencesHelper.UNKNOWN_UID; Loading Loading @@ -91,7 +101,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.FastXmlSerializer; import com.android.server.UiServiceTestCase; import org.json.JSONArray; import org.json.JSONObject; import org.junit.Before; Loading @@ -110,6 +119,7 @@ import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -146,6 +156,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { private PreferencesHelper mHelper; private AudioAttributes mAudioAttributes; private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake(); private WrappedSysUiStatsEvent.WrappedBuilderFactory mStatsEventBuilderFactory; @Before public void setUp() throws Exception { Loading Loading @@ -197,8 +208,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString(), eq(null), anyString())).thenReturn(MODE_DEFAULT); mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory(); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); resetZenModeHelper(); mAudioAttributes = new AudioAttributes.Builder() Loading Loading @@ -1483,7 +1497,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); Loading @@ -1495,7 +1509,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0); when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); resetZenModeHelper(); Loading Loading @@ -2262,7 +2276,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { + "</package>\n" + "</ranking>\n"; mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadByteArrayXml(preQXml.getBytes(), true, UserHandle.USER_SYSTEM); assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, Loading @@ -2275,7 +2289,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, Loading Loading @@ -2372,7 +2386,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); Loading @@ -2384,7 +2398,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); Loading @@ -2397,7 +2411,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); Loading @@ -2410,7 +2424,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); // appears disabled Loading @@ -2429,7 +2443,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); // appears disabled Loading @@ -2448,7 +2462,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O)); Loading Loading @@ -2503,7 +2517,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O)); Loading Loading @@ -2540,7 +2554,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE); Loading Loading @@ -3019,31 +3033,6 @@ public class PreferencesHelperTest extends UiServiceTestCase { PKG_O, UID_O, parent.getId(), conversationId, false, false), conversationId); } @Test public void testPullConversationNotificationChannel() { String conversationId = "friend"; NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); NotificationChannel friend = new NotificationChannel(channelId, "messages", IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), conversationId); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); boolean found = false; for (StatsEvent event : events) { // TODO(b/153195691): inspect the content once it is possible to do so found = true; } assertTrue("conversation was not in the pull", found); } @Test public void testGetNotificationChannel_conversationProvidedByNotCustomizedYet() { String conversationId = "friend"; Loading Loading @@ -3077,7 +3066,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testPlaceholderConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" Loading @@ -3096,7 +3085,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testNormalConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" Loading @@ -3115,7 +3104,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testNoConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" Loading Loading @@ -3477,4 +3466,151 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.setValidMessageSent(PKG_P, UID_P); assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P)); } @Test public void testPullPackageChannelPreferencesStats() { String channelId = "parent"; String name = "messages"; NotificationChannel fodderA = new NotificationChannel("a", "a", IMPORTANCE_LOW); mHelper.createNotificationChannel(PKG_O, UID_O, fodderA, true, false); NotificationChannel channel = new NotificationChannel(channelId, name, IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); NotificationChannel fodderB = new NotificationChannel("b", "b", IMPORTANCE_HIGH); mHelper.createNotificationChannel(PKG_O, UID_O, fodderB, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); int found = 0; for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { ++found; assertEquals("uid", UID_O, builder.getValue(UID_FIELD_NUMBER)); assertTrue("uid annotation", builder.getBooleanAnnotation( UID_FIELD_NUMBER, ANNOTATION_ID_IS_UID)); assertEquals("importance", IMPORTANCE_DEFAULT, builder.getValue( IMPORTANCE_FIELD_NUMBER)); assertEquals("name", name, builder.getValue(CHANNEL_NAME_FIELD_NUMBER)); assertFalse("isconv", builder.getBoolean(IS_CONVERSATION_FIELD_NUMBER)); assertFalse("deleted", builder.getBoolean(IS_DELETED_FIELD_NUMBER)); } } } @Test public void testPullPackageChannelPreferencesStats_one_to_one() { NotificationChannel channelA = new NotificationChannel("a", "a", IMPORTANCE_LOW); mHelper.createNotificationChannel(PKG_O, UID_O, channelA, true, false); NotificationChannel channelB = new NotificationChannel("b", "b", IMPORTANCE_LOW); mHelper.createNotificationChannel(PKG_O, UID_O, channelB, true, false); NotificationChannel channelC = new NotificationChannel("c", "c", IMPORTANCE_HIGH); mHelper.createNotificationChannel(PKG_O, UID_O, channelC, true, false); List<String> channels = new LinkedList<>(Arrays.asList("a", "b", "c")); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); int found = 0; for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES) { Object id = builder.getValue(CHANNEL_ID_FIELD_NUMBER); assertTrue("missing channel in the output", channels.contains(id)); channels.remove(id); } } assertTrue("unexpected channel in output", channels.isEmpty()); } @Test public void testPullPackageChannelPreferencesStats_conversation() { String conversationId = "friend"; NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); String name = "conversation"; NotificationChannel friend = new NotificationChannel(channelId, name, IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), conversationId); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { assertTrue("isConveration should be true", builder.getBoolean( IS_CONVERSATION_FIELD_NUMBER)); assertFalse("not demoted", builder.getBoolean( IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); assertFalse("not important", builder.getBoolean( IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); } } } @Test public void testPullPackageChannelPreferencesStats_conversation_demoted() { NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); NotificationChannel friend = new NotificationChannel(channelId, "conversation", IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), "friend"); friend.setDemoted(true); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { assertTrue("isConveration should be true", builder.getBoolean( IS_CONVERSATION_FIELD_NUMBER)); assertTrue("is demoted", builder.getBoolean( IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); assertFalse("not important", builder.getBoolean( IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); } } } @Test public void testPullPackageChannelPreferencesStats_conversation_priority() { NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); NotificationChannel friend = new NotificationChannel(channelId, "conversation", IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), "friend"); friend.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { assertTrue("isConveration should be true", builder.getBoolean( IS_CONVERSATION_FIELD_NUMBER)); assertFalse("not demoted", builder.getBoolean( IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); assertTrue("is important", builder.getBoolean( IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); } } } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +2 −1 Original line number Diff line number Diff line Loading @@ -1952,7 +1952,8 @@ public class NotificationManagerService extends SystemService { mRankingHandler, mZenModeHelper, new NotificationChannelLoggerImpl(), mAppOps); mAppOps, new SysUiStatsEvent.BuilderFactory()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, Loading
services/core/java/com/android/server/notification/PreferencesHelper.java +7 −4 Original line number Diff line number Diff line Loading @@ -140,6 +140,7 @@ public class PreferencesHelper implements RankingConfig { * fields. */ private static final int DEFAULT_LOCKED_APP_FIELDS = 0; private final SysUiStatsEvent.BuilderFactory mStatsEventBuilderFactory; /** * All user-lockable fields for a given application. Loading Loading @@ -171,13 +172,15 @@ public class PreferencesHelper implements RankingConfig { public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler, ZenModeHelper zenHelper, NotificationChannelLogger notificationChannelLogger, AppOpsManager appOpsManager) { AppOpsManager appOpsManager, SysUiStatsEvent.BuilderFactory statsEventBuilderFactory) { mContext = context; mZenModeHelper = zenHelper; mRankingHandler = rankingHandler; mPm = pm; mNotificationChannelLogger = notificationChannelLogger; mAppOps = appOpsManager; mStatsEventBuilderFactory = statsEventBuilderFactory; updateBadgingEnabled(); updateBubblesEnabled(); Loading Loading @@ -1898,7 +1901,7 @@ public class PreferencesHelper implements RankingConfig { if (i > NOTIFICATION_PREFERENCES_PULL_LIMIT) { break; } StatsEvent.Builder event = StatsEvent.newBuilder() SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES); final PackagePreferences r = mPackagePreferences.valueAt(i); event.writeInt(r.uid); Loading Loading @@ -1927,7 +1930,7 @@ public class PreferencesHelper implements RankingConfig { if (++totalChannelsPulled > NOTIFICATION_CHANNEL_PULL_LIMIT) { break; } StatsEvent.Builder event = StatsEvent.newBuilder() SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES); event.writeInt(r.uid); event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); Loading Loading @@ -1962,7 +1965,7 @@ public class PreferencesHelper implements RankingConfig { if (++totalGroupsPulled > NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT) { break; } StatsEvent.Builder event = StatsEvent.newBuilder() SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder() .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES); event.writeInt(r.uid); event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); Loading
services/core/java/com/android/server/notification/SysUiStatsEvent.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * 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.server.notification; import android.util.StatsEvent; /** * Wrapper for StatsEvent that enables unit testing. */ public class SysUiStatsEvent { static class Builder { private final StatsEvent.Builder mBuilder; protected Builder(StatsEvent.Builder builder) { mBuilder = builder; } public StatsEvent build() { return mBuilder.build(); } public Builder setAtomId(int atomId) { mBuilder.setAtomId(atomId); return this; } public Builder writeInt(int value) { mBuilder.writeInt(value); return this; } public Builder addBooleanAnnotation(byte annotation, boolean value) { mBuilder.addBooleanAnnotation(annotation, value); return this; } public Builder writeString(String value) { mBuilder.writeString(value); return this; } public Builder writeBoolean(boolean value) { mBuilder.writeBoolean(value); return this; } } static class BuilderFactory { Builder newBuilder() { return new Builder(StatsEvent.newBuilder()); } } }
services/tests/uiservicestests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ android_test { "mockito-target-inline-minus-junit4", "platform-test-annotations", "platformprotosnano", "statsdprotolite", "hamcrest-library", "testables", "truth-prebuilt", Loading
services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +178 −42 Original line number Diff line number Diff line Loading @@ -29,6 +29,16 @@ import static android.app.NotificationManager.IMPORTANCE_MAX; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID; import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_ID_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_NAME_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IMPORTANCE_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_CONVERSATION_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DELETED_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DEMOTED_CONVERSATION_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_IMPORTANT_CONVERSATION_FIELD_NUMBER; import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.UID_FIELD_NUMBER; import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE; import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT; import static com.android.server.notification.PreferencesHelper.UNKNOWN_UID; Loading Loading @@ -91,7 +101,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.FastXmlSerializer; import com.android.server.UiServiceTestCase; import org.json.JSONArray; import org.json.JSONObject; import org.junit.Before; Loading @@ -110,6 +119,7 @@ import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -146,6 +156,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { private PreferencesHelper mHelper; private AudioAttributes mAudioAttributes; private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake(); private WrappedSysUiStatsEvent.WrappedBuilderFactory mStatsEventBuilderFactory; @Before public void setUp() throws Exception { Loading Loading @@ -197,8 +208,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString(), eq(null), anyString())).thenReturn(MODE_DEFAULT); mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory(); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); resetZenModeHelper(); mAudioAttributes = new AudioAttributes.Builder() Loading Loading @@ -1483,7 +1497,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); Loading @@ -1495,7 +1509,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0); when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); resetZenModeHelper(); Loading Loading @@ -2262,7 +2276,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { + "</package>\n" + "</ranking>\n"; mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadByteArrayXml(preQXml.getBytes(), true, UserHandle.USER_SYSTEM); assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, Loading @@ -2275,7 +2289,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, Loading Loading @@ -2372,7 +2386,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); Loading @@ -2384,7 +2398,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); Loading @@ -2397,7 +2411,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); Loading @@ -2410,7 +2424,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); // appears disabled Loading @@ -2429,7 +2443,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); // appears disabled Loading @@ -2448,7 +2462,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O)); Loading Loading @@ -2503,7 +2517,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O)); Loading Loading @@ -2540,7 +2554,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); loadStreamXml(baos, false, UserHandle.USER_ALL); assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE); Loading Loading @@ -3019,31 +3033,6 @@ public class PreferencesHelperTest extends UiServiceTestCase { PKG_O, UID_O, parent.getId(), conversationId, false, false), conversationId); } @Test public void testPullConversationNotificationChannel() { String conversationId = "friend"; NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); NotificationChannel friend = new NotificationChannel(channelId, "messages", IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), conversationId); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); boolean found = false; for (StatsEvent event : events) { // TODO(b/153195691): inspect the content once it is possible to do so found = true; } assertTrue("conversation was not in the pull", found); } @Test public void testGetNotificationChannel_conversationProvidedByNotCustomizedYet() { String conversationId = "friend"; Loading Loading @@ -3077,7 +3066,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testPlaceholderConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" Loading @@ -3096,7 +3085,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testNormalConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" Loading @@ -3115,7 +3104,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testNoConversationId_shortcutRequired() throws Exception { mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger, mAppOpsManager); mAppOpsManager, mStatsEventBuilderFactory); final String xml = "<ranking version=\"1\">\n" + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" Loading Loading @@ -3477,4 +3466,151 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.setValidMessageSent(PKG_P, UID_P); assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P)); } @Test public void testPullPackageChannelPreferencesStats() { String channelId = "parent"; String name = "messages"; NotificationChannel fodderA = new NotificationChannel("a", "a", IMPORTANCE_LOW); mHelper.createNotificationChannel(PKG_O, UID_O, fodderA, true, false); NotificationChannel channel = new NotificationChannel(channelId, name, IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); NotificationChannel fodderB = new NotificationChannel("b", "b", IMPORTANCE_HIGH); mHelper.createNotificationChannel(PKG_O, UID_O, fodderB, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); int found = 0; for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { ++found; assertEquals("uid", UID_O, builder.getValue(UID_FIELD_NUMBER)); assertTrue("uid annotation", builder.getBooleanAnnotation( UID_FIELD_NUMBER, ANNOTATION_ID_IS_UID)); assertEquals("importance", IMPORTANCE_DEFAULT, builder.getValue( IMPORTANCE_FIELD_NUMBER)); assertEquals("name", name, builder.getValue(CHANNEL_NAME_FIELD_NUMBER)); assertFalse("isconv", builder.getBoolean(IS_CONVERSATION_FIELD_NUMBER)); assertFalse("deleted", builder.getBoolean(IS_DELETED_FIELD_NUMBER)); } } } @Test public void testPullPackageChannelPreferencesStats_one_to_one() { NotificationChannel channelA = new NotificationChannel("a", "a", IMPORTANCE_LOW); mHelper.createNotificationChannel(PKG_O, UID_O, channelA, true, false); NotificationChannel channelB = new NotificationChannel("b", "b", IMPORTANCE_LOW); mHelper.createNotificationChannel(PKG_O, UID_O, channelB, true, false); NotificationChannel channelC = new NotificationChannel("c", "c", IMPORTANCE_HIGH); mHelper.createNotificationChannel(PKG_O, UID_O, channelC, true, false); List<String> channels = new LinkedList<>(Arrays.asList("a", "b", "c")); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); int found = 0; for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES) { Object id = builder.getValue(CHANNEL_ID_FIELD_NUMBER); assertTrue("missing channel in the output", channels.contains(id)); channels.remove(id); } } assertTrue("unexpected channel in output", channels.isEmpty()); } @Test public void testPullPackageChannelPreferencesStats_conversation() { String conversationId = "friend"; NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); String name = "conversation"; NotificationChannel friend = new NotificationChannel(channelId, name, IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), conversationId); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { assertTrue("isConveration should be true", builder.getBoolean( IS_CONVERSATION_FIELD_NUMBER)); assertFalse("not demoted", builder.getBoolean( IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); assertFalse("not important", builder.getBoolean( IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); } } } @Test public void testPullPackageChannelPreferencesStats_conversation_demoted() { NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); NotificationChannel friend = new NotificationChannel(channelId, "conversation", IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), "friend"); friend.setDemoted(true); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { assertTrue("isConveration should be true", builder.getBoolean( IS_CONVERSATION_FIELD_NUMBER)); assertTrue("is demoted", builder.getBoolean( IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); assertFalse("not important", builder.getBoolean( IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); } } } @Test public void testPullPackageChannelPreferencesStats_conversation_priority() { NotificationChannel parent = new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); String channelId = String.format( CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); NotificationChannel friend = new NotificationChannel(channelId, "conversation", IMPORTANCE_DEFAULT); friend.setConversationId(parent.getId(), "friend"); friend.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); ArrayList<StatsEvent> events = new ArrayList<>(); mHelper.pullPackageChannelPreferencesStats(events); for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { assertTrue("isConveration should be true", builder.getBoolean( IS_CONVERSATION_FIELD_NUMBER)); assertFalse("not demoted", builder.getBoolean( IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); assertTrue("is important", builder.getBoolean( IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); } } } }