1 /*
2  * Copyright (C) 2020 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 
17 package com.android.cts.deviceowner;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import android.content.Intent;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.PackageInfo;
25 import android.content.pm.PackageManager;
26 import android.util.Log;
27 
28 import androidx.test.InstrumentationRegistry;
29 
30 import java.util.ArrayList;
31 
32 /**
33  * Test {@link DevicePolicyManager#setUserControlDisabledPackages} and
34  * {@link DevicePolicyManager#getUserControlDisabledPackages}
35  * Hostside test uses "am force-stop" and verifies that app is not stopped.
36  */
37 public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
38     private static final String TAG = "UserControlDisabledPackagesTest";
39 
40     private static final String SIMPLE_APP_PKG = "com.android.cts.launcherapps.simpleapp";
41     private static final String SIMPLE_APP_ACTIVITY =
42             "com.android.cts.launcherapps.simpleapp.SimpleActivityImmediateExit";
43     private static final String ARG_PID_BEFORE_STOP = "pidOfSimpleapp";
44 
testSetUserControlDisabledPackages()45     public void testSetUserControlDisabledPackages() throws Exception {
46         ArrayList<String> protectedPackages = new ArrayList<>();
47         protectedPackages.add(SIMPLE_APP_PKG);
48         mDevicePolicyManager.setUserControlDisabledPackages(getWho(), protectedPackages);
49     }
50 
testLaunchActivity()51     public void testLaunchActivity() throws Exception {
52         // Launch an activity so that the app exits stopped state.
53         Intent intent = new Intent(Intent.ACTION_MAIN);
54         intent.setClassName(SIMPLE_APP_PKG, SIMPLE_APP_ACTIVITY);
55         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
56         Log.d(TAG, "Starting " + intent + " on user " + getCurrentUser().getIdentifier());
57         mContext.startActivityAsUser(intent, getCurrentUser());
58     }
59 
testForceStopWithUserControlDisabled()60     public void testForceStopWithUserControlDisabled() throws Exception {
61         final ArrayList<String> pkgs = new ArrayList<>();
62         pkgs.add(SIMPLE_APP_PKG);
63         // Check if package is part of UserControlDisabledPackages before checking if
64         // package is stopped since it is a necessary condition to prevent stopping of
65         // package
66 
67         assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
68                 .contains(SIMPLE_APP_PKG);
69         assertPackageStopped(/* stopped= */ false);
70     }
71 
testClearSetUserControlDisabledPackages()72     public void testClearSetUserControlDisabledPackages() throws Exception {
73         final ArrayList<String> pkgs = new ArrayList<>();
74         mDevicePolicyManager.setUserControlDisabledPackages(getWho(), pkgs);
75         assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
76                 .doesNotContain(SIMPLE_APP_PKG);
77     }
78 
testForceStopWithUserControlEnabled()79     public void testForceStopWithUserControlEnabled() throws Exception {
80         assertPackageStopped(/* stopped= */ true);
81         assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
82                 .doesNotContain(SIMPLE_APP_PKG);
83     }
84 
testFgsStopWithUserControlDisabled()85     public void testFgsStopWithUserControlDisabled() throws Exception {
86         final ArrayList<String> pkgs = new ArrayList<>();
87         pkgs.add(SIMPLE_APP_PKG);
88         // Check if package is part of UserControlDisabledPackages before checking if
89         // package is stopped since it is a necessary condition to prevent stopping of
90         // package
91         assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
92                 .contains(SIMPLE_APP_PKG);
93         assertPackageRunningState(/* running= */ true,
94                 InstrumentationRegistry.getArguments().getString(ARG_PID_BEFORE_STOP, "-1"));
95     }
96 
testFgsStopWithUserControlEnabled()97     public void testFgsStopWithUserControlEnabled() throws Exception {
98         assertPackageRunningState(/* running= */ false,
99                 InstrumentationRegistry.getArguments().getString(ARG_PID_BEFORE_STOP, "-1"));
100         assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
101                 .doesNotContain(SIMPLE_APP_PKG);
102     }
103 
isPackageStopped(String packageName)104     private boolean isPackageStopped(String packageName) throws Exception {
105         PackageInfo packageInfo = mContext.getPackageManager()
106                 .getPackageInfoAsUser(packageName, PackageManager.GET_META_DATA,
107                         getCurrentUser().getIdentifier());
108         boolean stopped = (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED)
109                 == ApplicationInfo.FLAG_STOPPED;
110         Log.d(TAG, "Application flags for " + packageName + " on user "
111                 + getCurrentUser().getIdentifier() + " = "
112                 + Integer.toHexString(packageInfo.applicationInfo.flags) + ". Stopped: " + stopped);
113         return stopped;
114     }
115 
assertPackageStopped(boolean stopped)116     private void assertPackageStopped(boolean stopped) throws Exception {
117         assertWithMessage("Package %s stopped for user %s", SIMPLE_APP_PKG,
118                 getCurrentUser().getIdentifier())
119                 .that(isPackageStopped(SIMPLE_APP_PKG)).isEqualTo(stopped);
120     }
121 
isPackageRunning(String packageName)122     private boolean isPackageRunning(String packageName) throws Exception {
123         String pid = executeShellCommand(String.format("pidof %s", packageName)).trim();
124         return pid.length() > 0;
125     }
126 
assertPackageRunningState(boolean shouldBeRunning, String argPid)127     private void assertPackageRunningState(boolean shouldBeRunning, String argPid)
128             throws Exception {
129         String pid = executeShellCommand(String.format("pidof %s", SIMPLE_APP_PKG)).trim();
130 
131         final boolean samePid = pid.equals(argPid);
132         final boolean stillRunning = samePid && isPackageRunning(SIMPLE_APP_PKG);
133 
134         assertWithMessage("Package %s running for user %s", SIMPLE_APP_PKG,
135                 getCurrentUser().getIdentifier())
136                 .that(stillRunning).isEqualTo(shouldBeRunning);
137     }
138 }
139