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