1 /* 2 * Copyright (C) 2015 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.usage.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotEquals; 22 import static org.junit.Assume.assumeTrue; 23 24 import com.android.tradefed.device.DeviceNotAvailableException; 25 import com.android.tradefed.device.ITestDevice; 26 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 27 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 28 29 import org.junit.Before; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 33 @RunWith(DeviceJUnit4ClassRunner.class) 34 public class AppIdleHostTest extends BaseHostJUnit4Test { 35 private static final String SETTINGS_APP_IDLE_CONSTANTS = "app_idle_constants"; 36 37 private static final String TEST_APP_PACKAGE = "android.app.usage.app"; 38 private static final String TEST_APP_CLASS = "TestActivity"; 39 private static final String TEST_APP_PACKAGE2 = "android.app.usage.apptoo"; 40 41 private static final long ACTIVITY_LAUNCH_WAIT_MILLIS = 500; 42 43 private static final int SB_ACTIVE = 10; 44 private static final int SB_WORKING_SET = 20; 45 private static final int SB_FREQUENT = 30; 46 47 /** 48 * A reference to the device under test. 49 */ 50 private ITestDevice mDevice; 51 52 @Before setUp()53 public void setUp() { 54 // Get the device, this gives a handle to run commands and install APKs. 55 mDevice = getDevice(); 56 } 57 58 /** 59 * Checks whether an package is idle. 60 * @param appPackage The package to check for idleness. 61 * @return true if the package is idle 62 * @throws DeviceNotAvailableException 63 */ isAppIdle(String appPackage)64 private boolean isAppIdle(String appPackage) throws DeviceNotAvailableException { 65 String result = mDevice.executeShellCommand(String.format("am get-inactive %s", appPackage)); 66 return result.contains("Idle=true"); 67 } 68 69 /** 70 * Set the app idle settings. 71 * @param settingsStr The settings string, a comma separated key=value list. 72 * @throws DeviceNotAvailableException 73 */ setAppIdleSettings(String settingsStr)74 private void setAppIdleSettings(String settingsStr) throws DeviceNotAvailableException { 75 mDevice.executeShellCommand(String.format("settings put global %s \"%s\"", 76 SETTINGS_APP_IDLE_CONSTANTS, settingsStr)); 77 } 78 79 /** 80 * Get the current app idle settings. 81 * @throws DeviceNotAvailableException 82 */ getAppIdleSettings()83 private String getAppIdleSettings() throws DeviceNotAvailableException { 84 String result = mDevice.executeShellCommand(String.format("settings get global %s", 85 SETTINGS_APP_IDLE_CONSTANTS)); 86 return result.trim(); 87 } 88 89 /** 90 * Launch the test app for a few hundred milliseconds then launch home. 91 * @throws DeviceNotAvailableException 92 */ startAndStopTestApp()93 private void startAndStopTestApp() throws DeviceNotAvailableException { 94 // Launch the app. 95 mDevice.executeShellCommand( 96 String.format("am start -W -a android.intent.action.MAIN -n %s/%s.%s", 97 TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_APP_CLASS)); 98 99 // Wait for some time. 100 sleepUninterrupted(ACTIVITY_LAUNCH_WAIT_MILLIS); 101 102 // Launch home. 103 mDevice.executeShellCommand( 104 "am start -W -a android.intent.action.MAIN -c android.intent.category.HOME"); 105 } 106 107 /** 108 * Tests that the app is not idle right after it is launched. 109 */ 110 @Test testAppIsNotIdleAfterBeingLaunched()111 public void testAppIsNotIdleAfterBeingLaunched() throws Exception { 112 final String previousState = getAppIdleSettings(); 113 try { 114 // Set the app idle time to something large. 115 setAppIdleSettings("idle_duration=10000,wallclock_threshold=10000"); 116 startAndStopTestApp(); 117 assertFalse(isAppIdle(TEST_APP_PACKAGE)); 118 } finally { 119 setAppIdleSettings(previousState); 120 } 121 } 122 setAppStandbyBucket(String packageName, int bucket)123 private void setAppStandbyBucket(String packageName, int bucket) throws Exception { 124 mDevice.executeShellCommand( 125 String.format("am set-standby-bucket %s %s", packageName, bucket)); 126 } 127 isAppStandbyEnabled()128 private boolean isAppStandbyEnabled() throws DeviceNotAvailableException { 129 final String result = mDevice.executeShellCommand( 130 "dumpsys usagestats is-app-standby-enabled").trim(); 131 return Boolean.parseBoolean(result); 132 } 133 getAppStandbyBucket(String packageName)134 private int getAppStandbyBucket(String packageName) throws Exception { 135 String bucketString = mDevice.executeShellCommand( 136 String.format("am get-standby-bucket %s", packageName)); 137 try { 138 return Integer.parseInt(bucketString.trim()); 139 } catch (NumberFormatException nfe) { 140 } 141 return -1; 142 } 143 144 @Test testSetAppStandbyBucket()145 public void testSetAppStandbyBucket() throws Exception { 146 assumeTrue("App standby not enabled on device", isAppStandbyEnabled()); 147 // Set to ACTIVE 148 setAppStandbyBucket(TEST_APP_PACKAGE, SB_ACTIVE); 149 assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE)); 150 // set to WORKING_SET 151 setAppStandbyBucket(TEST_APP_PACKAGE, 20); 152 assertEquals(20, getAppStandbyBucket(TEST_APP_PACKAGE)); 153 } 154 155 @Test testSetAppStandbyBuckets()156 public void testSetAppStandbyBuckets() throws Exception { 157 assumeTrue("App standby not enabled on device", isAppStandbyEnabled()); 158 // Set multiple packages states 159 String command = String.format("am set-standby-bucket %s %d %s %d", 160 TEST_APP_PACKAGE, SB_FREQUENT, TEST_APP_PACKAGE2, SB_WORKING_SET); 161 mDevice.executeShellCommand(command); 162 assertEquals(SB_FREQUENT, getAppStandbyBucket(TEST_APP_PACKAGE)); 163 assertEquals(SB_WORKING_SET, getAppStandbyBucket(TEST_APP_PACKAGE2)); 164 } 165 166 @Test testCantSetOwnStandbyBucket()167 public void testCantSetOwnStandbyBucket() throws Exception { 168 assumeTrue("App standby not enabled on device", isAppStandbyEnabled()); 169 setAppStandbyBucket("com.android.shell", 40); 170 assertNotEquals(40, getAppStandbyBucket("com.android.shell")); 171 } 172 173 @Test testOutOfBoundsStandbyBucket()174 public void testOutOfBoundsStandbyBucket() throws Exception { 175 assumeTrue("App standby not enabled on device", isAppStandbyEnabled()); 176 setAppStandbyBucket(TEST_APP_PACKAGE, SB_ACTIVE); 177 assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE)); 178 // Try lower than min 179 setAppStandbyBucket(TEST_APP_PACKAGE, SB_ACTIVE - 1); 180 assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE)); 181 // Try higher than max 182 setAppStandbyBucket(TEST_APP_PACKAGE, 50 + 1); 183 assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE)); 184 } 185 sleepUninterrupted(long timeMillis)186 private static void sleepUninterrupted(long timeMillis) { 187 boolean interrupted; 188 do { 189 try { 190 Thread.sleep(timeMillis); 191 interrupted = false; 192 } catch (InterruptedException e) { 193 interrupted = true; 194 } 195 } while (interrupted); 196 } 197 } 198