1 /*
2  * Copyright (C) 2015 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 com.google.common.truth.Truth.assertWithMessage;
19 
20 import android.annotation.NonNull;
21 import android.app.admin.DeviceAdminReceiver;
22 import android.app.admin.DevicePolicyManager;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.content.pm.PackageInfo;
28 import android.content.pm.PackageManager;
29 import android.net.Uri;
30 import android.os.Process;
31 import android.os.SystemClock;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.test.InstrumentationTestCase;
35 import android.text.TextUtils;
36 import android.util.Log;
37 
38 import androidx.test.platform.app.InstrumentationRegistry;
39 
40 import com.android.bedstead.dpmwrapper.DeviceOwnerHelper;
41 import com.android.bedstead.dpmwrapper.TestAppSystemServiceFactory;
42 import com.android.compatibility.common.util.SystemUtil;
43 import com.android.cts.deviceandprofileowner.BaseDeviceAdminTest.BasicAdminReceiver;
44 
45 import java.util.List;
46 import java.util.concurrent.CountDownLatch;
47 
48 /**
49  * Base class for profile and device based tests.
50  *
51  * <p>This class handles making sure that the test is the profile or device owner and that it has an
52  * active admin registered, so that all tests may assume these are done.
53  */
54 public abstract class BaseDeviceAdminTest extends InstrumentationTestCase {
55 
56     public static final class BasicAdminReceiver extends DeviceAdminReceiver {
57 
58         static final String ACTION_NETWORK_LOGS_AVAILABLE =
59                 "com.android.cts.deviceandprofileowner.action.ACTION_NETWORK_LOGS_AVAILABLE";
60 
61         static final String EXTRA_NETWORK_LOGS_BATCH_TOKEN =
62                 "com.android.cts.deviceandprofileowner.extra.NETWORK_LOGS_BATCH_TOKEN";
63 
64         // Shared preference used to coordinate compliance acknowledgement test.
65         static final String COMPLIANCE_ACK_PREF_NAME = "compliance-pref";
66         // Shared preference key controlling whether to use default callback implementation.
67         static final String COMPLIANCE_ACK_PREF_KEY_OVERRIDE = "compliance-pref-override";
68         // Shared preference key to save broadcast receipt.
69         static final String COMPLIANCE_ACK_PREF_KEY_BCAST_RECEIVED = "compliance-pref-bcast";
70 
71         @Override
onReceive(Context context, Intent intent)72         public void onReceive(Context context, Intent intent) {
73             if (DeviceOwnerHelper.runManagerMethod(this, context, intent)) return;
74 
75             super.onReceive(context, intent);
76         }
77 
78         @Override
onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri, String suggestedAlias)79         public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
80                 String suggestedAlias) {
81             super.onChoosePrivateKeyAlias(context, intent, uid, uri, suggestedAlias);
82             if (uid != Process.myUid() || uri == null) {
83                 return null;
84             }
85             return uri.getQueryParameter("alias");
86         }
87 
88         @Override
onPasswordExpiring(Context context, Intent intent, UserHandle user)89         public void onPasswordExpiring(Context context, Intent intent, UserHandle user) {
90             super.onPasswordExpiring(context, intent, user);
91             if (mOnPasswordExpiryTimeoutCalled != null) {
92                 mOnPasswordExpiryTimeoutCalled.countDown();
93             }
94         }
95 
96         @Override
onNetworkLogsAvailable(Context context, Intent intent, long batchToken, int networkLogsCount)97         public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
98                 int networkLogsCount) {
99             super.onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
100             // send the broadcast, the rest of the test happens in NetworkLoggingTest
101             Intent batchIntent = new Intent(ACTION_NETWORK_LOGS_AVAILABLE);
102             batchIntent.putExtra(EXTRA_NETWORK_LOGS_BATCH_TOKEN, batchToken);
103             context.sendBroadcast(batchIntent);
104         }
105 
106         @Override
onComplianceAcknowledgementRequired( @onNull Context context, @NonNull Intent intent)107         public void onComplianceAcknowledgementRequired(
108                 @NonNull Context context, @NonNull Intent intent) {
109             final SharedPreferences pref =
110                     context.getSharedPreferences(COMPLIANCE_ACK_PREF_NAME, Context.MODE_PRIVATE);
111             // Record the broadcast receipt.
112             pref.edit().putBoolean(COMPLIANCE_ACK_PREF_KEY_BCAST_RECEIVED, true).commit();
113             // Call the default implementation unless instructed otherwise.
114             if (!pref.getBoolean(COMPLIANCE_ACK_PREF_KEY_OVERRIDE, false)) {
115                 super.onComplianceAcknowledgementRequired(context, intent);
116             }
117         }
118     }
119 
120     private static final String TAG = BaseDeviceAdminTest.class.getSimpleName();
121 
122     public static final String PACKAGE_NAME = BasicAdminReceiver.class.getPackage().getName();
123     public static final ComponentName ADMIN_RECEIVER_COMPONENT = new ComponentName(
124             PACKAGE_NAME, BasicAdminReceiver.class.getName());
125 
126     protected DevicePolicyManager mDevicePolicyManager;
127     protected UserManager mUserManager;
128     protected Context mContext;
129     protected boolean mHasSecureLockScreen;
130     static CountDownLatch mOnPasswordExpiryTimeoutCalled;
131 
132     protected final String mTag = getClass().getSimpleName();
133 
134     @Override
setUp()135     protected void setUp() throws Exception {
136         super.setUp();
137         mContext = getInstrumentation().getContext();
138 
139         mUserManager = mContext.getSystemService(UserManager.class);
140         assertWithMessage("userManager").that(mUserManager).isNotNull();
141 
142         mHasSecureLockScreen = mContext.getPackageManager().hasSystemFeature(
143                 PackageManager.FEATURE_SECURE_LOCK_SCREEN);
144 
145         boolean isDeviceOwnerTest = "DeviceOwner"
146                 .equals(InstrumentationRegistry.getArguments().getString("admin_type"));
147 
148         mDevicePolicyManager = TestAppSystemServiceFactory.getDevicePolicyManager(mContext,
149                 BasicAdminReceiver.class, isDeviceOwnerTest);
150 
151         Log.v(TAG, "setup(): dpm for " + getClass() + " and user " + mContext.getUserId() + ": "
152                 + mDevicePolicyManager);
153         assertWithMessage("dpm").that(mDevicePolicyManager).isNotNull();
154 
155         boolean isActiveAdmin = mDevicePolicyManager.isAdminActive(ADMIN_RECEIVER_COMPONENT);
156         boolean isProfileOwner = mDevicePolicyManager.isProfileOwnerApp(PACKAGE_NAME);
157         boolean isDeviceOwner = mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME);
158 
159         Log.d(mTag, "setup() on user " + mContext.getUserId() + ": package=" + PACKAGE_NAME
160                 + ", adminReceiverComponent=" + ADMIN_RECEIVER_COMPONENT
161                 + ", isActiveAdmin=" + isActiveAdmin + ", isProfileOwner=" + isProfileOwner
162                 + ", isDeviceOwner=" + isDeviceOwner + ", isDeviceOwnerTest=" + isDeviceOwnerTest);
163 
164         assertWithMessage("active admin for %s", ADMIN_RECEIVER_COMPONENT).that(isActiveAdmin)
165                 .isTrue();
166 
167         assertWithMessage("profile owner or device owner for %s", PACKAGE_NAME)
168                 .that(isProfileOwner || isDeviceOwner).isTrue();
169     }
170 
getTargetApiLevel()171     protected int getTargetApiLevel() throws Exception {
172         final PackageManager pm = mContext.getPackageManager();
173         final PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), /* flags= */ 0);
174         return pi.applicationInfo.targetSdkVersion;
175     }
176 
177     /**
178      * Runs a Shell command, returning a trimmed response.
179      */
runShellCommand(String template, Object...args)180     protected String runShellCommand(String template, Object...args) {
181         final String command = String.format(template, args);
182         Log.d(mTag, "runShellCommand(): " + command);
183         try {
184             final String result = SystemUtil.runShellCommand(getInstrumentation(), command);
185             return TextUtils.isEmpty(result) ? "" : result.trim();
186         } catch (Exception e) {
187             throw new RuntimeException("Command '" + command + "' failed: ", e);
188         }
189     }
190 
waitUntilUserUnlocked()191     protected void waitUntilUserUnlocked() {
192         boolean isUserUnlocked = mUserManager.isUserUnlocked();
193         int retries = 30;
194         while (retries >= 0 && !isUserUnlocked) {
195             retries--;
196             try {
197                 Thread.sleep(500);
198             } catch (InterruptedException e) {
199                 break;
200             }
201         }
202         assertWithMessage("user unlocked").that(mUserManager.isUserUnlocked()).isTrue();
203     }
204 
assertPasswordSufficiency(boolean expectPasswordSufficient)205     protected void assertPasswordSufficiency(boolean expectPasswordSufficient) {
206         waitUntilUserUnlocked();
207         assertWithMessage("isActivePasswordSufficient()")
208                 .that(mDevicePolicyManager.isActivePasswordSufficient())
209                 .isEqualTo(expectPasswordSufficient);
210     }
211 
isDeviceOwner()212     protected boolean isDeviceOwner() {
213         return mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME);
214     }
215 
setDelegatedScopes(String delegatePackage, List<String> scopes)216     protected void setDelegatedScopes(String delegatePackage, List<String> scopes) {
217         Log.v(TAG, "Calling setDelegatedScopes(" + ADMIN_RECEIVER_COMPONENT.flattenToShortString()
218                 + ", " + delegatePackage + ", " + scopes + ") using " + mDevicePolicyManager);
219         mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT, delegatePackage, scopes);
220     }
221 
sleep(int timeMs)222     void sleep(int timeMs) {
223         Log.d(TAG, "Sleeping " + timeMs + " ms");
224         SystemClock.sleep(timeMs);
225     }
226 }
227