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 android.app; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 20 21 import static junit.framework.Assert.assertEquals; 22 import static junit.framework.Assert.assertNotNull; 23 import static junit.framework.Assert.assertNull; 24 25 import static org.junit.Assert.assertFalse; 26 import static org.mockito.ArgumentMatchers.any; 27 import static org.mockito.ArgumentMatchers.anyInt; 28 import static org.mockito.ArgumentMatchers.anyString; 29 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.content.Intent; 35 import android.content.IntentFilter; 36 import android.media.AudioManager; 37 import android.os.IpcDataCache; 38 import android.os.RemoteException; 39 import android.platform.test.annotations.DisableFlags; 40 import android.platform.test.annotations.EnableFlags; 41 import android.platform.test.flag.junit.SetFlagsRule; 42 43 import com.android.dx.mockito.inline.extended.ExtendedMockito; 44 import com.android.internal.annotations.Keep; 45 import com.android.modules.utils.testing.ExtendedMockitoRule; 46 47 import junitparams.JUnitParamsRunner; 48 import junitparams.Parameters; 49 50 import org.junit.Before; 51 import org.junit.Rule; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 import org.mockito.Mock; 55 56 @RunWith(JUnitParamsRunner.class) 57 public class BroadcastStickyCacheTest { 58 59 @Rule 60 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 61 @Rule 62 public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) 63 .mockStatic(IpcDataCache.class) 64 .mockStatic(ActivityManager.class) 65 .build(); 66 67 @Mock 68 private IActivityManager mActivityManagerMock; 69 70 @Mock 71 private IApplicationThread mIApplicationThreadMock; 72 73 @Keep stickyBroadcastList()74 private static Object stickyBroadcastList() { 75 return BroadcastStickyCache.STICKY_BROADCAST_ACTIONS; 76 } 77 78 @Before setUp()79 public void setUp() { 80 BroadcastStickyCache.clearCacheForTest(); 81 82 doNothing().when(() -> IpcDataCache.invalidateCache(anyString(), anyString())); 83 } 84 85 @Test 86 @DisableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) useCache_flagDisabled_returnsFalse()87 public void useCache_flagDisabled_returnsFalse() { 88 assertFalse(BroadcastStickyCache.useCache(new IntentFilter(Intent.ACTION_BATTERY_CHANGED))); 89 } 90 91 @Test 92 @EnableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) useCache_nullFilter_returnsFalse()93 public void useCache_nullFilter_returnsFalse() { 94 assertFalse(BroadcastStickyCache.useCache(null)); 95 } 96 97 @Test 98 @EnableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) useCache_filterWithoutAction_returnsFalse()99 public void useCache_filterWithoutAction_returnsFalse() { 100 assertFalse(BroadcastStickyCache.useCache(new IntentFilter())); 101 } 102 103 @Test 104 @EnableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) useCache_filterWithoutStickyBroadcastAction_returnsFalse()105 public void useCache_filterWithoutStickyBroadcastAction_returnsFalse() { 106 assertFalse(BroadcastStickyCache.useCache(new IntentFilter(Intent.ACTION_BOOT_COMPLETED))); 107 } 108 109 @Test 110 @DisableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) invalidateCache_flagDisabled_cacheNotInvalidated()111 public void invalidateCache_flagDisabled_cacheNotInvalidated() { 112 final String apiName = BroadcastStickyCache.sActionApiNameMap.get( 113 AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 114 115 BroadcastStickyCache.invalidateCache( 116 AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 117 118 ExtendedMockito.verify( 119 () -> IpcDataCache.invalidateCache(eq(IpcDataCache.MODULE_SYSTEM), eq(apiName)), 120 times(0)); 121 } 122 123 @Test 124 @EnableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) invalidateCache_broadcastNotSticky_cacheNotInvalidated()125 public void invalidateCache_broadcastNotSticky_cacheNotInvalidated() { 126 BroadcastStickyCache.invalidateCache(Intent.ACTION_AIRPLANE_MODE_CHANGED); 127 128 ExtendedMockito.verify( 129 () -> IpcDataCache.invalidateCache(eq(IpcDataCache.MODULE_SYSTEM), anyString()), 130 times(0)); 131 } 132 133 @Test 134 @EnableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) invalidateCache_withStickyBroadcast_cacheInvalidated()135 public void invalidateCache_withStickyBroadcast_cacheInvalidated() { 136 final String apiName = BroadcastStickyCache.sActionApiNameMap.get( 137 Intent.ACTION_BATTERY_CHANGED); 138 139 BroadcastStickyCache.invalidateCache(Intent.ACTION_BATTERY_CHANGED); 140 141 ExtendedMockito.verify( 142 () -> IpcDataCache.invalidateCache(eq(IpcDataCache.MODULE_SYSTEM), eq(apiName)), 143 times(1)); 144 } 145 146 @Test invalidateAllCaches_cacheInvalidated()147 public void invalidateAllCaches_cacheInvalidated() { 148 BroadcastStickyCache.invalidateAllCaches(); 149 150 for (int i = BroadcastStickyCache.sActionApiNameMap.size() - 1; i > -1; i--) { 151 final String apiName = BroadcastStickyCache.sActionApiNameMap.valueAt(i); 152 ExtendedMockito.verify(() -> IpcDataCache.invalidateCache(anyString(), 153 eq(apiName)), times(1)); 154 } 155 } 156 157 @Test 158 @Parameters(method = "stickyBroadcastList") getIntent_createNewCache_verifyRegisterReceiverIsCalled(String action)159 public void getIntent_createNewCache_verifyRegisterReceiverIsCalled(String action) 160 throws RemoteException { 161 setActivityManagerMock(action); 162 final IntentFilter filter = new IntentFilter(action); 163 final Intent intent = queryIntent(filter); 164 165 assertNotNull(intent); 166 assertEquals(intent.getAction(), action); 167 verify(mActivityManagerMock, times(1)).registerReceiverWithFeature( 168 eq(mIApplicationThreadMock), anyString(), anyString(), anyString(), any(), 169 eq(filter), anyString(), anyInt(), anyInt()); 170 } 171 172 @Test getIntent_querySameValueTwice_verifyRegisterReceiverIsCalledOnce()173 public void getIntent_querySameValueTwice_verifyRegisterReceiverIsCalledOnce() 174 throws RemoteException { 175 setActivityManagerMock(Intent.ACTION_DEVICE_STORAGE_LOW); 176 final Intent intent = queryIntent(new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)); 177 final Intent cachedIntent = queryIntent(new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)); 178 179 assertNotNull(intent); 180 assertEquals(intent.getAction(), Intent.ACTION_DEVICE_STORAGE_LOW); 181 assertNotNull(cachedIntent); 182 assertEquals(cachedIntent.getAction(), Intent.ACTION_DEVICE_STORAGE_LOW); 183 184 verify(mActivityManagerMock, times(1)).registerReceiverWithFeature( 185 eq(mIApplicationThreadMock), anyString(), anyString(), anyString(), any(), 186 any(), anyString(), anyInt(), anyInt()); 187 } 188 189 @Test getIntent_queryActionTwiceWithNullResult_verifyRegisterReceiverIsCalledOnce()190 public void getIntent_queryActionTwiceWithNullResult_verifyRegisterReceiverIsCalledOnce() 191 throws RemoteException { 192 setActivityManagerMock(null); 193 final Intent intent = queryIntent(new IntentFilter(Intent.ACTION_DEVICE_STORAGE_FULL)); 194 final Intent cachedIntent = queryIntent( 195 new IntentFilter(Intent.ACTION_DEVICE_STORAGE_FULL)); 196 197 assertNull(intent); 198 assertNull(cachedIntent); 199 200 verify(mActivityManagerMock, times(1)).registerReceiverWithFeature( 201 eq(mIApplicationThreadMock), anyString(), anyString(), anyString(), any(), 202 any(), anyString(), anyInt(), anyInt()); 203 } 204 205 @Test getIntent_querySameActionWithDifferentFilter_verifyRegisterReceiverCalledTwice()206 public void getIntent_querySameActionWithDifferentFilter_verifyRegisterReceiverCalledTwice() 207 throws RemoteException { 208 setActivityManagerMock(Intent.ACTION_DEVICE_STORAGE_LOW); 209 final IntentFilter filter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); 210 final Intent intent = queryIntent(filter); 211 212 final IntentFilter newFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); 213 newFilter.addDataScheme("file"); 214 final Intent newIntent = queryIntent(newFilter); 215 216 assertNotNull(intent); 217 assertEquals(intent.getAction(), Intent.ACTION_DEVICE_STORAGE_LOW); 218 assertNotNull(newIntent); 219 assertEquals(newIntent.getAction(), Intent.ACTION_DEVICE_STORAGE_LOW); 220 221 verify(mActivityManagerMock, times(1)).registerReceiverWithFeature( 222 eq(mIApplicationThreadMock), anyString(), anyString(), anyString(), any(), 223 eq(filter), anyString(), anyInt(), anyInt()); 224 225 verify(mActivityManagerMock, times(1)).registerReceiverWithFeature( 226 eq(mIApplicationThreadMock), anyString(), anyString(), anyString(), any(), 227 eq(newFilter), anyString(), anyInt(), anyInt()); 228 } 229 queryIntent(IntentFilter filter)230 private Intent queryIntent(IntentFilter filter) { 231 return BroadcastStickyCache.getIntent( 232 mIApplicationThreadMock, 233 "android", 234 "android", 235 filter, 236 "system", 237 0, 238 0 239 ); 240 } 241 setActivityManagerMock(String action)242 private void setActivityManagerMock(String action) throws RemoteException { 243 when(ActivityManager.getService()).thenReturn(mActivityManagerMock); 244 when(mActivityManagerMock.registerReceiverWithFeature(any(), anyString(), 245 anyString(), anyString(), any(), any(), anyString(), anyInt(), 246 anyInt())).thenReturn(action != null ? new Intent(action) : null); 247 } 248 } 249