1 /* 2 * Copyright (C) 2017 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 package com.android.cts.deviceandprofileowner; 17 18 import android.app.ActivityManager; 19 import android.app.ActivityOptions; 20 import android.app.admin.DevicePolicyManager; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.os.Build; 28 import android.os.Bundle; 29 import android.os.SystemClock; 30 import android.support.test.uiautomator.By; 31 import android.support.test.uiautomator.UiDevice; 32 import android.support.test.uiautomator.Until; 33 import android.telecom.TelecomManager; 34 import android.util.Log; 35 36 import androidx.test.InstrumentationRegistry; 37 import androidx.test.runner.AndroidJUnit4; 38 39 /** 40 * Test class that is meant to be driven from the host and can't be run alone, which is required 41 * for tests that include rebooting or other connection-breaking steps. For this reason, this class 42 * does not override tearDown and setUp just initializes the test state, changing nothing in the 43 * device. Therefore, the host is responsible for making sure the tests leave the device in a clean 44 * state after running. 45 */ 46 public class LockTaskHostDrivenTest extends BaseDeviceAdminTest { 47 48 private static final String TAG = LockTaskHostDrivenTest.class.getName(); 49 private static final int ACTIVITY_RESUMED_TIMEOUT_MILLIS = 20000; // 20 seconds 50 private static final int LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS = 10000; // 10 seconds 51 private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL"; 52 private static final String LOCK_TASK_ACTIVITY 53 = LockTaskUtilityActivityIfWhitelisted.class.getName(); 54 55 private UiDevice mUiDevice; 56 private Context mContext; 57 private PackageManager mPackageManager; 58 private ActivityManager mActivityManager; 59 private TelecomManager mTelcomManager; 60 private DevicePolicyManager mDevicePolicyManager; 61 setUp()62 public void setUp() { 63 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 64 mContext = InstrumentationRegistry.getContext(); 65 mPackageManager = mContext.getPackageManager(); 66 mActivityManager = mContext.getSystemService(ActivityManager.class); 67 mTelcomManager = mContext.getSystemService(TelecomManager.class); 68 mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); 69 } 70 startLockTask()71 public void startLockTask() throws Exception { 72 Log.d(TAG, "startLockTask on host-driven test (no cleanup)"); 73 setLockTaskPackages(mContext.getPackageName()); 74 setDefaultHomeIntentReceiver(); 75 launchLockTaskActivity(); 76 mUiDevice.waitForIdle(); 77 } 78 cleanupLockTask()79 public void cleanupLockTask() { 80 Log.d(TAG, "cleanupLockTask on host-driven test"); 81 mDevicePolicyManager.clearPackagePersistentPreferredActivities( 82 ADMIN_RECEIVER_COMPONENT, 83 mContext.getPackageName()); 84 setLockTaskPackages(); 85 mDevicePolicyManager.setLockTaskFeatures(ADMIN_RECEIVER_COMPONENT, 0); 86 // In case some activity is still in foreground 87 mUiDevice.pressHome(); 88 } 89 90 /** 91 * On low-RAM devices, this test can take too long to finish, so the test runner can incorrectly 92 * assume it's finished. Therefore, only use it once in a given test. 93 * 94 * <p>Does not test that the locked activity is initially in the foreground, since running this 95 * test in instrumentation can immediately kill the locked activity (while maintaining lock task 96 * mode). 97 */ testLockTaskIsActiveAndCantBeInterrupted()98 public void testLockTaskIsActiveAndCantBeInterrupted() throws Exception { 99 Log.d(TAG, "testLockTaskIsActiveAndCantBeInterrupted on host-driven test"); 100 waitAndEnsureLockTaskUtilityActivityIsRunning(); 101 checkLockedActivityIsRunning(); 102 103 mUiDevice.pressHome(); 104 mUiDevice.waitForIdle(); 105 checkLockedActivityIsRunning(); 106 107 mUiDevice.pressRecentApps(); 108 mUiDevice.waitForIdle(); 109 checkLockedActivityIsRunning(); 110 111 mUiDevice.pressBack(); 112 mUiDevice.waitForIdle(); 113 checkLockedActivityIsRunning(); 114 115 mUiDevice.waitForIdle(); 116 } 117 118 /** 119 * Poll for {@link ActivityManager#getLockTaskModeState()} to equal 120 * {@link ActivityManager#LOCK_TASK_MODE_NONE} 121 * 122 * <p>This will check every 500 milliseconds for a maximum of 123 * {@link #LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS} milliseconds. 124 */ waitForLockTaskModeStateNone()125 private void waitForLockTaskModeStateNone() { 126 long delayed = 0; 127 long delay = 500; 128 while (delayed <= LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS) { 129 if (mActivityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE) { 130 break; 131 } 132 SystemClock.sleep(delay); 133 delayed += delay; 134 } 135 } 136 testLockTaskIsExitedIfNotWhitelisted()137 public void testLockTaskIsExitedIfNotWhitelisted() throws Exception { 138 Log.d(TAG, "testLockTaskIsExitedIfNotWhitelisted on host-driven test"); 139 140 // Whitelist this package 141 setLockTaskPackages(mContext.getPackageName()); 142 143 // Launch lock task root activity 144 setDefaultHomeIntentReceiver(); 145 launchLockTaskActivity(); 146 waitAndCheckLockedActivityIsResumed(); 147 assertEquals( 148 ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState()); 149 150 // Remove it from whitelist 151 setLockTaskPackages(); 152 waitForLockTaskModeStateNone(); 153 mUiDevice.waitForIdle(); 154 155 // The activity should be finished and exit lock task mode 156 waitAndCheckLockedActivityIsPaused(); 157 assertEquals(ActivityManager.LOCK_TASK_MODE_NONE, mActivityManager.getLockTaskModeState()); 158 } 159 testLockTaskCanLaunchDefaultDialer()160 public void testLockTaskCanLaunchDefaultDialer() throws Exception { 161 if (!hasTelephonyFeature()) { 162 Log.d(TAG, "testLockTaskCanLaunchDefaultDialer skipped"); 163 return; 164 } 165 166 Log.d(TAG, "testLockTaskCanLaunchDefaultDialer on host-driven test"); 167 168 // Whitelist dialer package 169 String dialerPackage = mTelcomManager.getSystemDialerPackage(); 170 assertNotNull(dialerPackage); 171 setLockTaskPackages(mContext.getPackageName(), dialerPackage); 172 173 // Launch lock task root activity 174 setDefaultHomeIntentReceiver(); 175 launchLockTaskActivity(); 176 waitAndCheckLockedActivityIsResumed(); 177 assertEquals( 178 ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState()); 179 180 // Launch dialer 181 launchDialerIntoLockTaskMode(dialerPackage); 182 183 // Wait until dialer package starts 184 mUiDevice.wait( 185 Until.hasObject(By.pkg(dialerPackage).depth(0)), 186 ACTIVITY_RESUMED_TIMEOUT_MILLIS); 187 mUiDevice.waitForIdle(); 188 waitAndCheckLockedActivityIsPaused(); 189 190 // But still in LockTask mode 191 assertEquals( 192 ActivityManager.LOCK_TASK_MODE_LOCKED, 193 mActivityManager.getLockTaskModeState()); 194 } 195 testLockTaskCanLaunchEmergencyDialer()196 public void testLockTaskCanLaunchEmergencyDialer() throws Exception { 197 if (!hasTelephonyFeature()) { 198 Log.d(TAG, "testLockTaskCanLaunchEmergencyDialer skipped"); 199 return; 200 } 201 202 // Find dialer package 203 String dialerPackage = getEmergencyDialerPackageName(); 204 if (dialerPackage == null || dialerPackage.isEmpty()) { 205 Log.d(TAG, "testLockTaskCanLaunchEmergencyDialer skipped since no emergency dialer"); 206 return; 207 } 208 209 Log.d(TAG, "testLockTaskCanLaunchEmergencyDialer on host-driven test"); 210 211 // Emergency dialer should be usable as long as keyguard feature is enabled 212 // regardless of the package whitelist 213 mDevicePolicyManager.setLockTaskFeatures( 214 ADMIN_RECEIVER_COMPONENT, DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD); 215 setLockTaskPackages(mContext.getPackageName()); 216 217 // Launch lock task root activity 218 setDefaultHomeIntentReceiver(); 219 launchLockTaskActivity(); 220 waitAndCheckLockedActivityIsResumed(); 221 assertEquals( 222 ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState()); 223 224 // Launch dialer 225 launchEmergencyDialer(); 226 227 // Wait until dialer package starts 228 mUiDevice.wait( 229 Until.hasObject(By.pkg(dialerPackage).depth(0)), 230 ACTIVITY_RESUMED_TIMEOUT_MILLIS); 231 mUiDevice.waitForIdle(); 232 waitAndCheckLockedActivityIsPaused(); 233 234 // But still in LockTask mode 235 assertEquals( 236 ActivityManager.LOCK_TASK_MODE_LOCKED, 237 mActivityManager.getLockTaskModeState()); 238 } 239 hasTelephonyFeature()240 private boolean hasTelephonyFeature() { 241 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && 242 mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 243 } 244 checkLockedActivityIsRunning()245 private void checkLockedActivityIsRunning() { 246 String activityName = 247 mActivityManager.getAppTasks().get(0).getTaskInfo().topActivity.getClassName(); 248 assertEquals(LOCK_TASK_ACTIVITY, activityName); 249 assertEquals( 250 ActivityManager.LOCK_TASK_MODE_LOCKED, mActivityManager.getLockTaskModeState()); 251 } 252 253 /** 254 * Ensures the locked activity is resumed or otherwise launches it but without starting lock 255 * task if it is not already in that mode. 256 */ waitAndEnsureLockTaskUtilityActivityIsRunning()257 private void waitAndEnsureLockTaskUtilityActivityIsRunning() throws Exception { 258 mUiDevice.waitForIdle(); 259 final boolean lockedActivityIsResumed = 260 LockTaskUtilityActivity.waitUntilActivityResumed(ACTIVITY_RESUMED_TIMEOUT_MILLIS); 261 if (!lockedActivityIsResumed) { 262 launchLockTaskUtilityActivityWithoutStartingLockTask(); 263 } 264 } 265 waitAndCheckLockedActivityIsResumed()266 private void waitAndCheckLockedActivityIsResumed() throws Exception { 267 mUiDevice.waitForIdle(); 268 assertTrue( 269 LockTaskUtilityActivity.waitUntilActivityResumed(ACTIVITY_RESUMED_TIMEOUT_MILLIS)); 270 } 271 waitAndCheckLockedActivityIsPaused()272 private void waitAndCheckLockedActivityIsPaused() throws Exception { 273 mUiDevice.waitForIdle(); 274 assertTrue( 275 LockTaskUtilityActivity.waitUntilActivityPaused(ACTIVITY_RESUMED_TIMEOUT_MILLIS)); 276 } 277 launchDialerIntoLockTaskMode(String dialerPackage)278 private void launchDialerIntoLockTaskMode(String dialerPackage) { 279 Intent intent = new Intent(Intent.ACTION_DIAL) 280 .setPackage(dialerPackage) 281 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 282 Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle(); 283 mContext.startActivity(intent, options); 284 } 285 launchEmergencyDialer()286 private void launchEmergencyDialer() { 287 Intent intent = new Intent(ACTION_EMERGENCY_DIAL).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 288 mContext.startActivity(intent); 289 } 290 getEmergencyDialerPackageName()291 private String getEmergencyDialerPackageName() { 292 Intent intent = new Intent(ACTION_EMERGENCY_DIAL).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 293 ResolveInfo dialerInfo = 294 mPackageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 295 return (dialerInfo != null) ? dialerInfo.activityInfo.packageName : null; 296 } 297 launchLockTaskActivity()298 private void launchLockTaskActivity() { 299 Intent intent = new Intent(mContext, LockTaskUtilityActivityIfWhitelisted.class); 300 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 301 intent.putExtra(LockTaskUtilityActivity.START_LOCK_TASK, true); 302 mContext.startActivity(intent); 303 } 304 launchLockTaskUtilityActivityWithoutStartingLockTask()305 private void launchLockTaskUtilityActivityWithoutStartingLockTask() { 306 final Intent intent = new Intent(mContext, LockTaskUtilityActivityIfWhitelisted.class); 307 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 308 mContext.startActivity(intent); 309 } 310 setLockTaskPackages(String... packages)311 private void setLockTaskPackages(String... packages) { 312 mDevicePolicyManager.setLockTaskPackages(ADMIN_RECEIVER_COMPONENT, packages); 313 } 314 setDefaultHomeIntentReceiver()315 private void setDefaultHomeIntentReceiver() { 316 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN); 317 intentFilter.addCategory(Intent.CATEGORY_HOME); 318 intentFilter.addCategory(Intent.CATEGORY_DEFAULT); 319 mDevicePolicyManager.addPersistentPreferredActivity( 320 ADMIN_RECEIVER_COMPONENT, intentFilter, 321 new ComponentName(mContext.getPackageName(), LOCK_TASK_ACTIVITY)); 322 } 323 } 324