1 /* 2 * Copyright (C) 2023 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.bedstead.remotedpc; 18 19 import android.content.ComponentName; 20 import android.util.Log; 21 22 import androidx.annotation.Nullable; 23 24 import com.android.bedstead.nene.TestApis; 25 import com.android.bedstead.nene.devicepolicy.DeviceAdmin; 26 import com.android.bedstead.nene.devicepolicy.DevicePolicyController; 27 import com.android.bedstead.nene.users.UserReference; 28 import com.android.bedstead.testapp.TestApp; 29 import com.android.bedstead.testapp.TestAppProvider; 30 import com.android.bedstead.testapp.TestAppQueryBuilder; 31 32 import java.util.Set; 33 import java.util.stream.Collectors; 34 35 /** Entry point to RemoteDeviceAdmin. */ 36 public final class RemoteDeviceAdmin extends RemotePolicyManager { 37 38 private static final String DEFAULT_KEY = "remoteDeviceAdmin"; 39 public static final String REMOTE_DEVICE_ADMIN_APP_PACKAGE_NAME = 40 "com.android.cts.RemoteDeviceAdmin"; 41 private static final String LOG_TAG = "RemoteDeviceAdmin"; 42 43 private final DevicePolicyController mDevicePolicyController; 44 45 private final String mKey; 46 RemoteDeviceAdmin(TestApp testApp, DevicePolicyController devicePolicyController)47 public RemoteDeviceAdmin(TestApp testApp, DevicePolicyController devicePolicyController) { 48 super(testApp, devicePolicyController == null ? null : devicePolicyController.user()); 49 mDevicePolicyController = devicePolicyController; 50 mKey = DEFAULT_KEY; 51 } 52 RemoteDeviceAdmin(String key, TestApp testApp, DevicePolicyController devicePolicyController)53 public RemoteDeviceAdmin(String key, TestApp testApp, 54 DevicePolicyController devicePolicyController) { 55 super(testApp, devicePolicyController == null ? null : devicePolicyController.user()); 56 mDevicePolicyController = devicePolicyController; 57 mKey = key; 58 } 59 60 /** Get the unique key of the RemoteDeviceAdmin. */ key()61 public String key() { 62 return mKey; 63 } 64 65 /** 66 * Set device admin on instrumented user. 67 * 68 * This will return the existing {@link RemoteDeviceAdmin} if there is already one installed, 69 * otherwise a new {@link RemoteDeviceAdmin} will be installed and returned. 70 */ setAsDeviceAdmin()71 public static RemoteDeviceAdmin setAsDeviceAdmin() { 72 return setAsDeviceAdmin(DEFAULT_KEY, TestApis.users().instrumented(), 73 new TestAppProvider().query() 74 .allowInternalBedsteadTestApps() 75 .wherePackageName() 76 .isEqualTo(REMOTE_DEVICE_ADMIN_APP_PACKAGE_NAME)); 77 } 78 79 /** 80 * Set device admin on the instrumented user that matches the specified query. 81 * 82 * This will return the existing {@link RemoteDeviceAdmin} if there is already one installed, 83 * otherwise a new {@link RemoteDeviceAdmin} will be installed and returned. 84 */ setAsDeviceAdmin(UserReference user, TestAppQueryBuilder deviceAdminQuery)85 public static RemoteDeviceAdmin setAsDeviceAdmin(UserReference user, 86 TestAppQueryBuilder deviceAdminQuery) { 87 // We make sure that the query has RemoteDeviceAdmin filter specified, 88 // this is useful for the case where the user calls the method directly 89 // and does not specify the required filter. 90 deviceAdminQuery = addRemoteDeviceAdminPackageFilter(deviceAdminQuery); 91 92 return setAsDeviceAdmin(DEFAULT_KEY, user, deviceAdminQuery); 93 } 94 95 /** 96 * Set device admin on user. 97 * 98 * This will return the existing {@link RemoteDeviceAdmin} if there is already one installed, 99 * otherwise a new {@link RemoteDeviceAdmin} will be installed and returned. 100 */ setAsDeviceAdmin(UserReference user)101 public static RemoteDeviceAdmin setAsDeviceAdmin(UserReference user) { 102 return setAsDeviceAdmin(DEFAULT_KEY, user, new TestAppProvider().query() 103 .allowInternalBedsteadTestApps() 104 .wherePackageName() 105 .isEqualTo(REMOTE_DEVICE_ADMIN_APP_PACKAGE_NAME)); 106 } 107 108 /** 109 * Set device admin with the specified key on the default user. 110 * 111 * This will return the existing {@link RemoteDeviceAdmin} if there is already one installed, 112 * otherwise a new {@link RemoteDeviceAdmin} will be installed and returned. 113 */ setAsDeviceAdmin(String key, UserReference user, TestAppQueryBuilder deviceAdminQuery)114 private static RemoteDeviceAdmin setAsDeviceAdmin(String key, UserReference user, 115 TestAppQueryBuilder deviceAdminQuery) { 116 RemoteDeviceAdmin remoteDeviceAdmin = fetchRemoteDeviceAdmin(user, deviceAdminQuery); 117 if (remoteDeviceAdmin != null) { 118 Log.i(LOG_TAG, "RemoteDeviceAdmin already exists as an active admin, reusing."); 119 return remoteDeviceAdmin; 120 } 121 122 removeAllRemoteDeviceAdmins(user); 123 124 TestApp testApp = deviceAdminQuery.get(); 125 testApp.install(user); 126 127 Log.i(LOG_TAG, "Installing RemoteDeviceAdmin app: " + testApp.packageName() 128 + " with policies: " + testApp.policies()); 129 ComponentName componentName = 130 new ComponentName(testApp.packageName(), 131 testApp.packageName() + ".DeviceAdminReceiver"); 132 DeviceAdmin deviceAdmin = TestApis.devicePolicy().setActiveAdmin(user, componentName); 133 return new RemoteDeviceAdmin(key, testApp, deviceAdmin); 134 } 135 136 /** 137 * Get the {@link RemoteDeviceAdmin} controller for the given {@link DevicePolicyController}. 138 */ forDevicePolicyController(DevicePolicyController controller)139 public static RemoteDeviceAdmin forDevicePolicyController(DevicePolicyController controller) { 140 if (controller == null) { 141 throw new NullPointerException(); 142 } 143 144 if (isRemoteDeviceAdmin(controller)) { 145 TestApp remoteDeviceAdminTestApp = new TestAppProvider().query() 146 .allowInternalBedsteadTestApps() 147 .wherePackageName().startsWith(controller.componentName().getPackageName()) 148 .get(); 149 150 return new RemoteDeviceAdmin(remoteDeviceAdminTestApp, controller); 151 } 152 153 throw new IllegalStateException("DevicePolicyController is not a RemoteDeviceAdmin: " 154 + controller); 155 } 156 157 /** 158 * Get the {@link DevicePolicyController} for this instance of RemoteDeviceAdmin. 159 */ devicePolicyController()160 public DevicePolicyController devicePolicyController() { 161 return mDevicePolicyController; 162 } 163 164 /** 165 * Check if {@link DevicePolicyController} is a {@link RemoteDeviceAdmin} 166 */ isRemoteDeviceAdmin(DevicePolicyController controller)167 public static boolean isRemoteDeviceAdmin(DevicePolicyController controller) { 168 return controller != null 169 && controller.componentName().getPackageName().startsWith( 170 REMOTE_DEVICE_ADMIN_APP_PACKAGE_NAME) 171 && controller.componentName().getClassName().equals( 172 controller.componentName().getPackageName() + ".DeviceAdminReceiver"); 173 } 174 175 /** 176 * Get the RemoteDeviceAdmin from the list of active admins for the user. 177 */ fetchRemoteDeviceAdmin(UserReference user)178 public static RemoteDeviceAdmin fetchRemoteDeviceAdmin(UserReference user) { 179 TestAppQueryBuilder remoteDeviceAdminQuery = new TestAppProvider().query() 180 .allowInternalBedsteadTestApps() 181 .wherePackageName().startsWith(REMOTE_DEVICE_ADMIN_APP_PACKAGE_NAME); 182 return fetchRemoteDeviceAdmin(user, remoteDeviceAdminQuery); 183 } 184 fetchAllRemoteDeviceAdmins(UserReference user)185 public static Set<RemoteDeviceAdmin> fetchAllRemoteDeviceAdmins(UserReference user) { 186 Set<DeviceAdmin> activeAdmins = TestApis.devicePolicy().getActiveAdmins(user) 187 .stream().map(a -> DeviceAdmin.of(user, a.pkg(), a.componentName())) 188 .collect(Collectors.toUnmodifiableSet()); 189 return activeAdmins.stream() 190 .filter(RemoteDeviceAdmin::isRemoteDeviceAdmin) 191 .map(RemoteDeviceAdmin::forDevicePolicyController) 192 .collect(Collectors.toSet()); 193 } 194 195 /** 196 * Get the RemoteDeviceAdmin that matches the query (if exists) from the list of active admins 197 * for the instrumented user. 198 */ 199 @Nullable fetchRemoteDeviceAdmin(TestAppQueryBuilder deviceAdminQuery)200 public static RemoteDeviceAdmin fetchRemoteDeviceAdmin(TestAppQueryBuilder deviceAdminQuery) { 201 return fetchRemoteDeviceAdmin(TestApis.users().instrumented(), deviceAdminQuery); 202 } 203 204 /** 205 * Get the RemoteDeviceAdmin that matches the query (if exists) from the list of active admins 206 * for the user. 207 */ 208 @Nullable fetchRemoteDeviceAdmin(UserReference user, TestAppQueryBuilder deviceAdminQuery)209 public static RemoteDeviceAdmin fetchRemoteDeviceAdmin(UserReference user, 210 TestAppQueryBuilder deviceAdminQuery) { 211 Set<DeviceAdmin> activeAdmins = TestApis.devicePolicy().getActiveAdmins(user) 212 .stream().map(a -> DeviceAdmin.of(user, a.pkg(), a.componentName())) 213 .collect(Collectors.toUnmodifiableSet()); 214 if (activeAdmins.isEmpty()) { 215 return null; 216 } 217 218 return activeAdmins.stream() 219 .filter(RemoteDeviceAdmin::isRemoteDeviceAdmin) 220 .map(RemoteDeviceAdmin::forDevicePolicyController) 221 .filter((remoteDeviceAdmin) -> 222 deviceAdminQuery.matches(remoteDeviceAdmin.testApp())) 223 .findFirst().orElse(null); 224 } 225 226 @Override componentName()227 public ComponentName componentName() { 228 return mDevicePolicyController.componentName(); 229 } 230 removeAllRemoteDeviceAdmins(UserReference user)231 private static void removeAllRemoteDeviceAdmins(UserReference user) { 232 Set<RemoteDeviceAdmin> remoteDeviceAdmins = fetchAllRemoteDeviceAdmins(user); 233 if (remoteDeviceAdmins == null) { 234 return; 235 } 236 237 for (RemoteDeviceAdmin remoteDeviceAdmin : remoteDeviceAdmins) { 238 remoteDeviceAdmin.devicePolicyController().remove(); 239 } 240 } 241 addRemoteDeviceAdminPackageFilter( TestAppQueryBuilder dpcQuery)242 private static TestAppQueryBuilder addRemoteDeviceAdminPackageFilter( 243 TestAppQueryBuilder dpcQuery) { 244 return dpcQuery.wherePackageName() 245 .startsWith(REMOTE_DEVICE_ADMIN_APP_PACKAGE_NAME) 246 .allowInternalBedsteadTestApps(); 247 } 248 249 @Override hashCode()250 public int hashCode() { 251 return mDevicePolicyController.hashCode(); 252 } 253 254 @Override equals(Object obj)255 public boolean equals(Object obj) { 256 if (!(obj instanceof RemoteDeviceAdmin)) { 257 return false; 258 } 259 260 RemoteDeviceAdmin other = (RemoteDeviceAdmin) obj; 261 return other.mDevicePolicyController.equals(mDevicePolicyController); 262 } 263 264 @Override toString()265 public String toString() { 266 return "RemoteDeviceAdmin{" 267 + "devicePolicyController=" + mDevicePolicyController 268 + ", testApp=" + super.toString() 269 + '}'; 270 } 271 } 272