1 /*
2  * Copyright (C) 2021 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.settings.fuelgauge;
18 
19 import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_OPTIMIZED;
20 import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_RESTRICTED;
21 import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 
25 import static org.mockito.ArgumentMatchers.anyInt;
26 import static org.mockito.ArgumentMatchers.anyString;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.verifyZeroInteractions;
30 import static org.mockito.Mockito.when;
31 
32 import android.app.AppOpsManager;
33 import android.content.Context;
34 
35 import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
36 
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.mockito.Mock;
41 import org.mockito.MockitoAnnotations;
42 import org.robolectric.RobolectricTestRunner;
43 import org.robolectric.RuntimeEnvironment;
44 
45 import java.util.concurrent.TimeUnit;
46 
47 @RunWith(RobolectricTestRunner.class)
48 public class BatteryOptimizeUtilsTest {
49 
50     private static final int UID = 12345;
51     private static final String PACKAGE_NAME = "com.android.app";
52 
53     @Mock BatteryUtils mMockBatteryUtils;
54     @Mock AppOpsManager mMockAppOpsManager;
55     @Mock PowerAllowlistBackend mMockBackend;
56 
57     private Context mContext;
58     private BatteryOptimizeUtils mBatteryOptimizeUtils;
59 
60     @Before
setUp()61     public void setUp() {
62         MockitoAnnotations.initMocks(this);
63         mContext = spy(RuntimeEnvironment.application);
64         mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
65         mBatteryOptimizeUtils.mAppOpsManager = mMockAppOpsManager;
66         mBatteryOptimizeUtils.mBatteryUtils = mMockBatteryUtils;
67         mBatteryOptimizeUtils.mPowerAllowListBackend = mMockBackend;
68         // Sets the default mode as MODE_RESTRICTED.
69         mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_IGNORED;
70         mBatteryOptimizeUtils.mAllowListed = false;
71     }
72 
73     @Test
testGetAppOptimizationMode_returnRestricted()74     public void testGetAppOptimizationMode_returnRestricted() {
75         when(mMockBackend.isAllowlisted(anyString())).thenReturn(false);
76         when(mMockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
77                 .thenReturn(AppOpsManager.MODE_IGNORED);
78 
79         assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
80                 .isEqualTo(MODE_RESTRICTED);
81     }
82 
83     @Test
testGetAppOptimizationMode_returnUnrestricted()84     public void testGetAppOptimizationMode_returnUnrestricted() {
85         when(mMockBackend.isAllowlisted(anyString())).thenReturn(true);
86         when(mMockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
87                 .thenReturn(AppOpsManager.MODE_ALLOWED);
88 
89         assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
90                 .isEqualTo(MODE_UNRESTRICTED);
91     }
92 
93     @Test
testGetAppOptimizationMode_returnOptimized()94     public void testGetAppOptimizationMode_returnOptimized() {
95         when(mMockBackend.isAllowlisted(anyString())).thenReturn(false);
96         when(mMockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
97                 .thenReturn(AppOpsManager.MODE_ALLOWED);
98 
99         assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
100                 .isEqualTo(MODE_OPTIMIZED);
101     }
102 
103     @Test
testIsSystemOrDefaultApp_isSystemOrDefaultApp_returnTrue()104     public void testIsSystemOrDefaultApp_isSystemOrDefaultApp_returnTrue() {
105         when(mMockBackend.isAllowlisted(anyString())).thenReturn(true);
106         when(mMockBackend.isDefaultActiveApp(anyString())).thenReturn(true);
107 
108         assertThat(mBatteryOptimizeUtils.isSystemOrDefaultApp()).isTrue();
109     }
110 
111     @Test
testIsSystemOrDefaultApp_notSystemOrDefaultApp_returnFalse()112     public void testIsSystemOrDefaultApp_notSystemOrDefaultApp_returnFalse() {
113         assertThat(mBatteryOptimizeUtils.isSystemOrDefaultApp()).isFalse();
114     }
115 
116     @Test
testIsValidPackageName_InvalidPackageName_returnFalse()117     public void testIsValidPackageName_InvalidPackageName_returnFalse() {
118         final BatteryOptimizeUtils testBatteryOptimizeUtils =
119                 new BatteryOptimizeUtils(mContext, UID, null);
120 
121         assertThat(testBatteryOptimizeUtils.isValidPackageName()).isFalse();
122     }
123 
124     @Test
testIsValidPackageName_validPackageName_returnTrue()125     public void testIsValidPackageName_validPackageName_returnTrue() {
126         assertThat(mBatteryOptimizeUtils.isValidPackageName()).isTrue();
127     }
128 
129     @Test
testSetAppUsageState_Restricted_verifyAction()130     public void testSetAppUsageState_Restricted_verifyAction() throws Exception {
131         // Sets the current mode as MODE_UNRESTRICTED.
132         mBatteryOptimizeUtils.mAllowListed = false;
133         mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_ALLOWED;
134 
135         mBatteryOptimizeUtils.setAppUsageState(MODE_RESTRICTED);
136         TimeUnit.SECONDS.sleep(1);
137 
138         verify(mMockBatteryUtils).setForceAppStandby(UID,
139                 PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
140         verify(mMockBackend).removeApp(PACKAGE_NAME);
141     }
142 
143     @Test
testSetAppUsageState_Unrestricted_verifyAction()144     public void testSetAppUsageState_Unrestricted_verifyAction() throws Exception {
145         mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
146         TimeUnit.SECONDS.sleep(1);
147 
148         verify(mMockBatteryUtils).setForceAppStandby(UID,
149                 PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
150         verify(mMockBackend).addApp(PACKAGE_NAME);
151     }
152 
153     @Test
testSetAppUsageState_Optimized_verifyAction()154     public void testSetAppUsageState_Optimized_verifyAction() throws Exception {
155         mBatteryOptimizeUtils.setAppUsageState(MODE_OPTIMIZED);
156         TimeUnit.SECONDS.sleep(1);
157 
158         verify(mMockBatteryUtils).setForceAppStandby(UID,
159                 PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
160         verify(mMockBackend).removeApp(PACKAGE_NAME);
161     }
162 
163     @Test
testSetAppUsageState_sameUnrestrictedMode_verifyNoAction()164     public void testSetAppUsageState_sameUnrestrictedMode_verifyNoAction() throws Exception {
165         // Sets the current mode as MODE_UNRESTRICTED.
166         mBatteryOptimizeUtils.mAllowListed = true;
167         mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_ALLOWED;
168 
169         mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
170         TimeUnit.SECONDS.sleep(1);
171 
172         verifyZeroInteractions(mMockBackend);
173         verifyZeroInteractions(mMockBatteryUtils);
174     }
175 }
176