1 /* 2 * Copyright (C) 2014 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.deviceowner; 17 18 import android.app.Activity; 19 import android.app.ActivityManager; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.provider.Settings; 25 import android.os.Bundle; 26 27 // This is not a standard test of an android activity (such as 28 // ActivityInstrumentationTestCase2) as it is attempting to test the actual 29 // life cycle and how it is affected by lock task, rather than mock intents 30 // and setup. 31 public class LockTaskTest extends BaseDeviceOwnerTest { 32 33 private static final String TEST_PACKAGE = "com.google.android.example.somepackage"; 34 35 private static final int ACTIVITY_RESUMED_TIMEOUT_MILLIS = 20000; // 20 seconds 36 private static final int ACTIVITY_RUNNING_TIMEOUT_MILLIS = 10000; // 10 seconds 37 private static final int ACTIVITY_DESTROYED_TIMEOUT_MILLIS = 60000; // 60 seconds 38 39 public static final String RECEIVING_ACTIVITY_CREATED_ACTION 40 = "com.android.cts.deviceowner.RECEIVER_ACTIVITY_STARTED_ACTION"; 41 /** 42 * The tests below need to keep detailed track of the state of the activity 43 * that is started and stopped frequently. To do this it sends a number of 44 * broadcasts that are caught here and translated into booleans (as well as 45 * notify some locks in case we are waiting). There is also an action used 46 * to specify that the activity has finished handling the current command 47 * (INTENT_ACTION). 48 */ 49 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 50 @Override 51 public void onReceive(Context context, Intent intent) { 52 String action = intent.getAction(); 53 if (LockTaskUtilityActivity.CREATE_ACTION.equals(action)) { 54 synchronized (mActivityRunningLock) { 55 mIsActivityRunning = true; 56 mActivityRunningLock.notify(); 57 } 58 } else if (LockTaskUtilityActivity.DESTROY_ACTION.equals(action)) { 59 synchronized (mActivityRunningLock) { 60 mIsActivityRunning = false; 61 mActivityRunningLock.notify(); 62 } 63 } else if (LockTaskUtilityActivity.RESUME_ACTION.equals(action)) { 64 synchronized (mActivityResumedLock) { 65 mIsActivityResumed = true; 66 mActivityResumedLock.notify(); 67 } 68 } else if (LockTaskUtilityActivity.PAUSE_ACTION.equals(action)) { 69 synchronized (mActivityResumedLock) { 70 mIsActivityResumed = false; 71 mActivityResumedLock.notify(); 72 } 73 } else if (LockTaskUtilityActivity.INTENT_ACTION.equals(action)) { 74 // Notify that intent has been handled. 75 synchronized (LockTaskTest.this) { 76 mIntentHandled = true; 77 LockTaskTest.this.notify(); 78 } 79 } else if (RECEIVING_ACTIVITY_CREATED_ACTION.equals(action)) { 80 synchronized(mReceivingActivityCreatedLock) { 81 mReceivingActivityWasCreated = true; 82 mReceivingActivityCreatedLock.notify(); 83 } 84 } 85 } 86 }; 87 88 public static class IntentReceivingActivity extends Activity { 89 @Override 90 public void onCreate(Bundle savedInstanceState) { 91 super.onCreate(savedInstanceState); 92 sendBroadcast(new Intent(RECEIVING_ACTIVITY_CREATED_ACTION)); 93 finish(); 94 } 95 } 96 97 private boolean mIsActivityRunning; 98 private boolean mIsActivityResumed; 99 private boolean mReceivingActivityWasCreated; 100 private final Object mActivityRunningLock = new Object(); 101 private final Object mActivityResumedLock = new Object(); 102 private final Object mReceivingActivityCreatedLock = new Object(); 103 private Boolean mIntentHandled; 104 105 @Override 106 protected void setUp() throws Exception { 107 super.setUp(); 108 IntentFilter filter = new IntentFilter(); 109 filter.addAction(LockTaskUtilityActivity.CREATE_ACTION); 110 filter.addAction(LockTaskUtilityActivity.DESTROY_ACTION); 111 filter.addAction(LockTaskUtilityActivity.INTENT_ACTION); 112 filter.addAction(LockTaskUtilityActivity.RESUME_ACTION); 113 filter.addAction(LockTaskUtilityActivity.PAUSE_ACTION); 114 filter.addAction(RECEIVING_ACTIVITY_CREATED_ACTION); 115 mContext.registerReceiver(mReceiver, filter); 116 } 117 118 @Override 119 protected void tearDown() throws Exception { 120 mContext.unregisterReceiver(mReceiver); 121 super.tearDown(); 122 } 123 124 public void testSetLockTaskPackages() { 125 mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { TEST_PACKAGE }); 126 assertTrue(mDevicePolicyManager.isLockTaskPermitted(TEST_PACKAGE)); 127 128 mDevicePolicyManager.setLockTaskPackages(getWho(), new String[0]); 129 assertFalse(mDevicePolicyManager.isLockTaskPermitted(TEST_PACKAGE)); 130 } 131 132 // Start lock task, verify that ActivityManager knows thats what is going on. 133 public void testStartLockTask() { 134 mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME }); 135 startLockTask(); 136 waitForResume(); 137 138 // Verify that activity open and activity manager is in lock task. 139 ActivityManager activityManager = (ActivityManager) 140 mContext.getSystemService(Context.ACTIVITY_SERVICE); 141 assertTrue(activityManager.isInLockTaskMode()); 142 assertTrue(mIsActivityRunning); 143 assertTrue(mIsActivityResumed); 144 145 stopAndFinish(activityManager); 146 } 147 148 // Verifies that the act of finishing is blocked by ActivityManager in lock task. 149 // This results in onDestroy not being called until stopLockTask is called before finish. 150 public void testCannotFinish() { 151 mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME }); 152 startLockTask(); 153 154 // If lock task has not exited then the activity shouldn't actually receive onDestroy. 155 finishAndWait(); 156 ActivityManager activityManager = (ActivityManager) 157 mContext.getSystemService(Context.ACTIVITY_SERVICE); 158 assertTrue(activityManager.isInLockTaskMode()); 159 assertTrue(mIsActivityRunning); 160 161 stopAndFinish(activityManager); 162 } 163 164 // This launches an activity that is in the current task. 165 // this should be permitted as a part of lock task (since it isn't a new task). 166 public void testStartActivityWithinTask() { 167 mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME }); 168 startLockTask(); 169 waitForResume(); 170 171 mReceivingActivityWasCreated = false; 172 Intent launchIntent = new Intent(mContext, IntentReceivingActivity.class); 173 Intent lockTaskUtility = getLockTaskUtility(); 174 lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent); 175 mContext.startActivity(lockTaskUtility); 176 177 synchronized (mReceivingActivityCreatedLock) { 178 try { 179 mReceivingActivityCreatedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS); 180 } catch (InterruptedException e) { 181 } 182 assertTrue(mReceivingActivityWasCreated); 183 } 184 stopAndFinish(null); 185 } 186 187 // This launches an activity that is not part of the current task and therefore 188 // should be blocked. 189 public void testCannotStartActivityOutsideTask() { 190 mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME }); 191 startLockTask(); 192 waitForResume(); 193 194 mReceivingActivityWasCreated = false; 195 Intent launchIntent = new Intent(mContext, IntentReceivingActivity.class); 196 launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 197 mContext.startActivity(launchIntent); 198 synchronized (mReceivingActivityCreatedLock) { 199 try { 200 mReceivingActivityCreatedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS); 201 } catch (InterruptedException e) { 202 } 203 assertFalse(mReceivingActivityWasCreated); 204 } 205 stopAndFinish(null); 206 } 207 208 /** 209 * Call stopLockTask and finish on the LockTaskUtilityActivity. 210 * 211 * Verify that the activity is no longer running. 212 * 213 * If activityManager is not null then verify that the ActivityManager 214 * is no longer in lock task mode. 215 */ 216 private void stopAndFinish(ActivityManager activityManager) { 217 stopLockTask(); 218 finishAndWait(); 219 if (activityManager != null) { 220 assertFalse(activityManager.isInLockTaskMode()); 221 } 222 assertFalse(mIsActivityRunning); 223 } 224 225 /** 226 * Call finish on the LockTaskUtilityActivity and wait for 227 * onDestroy to be called. 228 */ 229 private void finishAndWait() { 230 synchronized (mActivityRunningLock) { 231 finish(); 232 if (mIsActivityRunning) { 233 try { 234 mActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS); 235 } catch (InterruptedException e) { 236 } 237 } 238 } 239 } 240 241 /** 242 * Wait for onResume to be called on the LockTaskUtilityActivity. 243 */ 244 private void waitForResume() { 245 // It may take a moment for the resume to come in. 246 synchronized (mActivityResumedLock) { 247 if (!mIsActivityResumed) { 248 try { 249 mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS); 250 } catch (InterruptedException e) { 251 } 252 } 253 } 254 } 255 256 /** 257 * Calls startLockTask on the LockTaskUtilityActivity 258 */ 259 private void startLockTask() { 260 Intent intent = getLockTaskUtility(); 261 intent.putExtra(LockTaskUtilityActivity.START_LOCK_TASK, true); 262 startAndWait(intent); 263 } 264 265 /** 266 * Calls stopLockTask on the LockTaskUtilityActivity 267 */ 268 private void stopLockTask() { 269 Intent intent = getLockTaskUtility(); 270 intent.putExtra(LockTaskUtilityActivity.STOP_LOCK_TASK, true); 271 startAndWait(intent); 272 } 273 274 /** 275 * Calls finish on the LockTaskUtilityActivity 276 */ 277 private void finish() { 278 Intent intent = getLockTaskUtility(); 279 intent.putExtra(LockTaskUtilityActivity.FINISH, true); 280 startAndWait(intent); 281 } 282 283 /** 284 * Sends a command intent to the LockTaskUtilityActivity and waits 285 * to receive the broadcast back confirming it has finished processing 286 * the command. 287 */ 288 private void startAndWait(Intent intent) { 289 mIntentHandled = false; 290 synchronized (this) { 291 mContext.startActivity(intent); 292 // Give 20 secs to finish. 293 try { 294 wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS); 295 } catch (InterruptedException e) { 296 } 297 assertTrue(mIntentHandled); 298 } 299 } 300 301 /** 302 * Get basic intent that points at the LockTaskUtilityActivity. 303 * 304 * This intent includes the flags to make it act as single top. 305 */ 306 private Intent getLockTaskUtility() { 307 Intent intent = new Intent(); 308 intent.setClassName(PACKAGE_NAME, LockTaskUtilityActivity.class.getName()); 309 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 310 return intent; 311 } 312 } 313