1f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk/* 2f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * Copyright (C) 2017 The Android Open Source Project 3f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * 4f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * except in compliance with the License. You may obtain a copy of the License at 6f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * 7f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 8f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * 9f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * Unless required by applicable law or agreed to in writing, software distributed under the 10f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * KIND, either express or implied. See the License for the specific language governing 12f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk * permissions and limitations under the License. 13f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk */ 14f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 15f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkpackage com.android.systemui.statusbar.policy; 16f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 17f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NUM_STATUS_ICONS; 18f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS; 19f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent 20f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk .NOTIFICATION_SINCE_CREATE_MILLIS; 21f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 22f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.junit.Assert.*; 23f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.ArgumentMatchers.any; 24f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.ArgumentMatchers.argThat; 25f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.Mockito.clearInvocations; 26f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.Mockito.mock; 27f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.Mockito.never; 28f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.Mockito.times; 29f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.Mockito.verify; 30f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static org.mockito.Mockito.when; 31f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 32f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport static java.lang.Thread.sleep; 33f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 34f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport android.metrics.LogMaker; 35b16ae4ac94f11f41d30f44bad24fbe362b5e0e55Jason Monkimport android.support.test.filters.SmallTest; 36f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport android.testing.AndroidTestingRunner; 37f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport android.testing.TestableLooper; 38f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport android.testing.TestableLooper.MessageHandler; 39f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport android.testing.TestableLooper.RunWithLooper; 40f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport android.util.Log; 41f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 42f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport com.android.internal.logging.MetricsLogger; 43f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport com.android.systemui.SysuiTestCase; 44f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 45f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport org.junit.Before; 46f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport org.junit.Test; 47f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport org.junit.runner.RunWith; 48f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkimport org.mockito.ArgumentMatcher; 49f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 50f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk@RunWith(AndroidTestingRunner.class) 51f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk@RunWithLooper 52b16ae4ac94f11f41d30f44bad24fbe362b5e0e55Jason Monk@SmallTest 53f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monkpublic class IconLoggerImplTest extends SysuiTestCase { 54f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 55f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk private MetricsLogger mMetricsLogger; 56f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk private IconLoggerImpl mIconLogger; 57f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk private TestableLooper mTestableLooper; 58f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk private MessageHandler mMessageHandler; 59f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 60f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk @Before 61f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk public void setup() { 62f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk IconLoggerImpl.MIN_LOG_INTERVAL = 5; // Low interval for testing 63f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mMetricsLogger = mock(MetricsLogger.class); 64f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper = TestableLooper.get(this); 65f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mMessageHandler = mock(MessageHandler.class); 66f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.setMessageHandler(mMessageHandler); 67f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk String[] iconArray = new String[] { 68f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk "test_icon_1", 69f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk "test_icon_2", 70f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk }; 71f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mContext.getOrCreateTestableResources().addOverride( 72f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk com.android.internal.R.array.config_statusBarIcons, iconArray); 73f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger = new IconLoggerImpl(mContext, mTestableLooper.getLooper(), mMetricsLogger); 74f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk when(mMessageHandler.onMessageHandled(any())).thenReturn(true); 75f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk clearInvocations(mMetricsLogger); 76f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 77f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 78f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk @Test 79f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk public void testIconShown() throws InterruptedException { 80f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk // Should only get one message, for the same icon shown twice. 81f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconShown("test_icon_2"); 82f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconShown("test_icon_2"); 83f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 84f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk // There should be some delay before execute. 85f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 86f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMessageHandler, never()).onMessageHandled(any()); 87f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 88f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 89f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 90f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMessageHandler, times(1)).onMessageHandled(any()); 91f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 92f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 93f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk @Test 94f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk public void testIconHidden() throws InterruptedException { 95f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk // Add the icon so that it can be removed. 96f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconShown("test_icon_2"); 97f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 98f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 99f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk clearInvocations(mMessageHandler); 100f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 101f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk // Should only get one message, for the same icon shown twice. 102f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconHidden("test_icon_2"); 103f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconHidden("test_icon_2"); 104f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 105f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk // There should be some delay before execute. 106f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 107f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMessageHandler, never()).onMessageHandled(any()); 108f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 109f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 110f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 111f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMessageHandler, times(1)).onMessageHandled(any()); 112f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 113f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 114f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk @Test 115f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk public void testLog() throws InterruptedException { 116f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconShown("test_icon_2"); 117f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 118f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 119f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 120f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMetricsLogger).write(argThat(maker -> { 121f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk if (IconLoggerImpl.MIN_LOG_INTERVAL > 122f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk (long) maker.getTaggedData(NOTIFICATION_SINCE_CREATE_MILLIS)) { 123f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk Log.e("IconLoggerImplTest", "Invalid latency " 124f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk + maker.getTaggedData(NOTIFICATION_SINCE_CREATE_MILLIS)); 125f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return false; 126f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 127f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk if (1 != (int) maker.getTaggedData(FIELD_NUM_STATUS_ICONS)) { 128f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk Log.e("IconLoggerImplTest", "Invalid icon count " 129f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk + maker.getTaggedData(FIELD_NUM_STATUS_ICONS)); 130f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return false; 131f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 132f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return true; 133f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk })); 134f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 135f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 136f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk @Test 137f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk public void testBitField() throws InterruptedException { 138f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconShown("test_icon_2"); 139f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 140f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 141f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 142f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMetricsLogger).write(argThat(maker -> { 143f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk if ((1 << 1) != (int) maker.getTaggedData(FIELD_STATUS_ICONS)) { 144f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk Log.e("IconLoggerImplTest", "Invalid bitfield " + Integer.toHexString( 145f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk (Integer) maker.getTaggedData(FIELD_NUM_STATUS_ICONS))); 146f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return false; 147f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 148f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return true; 149f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk })); 150f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 151f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconShown("test_icon_1"); 152f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 153f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 154f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 155f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMetricsLogger).write(argThat(maker -> { 156f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk if ((1 << 1 | 1 << 0) != (int) maker.getTaggedData(FIELD_STATUS_ICONS)) { 157f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk Log.e("IconLoggerImplTest", "Invalid bitfield " + Integer.toHexString( 158f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk (Integer) maker.getTaggedData(FIELD_NUM_STATUS_ICONS))); 159f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return false; 160f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 161f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return true; 162f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk })); 163f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 164f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mIconLogger.onIconHidden("test_icon_2"); 165f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk sleep(10); 166f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk mTestableLooper.processAllMessages(); 167f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk 168f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk verify(mMetricsLogger).write(argThat(maker -> { 169f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk if ((1 << 0) != (int) maker.getTaggedData(FIELD_STATUS_ICONS)) { 170f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk Log.e("IconLoggerImplTest", "Invalid bitfield " + Integer.toHexString( 171f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk (Integer) maker.getTaggedData(FIELD_STATUS_ICONS))); 172f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return false; 173f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 174f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk return true; 175f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk })); 176f8c2f7bd7baf0d001a707af48b3152f26fbaeda2Jason Monk } 177b16ae4ac94f11f41d30f44bad24fbe362b5e0e55Jason Monk} 178