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.deviceandprofileowner;
17 
18 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
19 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
20 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
21 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
22 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
23 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
24 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
25 
26 import static org.junit.Assert.assertArrayEquals;
27 import static org.testng.Assert.assertThrows;
28 
29 import android.app.ActivityManager;
30 import android.app.ActivityOptions;
31 import android.app.admin.DevicePolicyManager;
32 import android.content.BroadcastReceiver;
33 import android.content.ComponentName;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.os.Bundle;
38 import android.util.Log;
39 
40 import androidx.test.InstrumentationRegistry;
41 import androidx.test.runner.AndroidJUnit4;
42 
43 import java.util.concurrent.TimeUnit;
44 
45 public class LockTaskTest extends BaseDeviceAdminTest {
46 
47     private static final String TAG = "LockTaskTest";
48 
49     private static final String PACKAGE_NAME = LockTaskTest.class.getPackage().getName();
50     private static final ComponentName ADMIN_COMPONENT = ADMIN_RECEIVER_COMPONENT;
51     private static final String TEST_PACKAGE = "com.google.android.example.somepackage";
52 
53     private static final String UTILITY_ACTIVITY
54             = "com.android.cts.deviceandprofileowner.LockTaskUtilityActivity";
55     private static final String UTILITY_ACTIVITY_IF_WHITELISTED
56             = "com.android.cts.deviceandprofileowner.LockTaskUtilityActivityIfWhitelisted";
57 
58     private static final String RECEIVER_ACTIVITY_PACKAGE_NAME =
59             "com.android.cts.intent.receiver";
60     private static final String RECEIVER_ACTIVITY_NAME =
61             "com.android.cts.intent.receiver.IntentReceiverActivity";
62     private static final String ACTION_JUST_CREATE =
63             "com.android.cts.action.JUST_CREATE";
64     private static final String ACTION_CREATE_AND_WAIT =
65             "com.android.cts.action.CREATE_AND_WAIT";
66     private static final String RECEIVER_ACTIVITY_CREATED_ACTION =
67             "com.android.cts.deviceowner.action.RECEIVER_ACTIVITY_CREATED";
68     private static final String RECEIVER_ACTIVITY_DESTROYED_ACTION =
69             "com.android.cts.deviceowner.action.RECEIVER_ACTIVITY_DESTROYED";
70 
71     private static final long ACTIVITY_RESUMED_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
72     private static final long ACTIVITY_RUNNING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);
73     private static final long ACTIVITY_DESTROYED_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60);
74 
75     /**
76      * The tests below need to keep detailed track of the state of the activity
77      * that is started and stopped frequently.  To do this it sends a number of
78      * broadcasts that are caught here and translated into booleans (as well as
79      * notify some locks in case we are waiting).  There is also an action used
80      * to specify that the activity has finished handling the current command
81      * (INTENT_ACTION).
82      */
83     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
84         @Override
85         public void onReceive(Context context, Intent intent) {
86             String action = intent.getAction();
87             Log.d(TAG, "onReceive: " + action);
88             if (LockTaskUtilityActivity.CREATE_ACTION.equals(action)) {
89                 synchronized (mActivityRunningLock) {
90                     mIsActivityRunning = true;
91                     mActivityRunningLock.notify();
92                 }
93             } else if (LockTaskUtilityActivity.DESTROY_ACTION.equals(action)) {
94                 synchronized (mActivityRunningLock) {
95                     mIsActivityRunning = false;
96                     mActivityRunningLock.notify();
97                 }
98             } else if (LockTaskUtilityActivity.RESUME_ACTION.equals(action)) {
99                 synchronized (mActivityResumedLock) {
100                     mIsActivityResumed = true;
101                     mActivityResumedLock.notify();
102                 }
103             } else if (LockTaskUtilityActivity.PAUSE_ACTION.equals(action)) {
104                 synchronized (mActivityResumedLock) {
105                     mIsActivityResumed = false;
106                     mActivityResumedLock.notify();
107                 }
108             } else if (LockTaskUtilityActivity.INTENT_ACTION.equals(action)) {
109                 // Notify that intent has been handled.
110                 synchronized (LockTaskTest.this) {
111                     mIntentHandled = true;
112                     LockTaskTest.this.notify();
113                 }
114             } else if (RECEIVER_ACTIVITY_CREATED_ACTION.equals(action)) {
115                 synchronized(mReceiverActivityRunningLock) {
116                     mIsReceiverActivityRunning = true;
117                     mReceiverActivityRunningLock.notify();
118                 }
119             } else if (RECEIVER_ACTIVITY_DESTROYED_ACTION.equals(action)) {
120                 synchronized (mReceiverActivityRunningLock) {
121                     mIsReceiverActivityRunning = false;
122                     mReceiverActivityRunningLock.notify();
123                 }
124             }
125         }
126     };
127 
128     private volatile boolean mIsActivityRunning;
129     private volatile boolean mIsActivityResumed;
130     private volatile boolean mIsReceiverActivityRunning;
131     private volatile boolean mIntentHandled;
132     private final Object mActivityRunningLock = new Object();
133     private final Object mActivityResumedLock = new Object();
134     private final Object mReceiverActivityRunningLock = new Object();
135 
136     private Context mContext;
137     private ActivityManager mActivityManager;
138     private DevicePolicyManager mDevicePolicyManager;
139 
setUp()140     public void setUp() {
141         mContext = InstrumentationRegistry.getContext();
142 
143         mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
144         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
145         mActivityManager = mContext.getSystemService(ActivityManager.class);
146         IntentFilter filter = new IntentFilter();
147         filter.addAction(LockTaskUtilityActivity.CREATE_ACTION);
148         filter.addAction(LockTaskUtilityActivity.DESTROY_ACTION);
149         filter.addAction(LockTaskUtilityActivity.INTENT_ACTION);
150         filter.addAction(LockTaskUtilityActivity.RESUME_ACTION);
151         filter.addAction(LockTaskUtilityActivity.PAUSE_ACTION);
152         filter.addAction(RECEIVER_ACTIVITY_CREATED_ACTION);
153         filter.addAction(RECEIVER_ACTIVITY_DESTROYED_ACTION);
154         mContext.registerReceiver(mReceiver, filter);
155     }
156 
tearDown()157     public void tearDown() {
158         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
159         mContext.unregisterReceiver(mReceiver);
160     }
161 
162     // Setting and unsetting the lock task packages.
testSetLockTaskPackages()163     public void testSetLockTaskPackages() {
164         final String[] packages = new String[] { TEST_PACKAGE, "some.other.package" };
165         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, packages);
166         assertArrayEquals(packages, mDevicePolicyManager.getLockTaskPackages(ADMIN_COMPONENT));
167         assertTrue(mDevicePolicyManager.isLockTaskPermitted(TEST_PACKAGE));
168 
169         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
170         assertEquals(0, mDevicePolicyManager.getLockTaskPackages(ADMIN_COMPONENT).length);
171         assertFalse(mDevicePolicyManager.isLockTaskPermitted(TEST_PACKAGE));
172     }
173 
174     // Setting and unsetting the lock task features. The actual UI behavior is tested with CTS
175     // verifier.
testSetLockTaskFeatures()176     public void testSetLockTaskFeatures() {
177         final int[] flags = new int[] {
178                 LOCK_TASK_FEATURE_SYSTEM_INFO,
179                 LOCK_TASK_FEATURE_HOME,
180                 LOCK_TASK_FEATURE_NOTIFICATIONS,
181                 LOCK_TASK_FEATURE_OVERVIEW,
182                 LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
183                 LOCK_TASK_FEATURE_KEYGUARD
184         };
185 
186         int cumulative = LOCK_TASK_FEATURE_NONE;
187         for (int flag : flags) {
188             if (flag == LOCK_TASK_FEATURE_OVERVIEW || flag == LOCK_TASK_FEATURE_NOTIFICATIONS) {
189                 // Those flags can only be used in combination with HOME
190                 assertThrows(
191                         IllegalArgumentException.class,
192                         () -> mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, flag));
193             } else {
194                 mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, flag);
195                 assertEquals(flag, mDevicePolicyManager.getLockTaskFeatures(ADMIN_COMPONENT));
196             }
197 
198             cumulative |= flag;
199             mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, cumulative);
200             assertEquals(cumulative, mDevicePolicyManager.getLockTaskFeatures(ADMIN_COMPONENT));
201 
202             mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, LOCK_TASK_FEATURE_NONE);
203             assertEquals(LOCK_TASK_FEATURE_NONE,
204                     mDevicePolicyManager.getLockTaskFeatures(ADMIN_COMPONENT));
205         }
206     }
207 
208     // Start lock task, verify that ActivityManager knows thats what is going on.
testStartLockTask()209     public void testStartLockTask() throws Exception {
210         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
211         startLockTask(UTILITY_ACTIVITY);
212         waitForResume();
213 
214         // Verify that activity open and activity manager is in lock task.
215         assertLockTaskModeActive();
216         assertTrue(mIsActivityRunning);
217         assertTrue(mIsActivityResumed);
218 
219         stopAndFinish(UTILITY_ACTIVITY);
220     }
221 
222     // Verifies that the act of finishing is blocked by ActivityManager in lock task.
223     // This results in onDestroy not being called until stopLockTask is called before finish.
testCannotFinish()224     public void testCannotFinish() throws Exception {
225         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
226         startLockTask(UTILITY_ACTIVITY);
227 
228         // If lock task has not exited then the activity shouldn't actually receive onDestroy.
229         finishAndWait(UTILITY_ACTIVITY);
230         assertLockTaskModeActive();
231         assertTrue(mIsActivityRunning);
232 
233         stopAndFinish(UTILITY_ACTIVITY);
234     }
235 
236     // Verifies that updating the whitelisting during lock task mode finishes the locked task.
testUpdateWhitelisting()237     public void testUpdateWhitelisting() throws Exception {
238         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
239         startLockTask(UTILITY_ACTIVITY);
240 
241         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
242 
243         synchronized (mActivityRunningLock) {
244             mActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS);
245         }
246 
247         assertLockTaskModeInactive();
248         assertFalse(mIsActivityRunning);
249         assertFalse(mIsActivityResumed);
250     }
251 
252     // Verifies that removing the whitelist authorization immediately finishes the corresponding
253     // locked task. The other locked task(s) should remain locked.
testUpdateWhitelisting_twoTasks()254     public void testUpdateWhitelisting_twoTasks() throws Exception {
255         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME,
256                 RECEIVER_ACTIVITY_PACKAGE_NAME});
257 
258         // Start first locked task
259         startLockTask(UTILITY_ACTIVITY);
260         waitForResume();
261 
262         // Start the other task from the running activity
263         mIsReceiverActivityRunning = false;
264         Intent launchIntent = createReceiverActivityIntent(true /*newTask*/, true /*shouldWait*/);
265         mContext.startActivity(launchIntent);
266         synchronized (mReceiverActivityRunningLock) {
267             mReceiverActivityRunningLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
268             assertTrue(mIsReceiverActivityRunning);
269         }
270 
271         // Remove whitelist authorization of the second task
272         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
273         synchronized (mReceiverActivityRunningLock) {
274             mReceiverActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS);
275             assertFalse(mIsReceiverActivityRunning);
276         }
277 
278         assertLockTaskModeActive();
279         assertTrue(mIsActivityRunning);
280         assertTrue(mIsActivityResumed);
281 
282         stopAndFinish(UTILITY_ACTIVITY);
283     }
284 
285     // This launches an activity that is in the current task.
286     // This should always be permitted as a part of lock task (since it isn't a new task).
testStartActivity_withinTask()287     public void testStartActivity_withinTask() throws Exception {
288         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
289         startLockTask(UTILITY_ACTIVITY);
290         waitForResume();
291 
292         mIsReceiverActivityRunning = false;
293         Intent launchIntent = createReceiverActivityIntent(false /*newTask*/, false /*shouldWait*/);
294         Intent lockTaskUtility = getLockTaskUtility(UTILITY_ACTIVITY);
295         lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent);
296         mContext.startActivity(lockTaskUtility);
297 
298         synchronized (mReceiverActivityRunningLock) {
299             mReceiverActivityRunningLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
300             assertTrue(mIsReceiverActivityRunning);
301         }
302         stopAndFinish(UTILITY_ACTIVITY);
303     }
304 
305     // This launches a whitelisted activity that is not part of the current task.
306     // This should be permitted as a part of lock task.
testStartActivity_outsideTaskWhitelisted()307     public void testStartActivity_outsideTaskWhitelisted() throws Exception {
308         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME,
309                 RECEIVER_ACTIVITY_PACKAGE_NAME});
310         startLockTask(UTILITY_ACTIVITY);
311         waitForResume();
312 
313         mIsReceiverActivityRunning = false;
314         Intent launchIntent = createReceiverActivityIntent(true /*newTask*/, false /*shouldWait*/);
315         mContext.startActivity(launchIntent);
316         synchronized (mReceiverActivityRunningLock) {
317             mReceiverActivityRunningLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
318             assertTrue(mIsReceiverActivityRunning);
319         }
320         stopAndFinish(UTILITY_ACTIVITY);
321     }
322 
323     // This launches a non-whitelisted activity that is not part of the current task.
324     // This should be blocked.
testStartActivity_outsideTaskNonWhitelisted()325     public void testStartActivity_outsideTaskNonWhitelisted() throws Exception {
326         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
327         startLockTask(UTILITY_ACTIVITY);
328         waitForResume();
329 
330         Intent launchIntent = createReceiverActivityIntent(true /*newTask*/, false /*shouldWait*/);
331         mContext.startActivity(launchIntent);
332         synchronized (mActivityResumedLock) {
333             mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
334             assertFalse(mIsReceiverActivityRunning);
335         }
336         stopAndFinish(UTILITY_ACTIVITY);
337     }
338 
339     // Test the lockTaskMode flag for an activity declaring if_whitelisted.
340     // Whitelist the activity and verify that lock task mode is started.
testManifestArgument_whitelisted()341     public void testManifestArgument_whitelisted() throws Exception {
342         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
343         startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_WHITELISTED));
344         waitForResume();
345 
346         assertLockTaskModeActive();
347         assertTrue(mIsActivityRunning);
348         assertTrue(mIsActivityResumed);
349 
350         stopAndFinish(UTILITY_ACTIVITY_IF_WHITELISTED);
351     }
352 
353     // Test the lockTaskMode flag for an activity declaring if_whitelisted.
354     // Don't whitelist the activity and verify that lock task mode is not started.
testManifestArgument_nonWhitelisted()355     public void testManifestArgument_nonWhitelisted() throws Exception {
356         startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_WHITELISTED));
357         waitForResume();
358 
359         assertLockTaskModeInactive();
360         assertTrue(mIsActivityRunning);
361         assertTrue(mIsActivityResumed);
362 
363         stopAndFinish(UTILITY_ACTIVITY_IF_WHITELISTED);
364     }
365 
366     // Test the lockTaskMode flag for an activity declaring if_whitelisted.
367     // An activity locked via manifest argument cannot finish without calling stopLockTask.
testManifestArgument_cannotFinish()368     public void testManifestArgument_cannotFinish() throws Exception {
369         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
370         startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_WHITELISTED));
371         waitForResume();
372 
373         // If lock task has not exited then the activity shouldn't actually receive onDestroy.
374         finishAndWait(UTILITY_ACTIVITY_IF_WHITELISTED);
375         assertLockTaskModeActive();
376         assertTrue(mIsActivityRunning);
377 
378         stopAndFinish(UTILITY_ACTIVITY_IF_WHITELISTED);
379     }
380 
381     // Test the lockTaskMode flag for an activity declaring if_whitelisted.
382     // Verifies that updating the whitelisting during lock task mode finishes the locked task.
testManifestArgument_updateWhitelisting()383     public void testManifestArgument_updateWhitelisting() throws Exception {
384         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
385         startAndWait(getLockTaskUtility(UTILITY_ACTIVITY_IF_WHITELISTED));
386         waitForResume();
387 
388         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
389 
390         synchronized (mActivityRunningLock) {
391             mActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS);
392         }
393 
394         assertLockTaskModeInactive();
395         assertFalse(mIsActivityRunning);
396         assertFalse(mIsActivityResumed);
397     }
398 
399     // Start lock task with ActivityOptions
testActivityOptions_whitelisted()400     public void testActivityOptions_whitelisted() throws Exception {
401         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
402         startLockTaskWithOptions(UTILITY_ACTIVITY);
403         waitForResume();
404 
405         // Verify that activity open and activity manager is in lock task.
406         assertLockTaskModeActive();
407         assertTrue(mIsActivityRunning);
408         assertTrue(mIsActivityResumed);
409 
410         stopAndFinish(UTILITY_ACTIVITY);
411     }
412 
413     // Starting a non-whitelisted activity with ActivityOptions is not allowed
testActivityOptions_nonWhitelisted()414     public void testActivityOptions_nonWhitelisted() throws Exception {
415         try {
416             startLockTaskWithOptions(UTILITY_ACTIVITY);
417             fail();
418         } catch (SecurityException e) {
419             // pass
420         }
421     }
422 
423     /**
424      * Checks that lock task mode is active and fails the test if it isn't.
425      */
assertLockTaskModeActive()426     private void assertLockTaskModeActive() {
427         assertTrue(mActivityManager.isInLockTaskMode());
428         assertEquals(ActivityManager.LOCK_TASK_MODE_LOCKED,
429                 mActivityManager.getLockTaskModeState());
430     }
431 
432     /**
433      * Checks that lock task mode is not active and fails the test if it is.
434      */
assertLockTaskModeInactive()435     private void assertLockTaskModeInactive() throws InterruptedException {
436         // Retry 10 times with 200 ms interval.
437         for (int i = 0; i < 10 && mActivityManager.isInLockTaskMode(); i++) {
438             Thread.sleep(200);
439         }
440         assertFalse(mActivityManager.isInLockTaskMode());
441         assertEquals(ActivityManager.LOCK_TASK_MODE_NONE, mActivityManager.getLockTaskModeState());
442     }
443 
444     /**
445      * Call stopLockTask and finish on the LockTaskUtilityActivity.
446      *
447      * Verify that the activity is no longer running.
448      *
449      * If activityManager is not null then verify that the ActivityManager
450      * is no longer in lock task mode.
451      */
stopAndFinish(String className)452     private void stopAndFinish(String className) throws InterruptedException {
453         stopLockTask(className);
454         finishAndWait(className);
455         assertLockTaskModeInactive();
456         assertFalse(mIsActivityRunning);
457     }
458 
459     /**
460      * Call finish on the LockTaskUtilityActivity and wait for
461      * onDestroy to be called.
462      */
finishAndWait(String className)463     private void finishAndWait(String className) throws InterruptedException {
464         synchronized (mActivityRunningLock) {
465             finish(className);
466             if (mIsActivityRunning) {
467                 mActivityRunningLock.wait(ACTIVITY_DESTROYED_TIMEOUT_MILLIS);
468             }
469         }
470     }
471 
472     /**
473      * Wait for onResume to be called on the LockTaskUtilityActivity.
474      */
waitForResume()475     private void waitForResume() throws InterruptedException {
476         // It may take a moment for the resume to come in.
477         synchronized (mActivityResumedLock) {
478             if (!mIsActivityResumed) {
479                 mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
480             }
481         }
482     }
483 
484     /**
485      * Calls startLockTask on the LockTaskUtilityActivity
486      */
startLockTask(String className)487     private void startLockTask(String className) throws InterruptedException {
488         Intent intent = getLockTaskUtility(className);
489         intent.putExtra(LockTaskUtilityActivity.START_LOCK_TASK, true);
490         startAndWait(intent);
491     }
492 
493     /**
494      * Starts LockTaskUtilityActivity with {@link ActivityOptions#setLockTaskEnabled(boolean)}
495      */
startLockTaskWithOptions(String className)496     private void startLockTaskWithOptions(String className) throws InterruptedException {
497         Intent intent = getLockTaskUtility(className);
498         Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle();
499         startAndWait(intent, options);
500     }
501 
502     /**
503      * Calls stopLockTask on the LockTaskUtilityActivity
504      */
stopLockTask(String className)505     private void stopLockTask(String className) throws InterruptedException {
506         Intent intent = getLockTaskUtility(className);
507         intent.putExtra(LockTaskUtilityActivity.STOP_LOCK_TASK, true);
508         startAndWait(intent);
509     }
510 
511     /**
512      * Calls finish on the LockTaskUtilityActivity
513      */
finish(String className)514     private void finish(String className) throws InterruptedException {
515         Intent intent = getLockTaskUtility(className);
516         intent.putExtra(LockTaskUtilityActivity.FINISH, true);
517         startAndWait(intent);
518     }
519 
520     /**
521      * Sends a command intent to the LockTaskUtilityActivity and waits
522      * to receive the broadcast back confirming it has finished processing
523      * the command.
524      */
startAndWait(Intent intent)525     private void startAndWait(Intent intent) throws InterruptedException {
526         startAndWait(intent, null);
527     }
528 
529     /**
530      * Same as {@link #startAndWait(Intent)}, but with additional {@link ActivityOptions}.
531      */
startAndWait(Intent intent, Bundle options)532     private void startAndWait(Intent intent, Bundle options) throws InterruptedException {
533         mIntentHandled = false;
534         synchronized (this) {
535             mContext.startActivity(intent, options);
536             // Give 20 secs to finish.
537             wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS);
538             assertTrue(mIntentHandled);
539         }
540     }
541 
542     /**
543      * Get basic intent that points at the LockTaskUtilityActivity.
544      *
545      * This intent includes the flags to make it act as single top.
546      */
getLockTaskUtility(String className)547     private Intent getLockTaskUtility(String className) {
548         Intent intent = new Intent();
549         intent.setClassName(PACKAGE_NAME, className);
550         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
551         return intent;
552     }
553 
554     /** Create an intent to launch {@link #RECEIVER_ACTIVITY_NAME}. */
createReceiverActivityIntent(boolean newTask, boolean shouldWait)555     private Intent createReceiverActivityIntent(boolean newTask, boolean shouldWait) {
556         final Intent intent = new Intent();
557         intent.setComponent(
558                 new ComponentName(RECEIVER_ACTIVITY_PACKAGE_NAME, RECEIVER_ACTIVITY_NAME));
559         intent.setAction(shouldWait ? ACTION_CREATE_AND_WAIT : ACTION_JUST_CREATE);
560         intent.setFlags(newTask ? Intent.FLAG_ACTIVITY_NEW_TASK : 0);
561         return intent;
562     }
563 }
564