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 @Override onPasswordChanged(@onNull Context context, @NonNull Intent intent, @NonNull UserHandle user)120 public void onPasswordChanged(@NonNull Context context, @NonNull Intent intent, 121 @NonNull UserHandle user) { 122 super.onPasswordChanged(context, intent, user); 123 if (mOnPasswordChangedCalled != null) { 124 mOnPasswordChangedCalled.countDown(); 125 } 126 } 127 128 @Override onSecurityLogsAvailable(@onNull Context context, @NonNull Intent intent)129 public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) { 130 super.onSecurityLogsAvailable(context, intent); 131 if (mOnSecurityLogsAvailableCalled != null) { 132 mOnSecurityLogsAvailableCalled.countDown(); 133 } 134 } 135 } 136 137 private static final String TAG = BaseDeviceAdminTest.class.getSimpleName(); 138 139 public static final String PACKAGE_NAME = BasicAdminReceiver.class.getPackage().getName(); 140 public static final ComponentName ADMIN_RECEIVER_COMPONENT = new ComponentName( 141 PACKAGE_NAME, BasicAdminReceiver.class.getName()); 142 143 protected DevicePolicyManager mDevicePolicyManager; 144 protected DevicePolicyManager mLocalDevicePolicyManager; 145 protected UserManager mUserManager; 146 protected Context mContext; 147 protected boolean mHasSecureLockScreen; 148 protected boolean mIsAutomotive; 149 protected boolean mIsDeviceOwnerTest; 150 static CountDownLatch mOnPasswordExpiryTimeoutCalled; 151 static CountDownLatch mOnPasswordChangedCalled; 152 static CountDownLatch mOnSecurityLogsAvailableCalled; 153 protected final String mTag = getClass().getSimpleName(); 154 155 @Override setUp()156 protected void setUp() throws Exception { 157 super.setUp(); 158 mContext = getInstrumentation().getContext(); 159 160 mUserManager = mContext.getSystemService(UserManager.class); 161 assertWithMessage("userManager").that(mUserManager).isNotNull(); 162 163 mHasSecureLockScreen = mContext.getPackageManager().hasSystemFeature( 164 PackageManager.FEATURE_SECURE_LOCK_SCREEN); 165 mIsAutomotive = mContext.getPackageManager().hasSystemFeature( 166 PackageManager.FEATURE_AUTOMOTIVE); 167 168 mIsDeviceOwnerTest = "DeviceOwner" 169 .equals(InstrumentationRegistry.getArguments().getString("admin_type")); 170 171 mDevicePolicyManager = TestAppSystemServiceFactory.getDevicePolicyManager(mContext, 172 BasicAdminReceiver.class, mIsDeviceOwnerTest); 173 mLocalDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); 174 175 Log.v(TAG, "setup(): dpm for " + getClass() + " and user " + mContext.getUserId() + ": " 176 + mDevicePolicyManager); 177 assertWithMessage("dpm").that(mDevicePolicyManager).isNotNull(); 178 179 boolean isActiveAdmin = mDevicePolicyManager.isAdminActive(ADMIN_RECEIVER_COMPONENT); 180 boolean isProfileOwner = mDevicePolicyManager.isProfileOwnerApp(PACKAGE_NAME); 181 boolean isDeviceOwner = mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME); 182 183 Log.d(mTag, "setup() on user " + mContext.getUserId() + ": package=" + PACKAGE_NAME 184 + ", adminReceiverComponent=" + ADMIN_RECEIVER_COMPONENT 185 + ", isActiveAdmin=" + isActiveAdmin + ", isProfileOwner=" + isProfileOwner 186 + ", isDeviceOwner=" + isDeviceOwner + ", isDeviceOwnerTest=" + mIsDeviceOwnerTest); 187 188 assertWithMessage("active admin for %s", ADMIN_RECEIVER_COMPONENT).that(isActiveAdmin) 189 .isTrue(); 190 191 assertWithMessage("profile owner or device owner for %s", PACKAGE_NAME) 192 .that(isProfileOwner || isDeviceOwner).isTrue(); 193 } 194 getTargetApiLevel()195 protected int getTargetApiLevel() throws Exception { 196 final PackageManager pm = mContext.getPackageManager(); 197 final PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), /* flags= */ 0); 198 return pi.applicationInfo.targetSdkVersion; 199 } 200 201 /** 202 * Runs a Shell command, returning a trimmed response. 203 */ runShellCommand(String template, Object...args)204 protected String runShellCommand(String template, Object...args) { 205 final String command = String.format(template, args); 206 Log.d(mTag, "runShellCommand(): " + command); 207 try { 208 final String result = SystemUtil.runShellCommand(getInstrumentation(), command); 209 return TextUtils.isEmpty(result) ? "" : result.trim(); 210 } catch (Exception e) { 211 throw new RuntimeException("Command '" + command + "' failed: ", e); 212 } 213 } 214 waitUntilUserUnlocked()215 protected void waitUntilUserUnlocked() { 216 boolean isUserUnlocked = mUserManager.isUserUnlocked(); 217 int retries = 30; 218 while (retries >= 0 && !isUserUnlocked) { 219 retries--; 220 try { 221 Thread.sleep(500); 222 } catch (InterruptedException e) { 223 break; 224 } 225 } 226 assertWithMessage("user unlocked").that(mUserManager.isUserUnlocked()).isTrue(); 227 } 228 assertPasswordSufficiency(boolean expectPasswordSufficient)229 protected void assertPasswordSufficiency(boolean expectPasswordSufficient) { 230 waitUntilUserUnlocked(); 231 assertWithMessage("isActivePasswordSufficient()") 232 .that(mDevicePolicyManager.isActivePasswordSufficient()) 233 .isEqualTo(expectPasswordSufficient); 234 } 235 isDeviceOwner()236 protected boolean isDeviceOwner() { 237 return mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME); 238 } 239 setDelegatedScopes(String delegatePackage, List<String> scopes)240 protected void setDelegatedScopes(String delegatePackage, List<String> scopes) { 241 Log.v(TAG, "Calling setDelegatedScopes(" + ADMIN_RECEIVER_COMPONENT.flattenToShortString() 242 + ", " + delegatePackage + ", " + scopes + ") using " + mDevicePolicyManager); 243 mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT, delegatePackage, scopes); 244 } 245 sleep(int timeMs)246 void sleep(int timeMs) { 247 Log.d(TAG, "Sleeping " + timeMs + " ms"); 248 SystemClock.sleep(timeMs); 249 } 250 } 251