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