1 /* 2 * Copyright (C) 2022 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.server.tare; 18 19 import static android.app.tare.EconomyManager.arcToCake; 20 import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS; 21 22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 26 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 27 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.fail; 30 import static org.mockito.ArgumentMatchers.any; 31 import static org.mockito.ArgumentMatchers.anyInt; 32 import static org.mockito.Mockito.eq; 33 import static org.mockito.Mockito.mock; 34 35 import android.app.ActivityManager; 36 import android.app.IActivityManager; 37 import android.app.tare.EconomyManager; 38 import android.content.ContentResolver; 39 import android.content.Context; 40 import android.os.BatteryManager; 41 import android.os.Looper; 42 import android.os.PowerManager; 43 import android.os.RemoteException; 44 import android.provider.DeviceConfig; 45 46 import androidx.annotation.NonNull; 47 import androidx.annotation.Nullable; 48 import androidx.test.runner.AndroidJUnit4; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 import org.mockito.ArgumentMatchers; 55 import org.mockito.Mock; 56 import org.mockito.MockitoSession; 57 import org.mockito.quality.Strictness; 58 import org.mockito.stubbing.Answer; 59 60 @RunWith(AndroidJUnit4.class) 61 public class AlarmManagerEconomicPolicyTest { 62 private AlarmManagerEconomicPolicy mEconomicPolicy; 63 private DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder; 64 private EconomicPolicy.Injector mInjector = new InjectorForTest(); 65 66 private MockitoSession mMockingSession; 67 @Mock 68 private Context mContext; 69 @Mock 70 private InternalResourceService mIrs; 71 72 private static class InjectorForTest extends EconomicPolicy.Injector { 73 public String settingsConstant; 74 75 @Nullable 76 @Override getSettingsGlobalString(@onNull ContentResolver resolver, @NonNull String name)77 String getSettingsGlobalString(@NonNull ContentResolver resolver, @NonNull String name) { 78 return TARE_ALARM_MANAGER_CONSTANTS.equals(name) ? settingsConstant : null; 79 } 80 } 81 82 @Before setUp()83 public void setUp() { 84 mMockingSession = mockitoSession() 85 .initMocks(this) 86 .strictness(Strictness.LENIENT) 87 .spyStatic(DeviceConfig.class) 88 .startMocking(); 89 90 when(mIrs.getContext()).thenReturn(mContext); 91 when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); 92 when(mContext.getContentResolver()).thenReturn(mock(ContentResolver.class)); 93 // Called by Modifiers. 94 when(mContext.getSystemService(BatteryManager.class)) 95 .thenReturn(mock(BatteryManager.class)); 96 when(mContext.getSystemService(PowerManager.class)) 97 .thenReturn(mock(PowerManager.class)); 98 IActivityManager activityManager = ActivityManager.getService(); 99 spyOn(activityManager); 100 try { 101 doNothing().when(activityManager).registerUidObserver(any(), anyInt(), anyInt(), any()); 102 } catch (RemoteException e) { 103 fail("registerUidObserver threw exception: " + e.getMessage()); 104 } 105 106 mDeviceConfigPropertiesBuilder = 107 new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_TARE); 108 doAnswer( 109 (Answer<DeviceConfig.Properties>) invocationOnMock 110 -> mDeviceConfigPropertiesBuilder.build()) 111 .when(() -> DeviceConfig.getProperties( 112 eq(DeviceConfig.NAMESPACE_TARE), ArgumentMatchers.<String>any())); 113 114 // Initialize real objects. 115 // Capture the listeners. 116 mEconomicPolicy = new AlarmManagerEconomicPolicy(mIrs, mInjector); 117 } 118 119 @After tearDown()120 public void tearDown() { 121 if (mMockingSession != null) { 122 mMockingSession.finishMocking(); 123 } 124 } 125 setDeviceConfigCakes(String key, long valCakes)126 private void setDeviceConfigCakes(String key, long valCakes) { 127 mDeviceConfigPropertiesBuilder.setString(key, valCakes + "c"); 128 mEconomicPolicy.setup(mDeviceConfigPropertiesBuilder.build()); 129 } 130 131 @Test testDefaults()132 public void testDefaults() { 133 assertEquals(EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES, 134 mEconomicPolicy.getInitialSatiatedConsumptionLimit()); 135 assertEquals(EconomyManager.DEFAULT_AM_MIN_CONSUMPTION_LIMIT_CAKES, 136 mEconomicPolicy.getMinSatiatedConsumptionLimit()); 137 assertEquals(EconomyManager.DEFAULT_AM_MAX_CONSUMPTION_LIMIT_CAKES, 138 mEconomicPolicy.getMaxSatiatedConsumptionLimit()); 139 140 final String pkgRestricted = "com.pkg.restricted"; 141 when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true); 142 assertEquals(0, mEconomicPolicy.getMinSatiatedBalance(0, pkgRestricted)); 143 assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted)); 144 145 final String pkgExempted = "com.pkg.exempted"; 146 when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); 147 assertEquals(EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, 148 mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); 149 assertEquals(EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES, 150 mEconomicPolicy.getMaxSatiatedBalance(0, pkgExempted)); 151 152 final String pkgHeadlessSystemApp = "com.pkg.headless_system_app"; 153 when(mIrs.isHeadlessSystemApp(anyInt(), eq(pkgHeadlessSystemApp))).thenReturn(true); 154 assertEquals(EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES, 155 mEconomicPolicy.getMinSatiatedBalance(0, pkgHeadlessSystemApp)); 156 assertEquals(EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES, 157 mEconomicPolicy.getMaxSatiatedBalance(0, pkgHeadlessSystemApp)); 158 159 assertEquals(EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, 160 mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); 161 assertEquals(EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES, 162 mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); 163 } 164 165 @Test testConstantsUpdating_ValidValues()166 public void testConstantsUpdating_ValidValues() { 167 setDeviceConfigCakes(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT, arcToCake(5)); 168 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_CONSUMPTION_LIMIT, arcToCake(3)); 169 setDeviceConfigCakes(EconomyManager.KEY_AM_MAX_CONSUMPTION_LIMIT, arcToCake(25)); 170 setDeviceConfigCakes(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE, arcToCake(10)); 171 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(9)); 172 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, 173 arcToCake(8)); 174 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(7)); 175 176 assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); 177 assertEquals(arcToCake(3), mEconomicPolicy.getMinSatiatedConsumptionLimit()); 178 assertEquals(arcToCake(25), mEconomicPolicy.getMaxSatiatedConsumptionLimit()); 179 final String pkgRestricted = "com.pkg.restricted"; 180 when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true); 181 assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted)); 182 assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); 183 final String pkgExempted = "com.pkg.exempted"; 184 when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); 185 assertEquals(arcToCake(9), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); 186 final String pkgHeadlessSystemApp = "com.pkg.headless_system_app"; 187 when(mIrs.isHeadlessSystemApp(anyInt(), eq(pkgHeadlessSystemApp))).thenReturn(true); 188 assertEquals(arcToCake(8), mEconomicPolicy.getMinSatiatedBalance(0, pkgHeadlessSystemApp)); 189 assertEquals(arcToCake(7), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); 190 } 191 192 @Test testConstantsUpdating_InvalidValues()193 public void testConstantsUpdating_InvalidValues() { 194 // Test negatives. 195 setDeviceConfigCakes(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT, arcToCake(-5)); 196 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_CONSUMPTION_LIMIT, arcToCake(-5)); 197 setDeviceConfigCakes(EconomyManager.KEY_AM_MAX_CONSUMPTION_LIMIT, arcToCake(-5)); 198 setDeviceConfigCakes(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE, arcToCake(-1)); 199 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(-2)); 200 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, 201 arcToCake(-3)); 202 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(-3)); 203 204 assertEquals(arcToCake(1), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); 205 assertEquals(arcToCake(1), mEconomicPolicy.getMinSatiatedConsumptionLimit()); 206 assertEquals(arcToCake(1), mEconomicPolicy.getMaxSatiatedConsumptionLimit()); 207 final String pkgRestricted = "com.pkg.restricted"; 208 when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true); 209 assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted)); 210 assertEquals(arcToCake(1), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); 211 final String pkgExempted = "com.pkg.exempted"; 212 when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); 213 assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); 214 final String pkgHeadlessSystemApp = "com.pkg.headless_system_app"; 215 when(mIrs.isHeadlessSystemApp(anyInt(), eq(pkgHeadlessSystemApp))).thenReturn(true); 216 assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgHeadlessSystemApp)); 217 assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); 218 219 // Test min+max reversed. 220 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_CONSUMPTION_LIMIT, arcToCake(5)); 221 setDeviceConfigCakes(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT, arcToCake(4)); 222 setDeviceConfigCakes(EconomyManager.KEY_AM_MAX_CONSUMPTION_LIMIT, arcToCake(3)); 223 setDeviceConfigCakes(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE, arcToCake(10)); 224 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(11)); 225 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, 226 arcToCake(12)); 227 setDeviceConfigCakes(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(13)); 228 229 assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); 230 assertEquals(arcToCake(5), mEconomicPolicy.getMinSatiatedConsumptionLimit()); 231 assertEquals(arcToCake(5), mEconomicPolicy.getMaxSatiatedConsumptionLimit()); 232 assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted)); 233 assertEquals(arcToCake(13), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); 234 assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); 235 assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, pkgHeadlessSystemApp)); 236 assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); 237 } 238 } 239