• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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