1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.activity.data.repository 18 19 import android.app.ActivityManager 20 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND 21 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE 22 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING 23 import android.app.activityManager 24 import androidx.test.ext.junit.runners.AndroidJUnit4 25 import androidx.test.filters.SmallTest 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.kosmos.Kosmos 28 import com.android.systemui.kosmos.collectLastValue 29 import com.android.systemui.kosmos.runTest 30 import com.android.systemui.kosmos.useUnconfinedTestDispatcher 31 import com.android.systemui.log.core.Logger 32 import com.android.systemui.log.logcatLogBuffer 33 import com.android.systemui.testKosmos 34 import com.google.common.truth.Truth.assertThat 35 import org.junit.Test 36 import org.junit.runner.RunWith 37 import org.mockito.kotlin.any 38 import org.mockito.kotlin.argumentCaptor 39 import org.mockito.kotlin.verify 40 import org.mockito.kotlin.whenever 41 42 @SmallTest 43 @RunWith(AndroidJUnit4::class) 44 class ActivityManagerRepositoryTest : SysuiTestCase() { 45 private val kosmos = testKosmos().useUnconfinedTestDispatcher() 46 private val logger = Logger(logcatLogBuffer("ActivityManagerRepositoryTest"), "tag") 47 <lambda>null48 private val Kosmos.underTest by Kosmos.Fixture { realActivityManagerRepository } 49 50 @Test createIsAppVisibleFlow_fetchesInitialValue_truenull51 fun createIsAppVisibleFlow_fetchesInitialValue_true() = 52 kosmos.runTest { 53 whenever(activityManager.getUidImportance(THIS_UID)).thenReturn(IMPORTANCE_FOREGROUND) 54 55 val latest by 56 collectLastValue(underTest.createIsAppVisibleFlow(THIS_UID, logger, LOG_TAG)) 57 58 assertThat(latest).isTrue() 59 } 60 61 @Test createIsAppVisibleFlow_fetchesInitialValue_falsenull62 fun createIsAppVisibleFlow_fetchesInitialValue_false() = 63 kosmos.runTest { 64 whenever(activityManager.getUidImportance(THIS_UID)).thenReturn(IMPORTANCE_GONE) 65 66 val latest by 67 collectLastValue(underTest.createIsAppVisibleFlow(THIS_UID, logger, LOG_TAG)) 68 69 assertThat(latest).isFalse() 70 } 71 72 @Test createIsAppVisibleFlow_getsImportanceUpdatesnull73 fun createIsAppVisibleFlow_getsImportanceUpdates() = 74 kosmos.runTest { 75 val latest by 76 collectLastValue(underTest.createIsAppVisibleFlow(THIS_UID, logger, LOG_TAG)) 77 78 val listenerCaptor = argumentCaptor<ActivityManager.OnUidImportanceListener>() 79 verify(activityManager).addOnUidImportanceListener(listenerCaptor.capture(), any()) 80 val listener = listenerCaptor.firstValue 81 82 listener.onUidImportance(THIS_UID, IMPORTANCE_GONE) 83 assertThat(latest).isFalse() 84 85 listener.onUidImportance(THIS_UID, IMPORTANCE_FOREGROUND) 86 assertThat(latest).isTrue() 87 88 listener.onUidImportance(THIS_UID, IMPORTANCE_TOP_SLEEPING) 89 assertThat(latest).isFalse() 90 } 91 92 @Test createIsAppVisibleFlow_ignoresUpdatesForOtherUidsnull93 fun createIsAppVisibleFlow_ignoresUpdatesForOtherUids() = 94 kosmos.runTest { 95 val latest by 96 collectLastValue(underTest.createIsAppVisibleFlow(THIS_UID, logger, LOG_TAG)) 97 98 val listenerCaptor = argumentCaptor<ActivityManager.OnUidImportanceListener>() 99 verify(activityManager).addOnUidImportanceListener(listenerCaptor.capture(), any()) 100 val listener = listenerCaptor.firstValue 101 102 listener.onUidImportance(THIS_UID, IMPORTANCE_GONE) 103 assertThat(latest).isFalse() 104 105 // WHEN another UID becomes foreground 106 listener.onUidImportance(THIS_UID + 2, IMPORTANCE_FOREGROUND) 107 108 // THEN this UID still stays not visible 109 assertThat(latest).isFalse() 110 } 111 112 @Test createIsAppVisibleFlow_securityExceptionOnUidRegistration_oknull113 fun createIsAppVisibleFlow_securityExceptionOnUidRegistration_ok() = 114 kosmos.runTest { 115 whenever(activityManager.getUidImportance(THIS_UID)).thenReturn(IMPORTANCE_GONE) 116 whenever(activityManager.addOnUidImportanceListener(any(), any())) 117 .thenThrow(SecurityException()) 118 119 val latest by 120 collectLastValue(underTest.createIsAppVisibleFlow(THIS_UID, logger, LOG_TAG)) 121 122 // Verify no crash, and we get a value emitted 123 assertThat(latest).isFalse() 124 } 125 126 /** Regression test for b/216248574. */ 127 @Test createIsAppVisibleFlow_getUidImportanceThrowsException_oknull128 fun createIsAppVisibleFlow_getUidImportanceThrowsException_ok() = 129 kosmos.runTest { 130 whenever(activityManager.getUidImportance(any())).thenThrow(SecurityException()) 131 132 val latest by 133 collectLastValue(underTest.createIsAppVisibleFlow(THIS_UID, logger, LOG_TAG)) 134 135 // Verify no crash, and we get a value emitted 136 assertThat(latest).isFalse() 137 } 138 139 companion object { 140 private const val THIS_UID = 558 141 private const val LOG_TAG = "LogTag" 142 } 143 } 144