Files
app_Settings/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
Kuan Wang 4028e6123c Reset Optimization Mode of apps when users reset app settings.
Fix the issue that Optimization Mode is not reset when users click the
"Reset apps" button in the setting.

Bug: 222037028
Test: make RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.fuelgauge" + emulator
Change-Id: I22fb8aa19e284e11882b2920b77b544dee4cc33c
2022-05-16 05:01:20 +00:00

334 lines
13 KiB
Java

/*
* Copyright (C) 2021 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.settings.fuelgauge;
import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_OPTIMIZED;
import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_RESTRICTED;
import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.os.UserManager;
import android.util.ArraySet;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class)
public class BatteryOptimizeUtilsTest {
private static final int UID = 12345;
private static final String PACKAGE_NAME = "com.android.app";
@Mock private BatteryUtils mMockBatteryUtils;
@Mock private AppOpsManager mMockAppOpsManager;
@Mock private PowerAllowlistBackend mMockBackend;
@Mock private IPackageManager mMockIPackageManager;
@Mock private UserManager mMockUserManager;
private Context mContext;
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
mBatteryOptimizeUtils.mAppOpsManager = mMockAppOpsManager;
mBatteryOptimizeUtils.mBatteryUtils = mMockBatteryUtils;
mBatteryOptimizeUtils.mPowerAllowListBackend = mMockBackend;
// Sets the default mode as MODE_RESTRICTED.
mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_IGNORED;
mBatteryOptimizeUtils.mAllowListed = false;
doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class);
}
@Test
public void testGetAppOptimizationMode_returnRestricted() {
when(mMockBackend.isAllowlisted(anyString())).thenReturn(false);
when(mMockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
.thenReturn(AppOpsManager.MODE_IGNORED);
assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
.isEqualTo(MODE_RESTRICTED);
}
@Test
public void testGetAppOptimizationMode_returnUnrestricted() {
when(mMockBackend.isAllowlisted(anyString())).thenReturn(true);
when(mMockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
.thenReturn(AppOpsManager.MODE_ALLOWED);
assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
.isEqualTo(MODE_UNRESTRICTED);
}
@Test
public void testGetAppOptimizationMode_returnOptimized() {
when(mMockBackend.isAllowlisted(anyString())).thenReturn(false);
when(mMockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
.thenReturn(AppOpsManager.MODE_ALLOWED);
assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
.isEqualTo(MODE_OPTIMIZED);
}
@Test
public void testIsSystemOrDefaultApp_isSystemOrDefaultApp_returnTrue() {
when(mMockBackend.isAllowlisted(anyString())).thenReturn(true);
when(mMockBackend.isDefaultActiveApp(anyString())).thenReturn(true);
assertThat(mBatteryOptimizeUtils.isSystemOrDefaultApp()).isTrue();
}
@Test
public void testIsSystemOrDefaultApp_notSystemOrDefaultApp_returnFalse() {
assertThat(mBatteryOptimizeUtils.isSystemOrDefaultApp()).isFalse();
}
@Test
public void testIsValidPackageName_InvalidPackageName_returnFalse() {
final BatteryOptimizeUtils testBatteryOptimizeUtils =
new BatteryOptimizeUtils(mContext, UID, null);
assertThat(testBatteryOptimizeUtils.isValidPackageName()).isFalse();
}
@Test
public void testIsValidPackageName_validPackageName_returnTrue() {
assertThat(mBatteryOptimizeUtils.isValidPackageName()).isTrue();
}
@Test
public void testSetAppUsageState_Restricted_verifyAction() throws Exception {
// Sets the current mode as MODE_UNRESTRICTED.
mBatteryOptimizeUtils.mAllowListed = false;
mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_ALLOWED;
mBatteryOptimizeUtils.setAppUsageState(MODE_RESTRICTED);
TimeUnit.SECONDS.sleep(1);
verifySetAppOptimizationMode(AppOpsManager.MODE_IGNORED, /* allowListed */ false);
}
@Test
public void testSetAppUsageState_Unrestricted_verifyAction() throws Exception {
mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
TimeUnit.SECONDS.sleep(1);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ true);
}
@Test
public void testSetAppUsageState_Optimized_verifyAction() throws Exception {
mBatteryOptimizeUtils.setAppUsageState(MODE_OPTIMIZED);
TimeUnit.SECONDS.sleep(1);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
}
@Test
public void testSetAppUsageState_sameUnrestrictedMode_verifyNoAction() throws Exception {
// Sets the current mode as MODE_UNRESTRICTED.
mBatteryOptimizeUtils.mAllowListed = true;
mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_ALLOWED;
mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
TimeUnit.SECONDS.sleep(1);
verifyZeroInteractions(mMockBackend);
verifyZeroInteractions(mMockBatteryUtils);
}
@Test
public void testGetInstalledApplications_returnEmptyArray() {
assertTrue(BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager)
.isEmpty());
}
@Test
public void testGetInstalledApplications_returnNull() throws Exception {
final UserInfo userInfo =
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
doThrow(new RuntimeException())
.when(mMockIPackageManager)
.getInstalledApplications(anyLong(), anyInt());
assertNull(BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager));
}
@Test
public void testGetInstalledApplications_returnInstalledApps() throws Exception {
final UserInfo userInfo =
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
final ApplicationInfo applicationInfo1 = new ApplicationInfo();
applicationInfo1.enabled = true;
applicationInfo1.uid = 1;
final ApplicationInfo applicationInfo2 = new ApplicationInfo();
applicationInfo2.enabled = false;
applicationInfo2.uid = 2;
applicationInfo2.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
final ApplicationInfo applicationInfo3 = new ApplicationInfo();
applicationInfo3.enabled = false;
applicationInfo3.uid = 3;
applicationInfo3.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
final ApplicationInfo applicationInfo4 = new ApplicationInfo();
applicationInfo4.enabled = true;
applicationInfo4.uid = 4;
applicationInfo4.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
doReturn(new ParceledListSlice<ApplicationInfo>(
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3, applicationInfo4)))
.when(mMockIPackageManager)
.getInstalledApplications(anyLong(), anyInt());
final ArraySet<ApplicationInfo> applications =
BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager);
assertThat(applications.size()).isEqualTo(3);
// applicationInfo3 should be filtered.
assertTrue(applications.contains(applicationInfo1));
assertTrue(applications.contains(applicationInfo2));
assertFalse(applications.contains(applicationInfo3));
assertTrue(applications.contains(applicationInfo4));
}
@Test
public void testResetAppOptimizationMode_Optimized_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_ALLOWED, /* allowListed */ false,
/* isSystemOrDefaultApp */ false);
verifyZeroInteractions(mMockBatteryUtils);
final InOrder inOrder = inOrder(mMockBackend);
inOrder.verify(mMockBackend).refreshList();
inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME);
verifyNoMoreInteractions(mMockBackend);
}
@Test
public void testResetAppOptimizationMode_SystemOrDefault_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
/* isSystemOrDefaultApp */ true);
verifyZeroInteractions(mMockBatteryUtils);
final InOrder inOrder = inOrder(mMockBackend);
inOrder.verify(mMockBackend).refreshList();
inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME);
inOrder.verify(mMockBackend).isSysAllowlisted(PACKAGE_NAME);
verifyNoMoreInteractions(mMockBackend);
}
@Test
public void testResetAppOptimizationMode_Restricted_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_IGNORED, /* allowListed */ false,
/* isSystemOrDefaultApp */ false);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
}
@Test
public void testResetAppOptimizationMode_Unrestricted_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
/* isSystemOrDefaultApp */ false);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
}
private void runTestForResetWithMode(
int appStandbyMode, boolean allowListed, boolean isSystemOrDefaultApp)
throws Exception {
final UserInfo userInfo =
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = UID;
applicationInfo.packageName = PACKAGE_NAME;
applicationInfo.enabled = true;
doReturn(new ParceledListSlice<ApplicationInfo>(
Arrays.asList(applicationInfo)))
.when(mMockIPackageManager)
.getInstalledApplications(anyLong(), anyInt());
doReturn(appStandbyMode)
.when(mMockAppOpsManager)
.checkOpNoThrow(anyInt(), anyInt(), anyString());
doReturn(allowListed)
.when(mMockBackend)
.isAllowlisted(anyString());
doReturn(isSystemOrDefaultApp)
.when(mMockBackend)
.isSysAllowlisted(anyString());
doReturn(isSystemOrDefaultApp)
.when(mMockBackend)
.isDefaultActiveApp(anyString());
BatteryOptimizeUtils.resetAppOptimizationMode(
mContext, mMockIPackageManager, mMockAppOpsManager, mMockBackend,
mMockBatteryUtils);
TimeUnit.SECONDS.sleep(1);
}
private void verifySetAppOptimizationMode(int appStandbyMode, boolean allowListed) {
verify(mMockBatteryUtils).setForceAppStandby(UID, PACKAGE_NAME, appStandbyMode);
if (allowListed) {
verify(mMockBackend).addApp(PACKAGE_NAME);
} else {
verify(mMockBackend).removeApp(PACKAGE_NAME);
}
}
}