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.admin.DevicePolicyManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.PackageManager;
25 import android.util.Log;
26 
27 import androidx.test.InstrumentationRegistry;
28 import androidx.test.uiautomator.UiDevice;
29 
30 import com.android.compatibility.common.util.PollingCheck;
31 
32 /**
33  * Test class that is meant to be driven from the host and can't be run alone, which is required
34  * for tests that include rebooting or other connection-breaking steps. For this reason, this class
35  * does not override tearDown and setUp just initializes the test state, changing nothing in the
36  * device. Therefore, the host is responsible for making sure the tests leave the device in a clean
37  * state after running.
38  */
39 public class LockTaskHostDrivenTest extends BaseDeviceAdminTest {
40 
41     private static final String TAG = LockTaskHostDrivenTest.class.getName();
42     private static final int ACTIVITY_RESUMED_TIMEOUT_MILLIS = 20000;  // 20 seconds
43     private static final int LOCK_TASK_STATE_CHANGE_TIMEOUT_MILLIS = 10000;  // 10 seconds
44     private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
45     private static final String LOCK_TASK_ACTIVITY
46             = LockTaskUtilityActivityIfAllowed.class.getName();
47 
48     private UiDevice mUiDevice;
49     private Context mContext;
50     private PackageManager mPackageManager;
51     private ActivityManager mActivityManager;
52     private DevicePolicyManager mDevicePolicyManager;
53 
setUp()54     public void setUp() {
55         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
56         mContext = InstrumentationRegistry.getContext();
57         mPackageManager = mContext.getPackageManager();
58         mActivityManager = mContext.getSystemService(ActivityManager.class);
59         mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
60     }
61 
testStartLockTask_noAsserts()62     public void testStartLockTask_noAsserts() throws Exception {
63         Log.d(TAG, "testStartLockTask_noAsserts on host-driven test (no cleanup)");
64         setLockTaskPackages(mContext.getPackageName());
65         setDefaultHomeIntentReceiver();
66         launchLockTaskActivity();
67         mUiDevice.waitForIdle();
68     }
69 
testCleanupLockTask_noAsserts()70     public void testCleanupLockTask_noAsserts() {
71         Log.d(TAG, "testCleanupLockTask_noAsserts on host-driven test");
72         mDevicePolicyManager.clearPackagePersistentPreferredActivities(
73                 ADMIN_RECEIVER_COMPONENT,
74                 mContext.getPackageName());
75         setLockTaskPackages();
76         mDevicePolicyManager.setLockTaskFeatures(ADMIN_RECEIVER_COMPONENT, 0);
77         // In case some activity is still in foreground
78         mUiDevice.pressHome();
79     }
80 
testLockTaskIsActive()81     public void testLockTaskIsActive() throws Exception {
82         Log.d(TAG, "testLockTaskIsActive on host-driven test");
83         waitAndCheckLockedActivityIsResumed();
84         checkLockedActivityIsRunning();
85     }
86 
87     /**
88      * On low-RAM devices, this test can take too long to finish, so the test runner can incorrectly
89      * assume it's finished. Therefore, only use it once in a given test.
90      *
91      * <p>Does not test that the locked activity is initially in the foreground, since running this
92      * test in instrumentation can immediately kill the locked activity (while maintaining lock task
93      * mode).
94      */
testLockTaskIsActiveAndCantBeInterrupted()95     public void testLockTaskIsActiveAndCantBeInterrupted() throws Exception {
96         Log.d(TAG, "testLockTaskIsActiveAndCantBeInterrupted on host-driven test");
97         waitAndEnsureLockTaskUtilityActivityIsRunning();
98         checkLockedActivityIsRunning();
99 
100         mUiDevice.pressHome();
101         mUiDevice.waitForIdle();
102         checkLockedActivityIsRunning();
103 
104         mUiDevice.pressRecentApps();
105         mUiDevice.waitForIdle();
106         checkLockedActivityIsRunning();
107 
108         mUiDevice.pressBack();
109         mUiDevice.waitForIdle();
110         checkLockedActivityIsRunning();
111 
112         mUiDevice.waitForIdle();
113     }
114 
checkLockedActivityIsRunning()115     private void checkLockedActivityIsRunning() throws Exception {
116         waitAndCheckLockedActivityIsResumed();
117 
118         ComponentName topActivity = mActivityManager.getAppTasks().get(0).getTaskInfo().topActivity;
119         assertNotNull(topActivity);
120         assertEquals(LOCK_TASK_ACTIVITY, topActivity.getClassName());
121 
122         PollingCheck.waitFor(
123                 () -> (mActivityManager.getLockTaskModeState()
124                         == ActivityManager.LOCK_TASK_MODE_LOCKED));
125     }
126 
127     /**
128      * Ensures the locked activity is resumed or otherwise launches it but without starting lock
129      * task if it is not already in that mode.
130      */
waitAndEnsureLockTaskUtilityActivityIsRunning()131     private void waitAndEnsureLockTaskUtilityActivityIsRunning() throws Exception {
132         mUiDevice.waitForIdle();
133         final boolean lockedActivityIsResumed =
134                 LockTaskUtilityActivity.waitUntilActivityResumed(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
135         if (!lockedActivityIsResumed) {
136             launchLockTaskUtilityActivityWithoutStartingLockTask();
137             waitAndCheckLockedActivityIsResumed();
138         }
139     }
140 
waitAndCheckLockedActivityIsResumed()141     private void waitAndCheckLockedActivityIsResumed() throws Exception {
142         mUiDevice.waitForIdle();
143         assertTrue(
144                 LockTaskUtilityActivity.waitUntilActivityResumed(ACTIVITY_RESUMED_TIMEOUT_MILLIS));
145     }
146 
launchLockTaskActivity()147     private void launchLockTaskActivity() {
148         Intent intent = new Intent(mContext, LockTaskUtilityActivityIfAllowed.class);
149         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
150         intent.putExtra(LockTaskUtilityActivity.START_LOCK_TASK, true);
151         mContext.startActivity(intent);
152     }
153 
launchLockTaskUtilityActivityWithoutStartingLockTask()154     private void launchLockTaskUtilityActivityWithoutStartingLockTask() {
155         final Intent intent = new Intent();
156         intent.setAction(Intent.ACTION_MAIN);
157         intent.addCategory(Intent.CATEGORY_HOME);
158         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
159         mContext.startActivity(intent);
160     }
161 
setLockTaskPackages(String... packages)162     private void setLockTaskPackages(String... packages) {
163         mDevicePolicyManager.setLockTaskPackages(ADMIN_RECEIVER_COMPONENT, packages);
164     }
165 
setDefaultHomeIntentReceiver()166     private void setDefaultHomeIntentReceiver() {
167         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
168         intentFilter.addCategory(Intent.CATEGORY_HOME);
169         intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
170         mDevicePolicyManager.addPersistentPreferredActivity(
171                 ADMIN_RECEIVER_COMPONENT, intentFilter,
172                 new ComponentName(mContext.getPackageName(), LOCK_TASK_ACTIVITY));
173     }
174 }
175