1 /*
2  * Copyright (C) 2010 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 android.app.admin;
18 
19 import static android.app.admin.flags.Flags.FLAG_HEADLESS_DEVICE_OWNER_SINGLE_USER_ENABLED;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.app.admin.flags.Flags;
25 import android.compat.annotation.UnsupportedAppUsage;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.PackageManager.NameNotFoundException;
31 import android.content.pm.ResolveInfo;
32 import android.content.res.Resources;
33 import android.content.res.Resources.NotFoundException;
34 import android.content.res.TypedArray;
35 import android.content.res.XmlResourceParser;
36 import android.graphics.drawable.Drawable;
37 import android.os.Build;
38 import android.os.Parcel;
39 import android.os.Parcelable;
40 import android.os.PersistableBundle;
41 import android.util.AttributeSet;
42 import android.util.Log;
43 import android.util.Printer;
44 import android.util.SparseArray;
45 import android.util.Xml;
46 
47 import com.android.modules.utils.TypedXmlPullParser;
48 import com.android.modules.utils.TypedXmlSerializer;
49 
50 import org.xmlpull.v1.XmlPullParser;
51 import org.xmlpull.v1.XmlPullParserException;
52 
53 import java.io.IOException;
54 import java.lang.annotation.Retention;
55 import java.lang.annotation.RetentionPolicy;
56 import java.util.ArrayList;
57 import java.util.HashMap;
58 
59 /**
60  * This class is used to specify meta information of a device administrator
61  * component.
62  */
63 public final class DeviceAdminInfo implements Parcelable {
64     static final String TAG = "DeviceAdminInfo";
65 
66     /**
67      * A type of policy that this device admin can use: limit the passwords
68      * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
69      * and {@link DevicePolicyManager#setPasswordMinimumLength}.
70      *
71      * <p>To control this policy, the device admin must be a device owner or profile owner,
72      * and must have a "limit-password" tag in the "uses-policies" section of its meta-data.
73      * If used by a device owner, the policy only affects the primary user and its profiles,
74      * but not any secondary users on the device.
75      */
76     public static final int USES_POLICY_LIMIT_PASSWORD = 0;
77 
78     /**
79      * A type of policy that this device admin can use: able to watch login
80      * attempts from the user, via {@link DeviceAdminReceiver#ACTION_PASSWORD_FAILED},
81      * {@link DeviceAdminReceiver#ACTION_PASSWORD_SUCCEEDED}, and
82      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts}.
83      *
84      * <p>To control this policy, the device admin must have a "watch-login"
85      * tag in the "uses-policies" section of its meta-data.
86      */
87     public static final int USES_POLICY_WATCH_LOGIN = 1;
88 
89     /**
90      * A type of policy that this device admin can use: able to reset the
91      * user's password via
92      * {@link DevicePolicyManager#resetPassword}.
93      *
94      * <p>To control this policy, the device admin must have a "reset-password"
95      * tag in the "uses-policies" section of its meta-data.
96      */
97     public static final int USES_POLICY_RESET_PASSWORD = 2;
98 
99     /**
100      * A type of policy that this device admin can use: able to force the device
101      * to lock via{@link DevicePolicyManager#lockNow} or limit the
102      * maximum lock timeout for the device via
103      * {@link DevicePolicyManager#setMaximumTimeToLock}.
104      *
105      * <p>To control this policy, the device admin must have a "force-lock"
106      * tag in the "uses-policies" section of its meta-data.
107      */
108     public static final int USES_POLICY_FORCE_LOCK = 3;
109 
110     /**
111      * A type of policy that this device admin can use: able to factory
112      * reset the device, erasing all of the user's data, via
113      * {@link DevicePolicyManager#wipeData}.
114      *
115      * <p>To control this policy, the device admin must have a "wipe-data"
116      * tag in the "uses-policies" section of its meta-data.
117      */
118     public static final int USES_POLICY_WIPE_DATA = 4;
119 
120     /**
121      * A type of policy that this device admin can use: able to specify the
122      * device Global Proxy, via {@link DevicePolicyManager#setGlobalProxy}.
123      *
124      * <p>To control this policy, the device admin must have a "set-global-proxy"
125      * tag in the "uses-policies" section of its meta-data.
126      * @hide
127      */
128     public static final int USES_POLICY_SETS_GLOBAL_PROXY = 5;
129 
130     /**
131      * A type of policy that this device admin can use: force the user to
132      * change their password after an administrator-defined time limit.
133      *
134      * <p>To control this policy, the device admin must be a device owner or profile owner,
135      * and must have an "expire-password" tag in the "uses-policies" section of its meta-data.
136      * If used by a device owner, the policy only affects the primary user and its profiles,
137      * but not any secondary users on the device.
138      */
139     public static final int USES_POLICY_EXPIRE_PASSWORD = 6;
140 
141     /**
142      * A type of policy that this device admin can use: require encryption of stored data.
143      *
144      * <p>To control this policy, the device admin must have a "encrypted-storage"
145      * tag in the "uses-policies" section of its meta-data.
146      */
147     public static final int USES_ENCRYPTED_STORAGE = 7;
148 
149     /**
150      * A type of policy that this device admin can use: disables use of all device cameras.
151      *
152      * <p>To control this policy, the device admin must be a device owner or profile owner,
153      * and must have a "disable-camera" tag in the "uses-policies" section of its meta-data.
154      * If used by a device owner, the policy affects all users on the device.
155      */
156     public static final int USES_POLICY_DISABLE_CAMERA = 8;
157 
158     /**
159      * A type of policy that this device admin can use: disables use of keyguard features.
160      *
161      * <p>To control this policy, the device admin must be a device owner or profile owner,
162      * and must have a "disable-keyguard-features" tag in the "uses-policies" section of its
163      * meta-data.  If used by a device owner, the policy only affects the primary user and
164      * its profiles, but not any secondary users on the device.
165      */
166     public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
167 
168 
169     /**
170      * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should not
171      * be provisioned into Device Owner mode on a Headless System User Mode device.
172      */
173     public static final int HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED = 0;
174 
175     /**
176      * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should be
177      * provisioned into "affiliated" mode when on a Headless System User Mode device.
178      *
179      * <p>This mode adds a Profile Owner to all users other than the user the Device Owner is on.
180      *
181      * <p>Starting from Android version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
182      * DPCs should set the value of attribute "headless-device-owner-mode" inside the
183      * "headless-system-user" tag as "affiliated".
184      */
185     public static final int HEADLESS_DEVICE_OWNER_MODE_AFFILIATED = 1;
186 
187     /**
188      * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should be
189      * provisioned into the first secondary user when on a Headless System User Mode device.
190      *
191      * <p>This mode only allows a single secondary user on the device blocking the creation of
192      * additional secondary users.
193      *
194      * <p>Starting from Android version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
195      * DPCs should set the value of attribute "headless-device-owner-mode" inside the
196      * "headless-system-user" tag as "single_user".
197      */
198     @FlaggedApi(FLAG_HEADLESS_DEVICE_OWNER_SINGLE_USER_ENABLED)
199     public static final int HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER = 2;
200 
201     /**
202      * @hide
203      */
204     @IntDef({HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED, HEADLESS_DEVICE_OWNER_MODE_AFFILIATED,
205             HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER})
206     @Retention(RetentionPolicy.SOURCE)
207     public @interface HeadlessDeviceOwnerMode {}
208 
209     /** @hide */
210     public static class PolicyInfo {
211         public final int ident;
212         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
213         public final String tag;
214         public final int label;
215         public final int description;
216         public final int labelForSecondaryUsers;
217         public final int descriptionForSecondaryUsers;
218 
PolicyInfo(int ident, String tag, int label, int description)219         public PolicyInfo(int ident, String tag, int label, int description) {
220             this(ident, tag, label, description, label, description);
221         }
222 
PolicyInfo(int ident, String tag, int label, int description, int labelForSecondaryUsers, int descriptionForSecondaryUsers)223         public PolicyInfo(int ident, String tag, int label, int description,
224                 int labelForSecondaryUsers, int descriptionForSecondaryUsers) {
225             this.ident = ident;
226             this.tag = tag;
227             this.label = label;
228             this.description = description;
229             this.labelForSecondaryUsers = labelForSecondaryUsers;
230             this.descriptionForSecondaryUsers = descriptionForSecondaryUsers;
231         }
232     }
233 
234     static ArrayList<PolicyInfo> sPoliciesDisplayOrder = new ArrayList<PolicyInfo>();
235     static HashMap<String, Integer> sKnownPolicies = new HashMap<String, Integer>();
236     static SparseArray<PolicyInfo> sRevKnownPolicies = new SparseArray<PolicyInfo>();
237 
238     static {
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data", com.android.internal.R.string.policylab_wipeData, com.android.internal.R.string.policydesc_wipeData, com.android.internal.R.string.policylab_wipeData_secondaryUser, com.android.internal.R.string.policydesc_wipeData_secondaryUser ))239         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data",
240                 com.android.internal.R.string.policylab_wipeData,
241                 com.android.internal.R.string.policydesc_wipeData,
242                 com.android.internal.R.string.policylab_wipeData_secondaryUser,
243                 com.android.internal.R.string.policydesc_wipeData_secondaryUser
244                 ));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_RESET_PASSWORD, "reset-password", com.android.internal.R.string.policylab_resetPassword, com.android.internal.R.string.policydesc_resetPassword))245         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_RESET_PASSWORD, "reset-password",
246                 com.android.internal.R.string.policylab_resetPassword,
247                 com.android.internal.R.string.policydesc_resetPassword));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_LIMIT_PASSWORD, "limit-password", com.android.internal.R.string.policylab_limitPassword, com.android.internal.R.string.policydesc_limitPassword))248         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_LIMIT_PASSWORD, "limit-password",
249                 com.android.internal.R.string.policylab_limitPassword,
250                 com.android.internal.R.string.policydesc_limitPassword));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WATCH_LOGIN, "watch-login", com.android.internal.R.string.policylab_watchLogin, com.android.internal.R.string.policydesc_watchLogin, com.android.internal.R.string.policylab_watchLogin, com.android.internal.R.string.policydesc_watchLogin_secondaryUser ))251         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WATCH_LOGIN, "watch-login",
252                 com.android.internal.R.string.policylab_watchLogin,
253                 com.android.internal.R.string.policydesc_watchLogin,
254                 com.android.internal.R.string.policylab_watchLogin,
255                 com.android.internal.R.string.policydesc_watchLogin_secondaryUser
256         ));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_FORCE_LOCK, "force-lock", com.android.internal.R.string.policylab_forceLock, com.android.internal.R.string.policydesc_forceLock))257         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_FORCE_LOCK, "force-lock",
258                 com.android.internal.R.string.policylab_forceLock,
259                 com.android.internal.R.string.policydesc_forceLock));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_SETS_GLOBAL_PROXY, "set-global-proxy", com.android.internal.R.string.policylab_setGlobalProxy, com.android.internal.R.string.policydesc_setGlobalProxy))260         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_SETS_GLOBAL_PROXY, "set-global-proxy",
261                 com.android.internal.R.string.policylab_setGlobalProxy,
262                 com.android.internal.R.string.policydesc_setGlobalProxy));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_EXPIRE_PASSWORD, "expire-password", com.android.internal.R.string.policylab_expirePassword, com.android.internal.R.string.policydesc_expirePassword))263         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_EXPIRE_PASSWORD, "expire-password",
264                 com.android.internal.R.string.policylab_expirePassword,
265                 com.android.internal.R.string.policydesc_expirePassword));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_ENCRYPTED_STORAGE, "encrypted-storage", com.android.internal.R.string.policylab_encryptedStorage, com.android.internal.R.string.policydesc_encryptedStorage))266         sPoliciesDisplayOrder.add(new PolicyInfo(USES_ENCRYPTED_STORAGE, "encrypted-storage",
267                 com.android.internal.R.string.policylab_encryptedStorage,
268                 com.android.internal.R.string.policydesc_encryptedStorage));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_DISABLE_CAMERA, "disable-camera", com.android.internal.R.string.policylab_disableCamera, com.android.internal.R.string.policydesc_disableCamera))269         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_DISABLE_CAMERA, "disable-camera",
270                 com.android.internal.R.string.policylab_disableCamera,
271                 com.android.internal.R.string.policydesc_disableCamera));
sPoliciesDisplayOrder.add(new PolicyInfo( USES_POLICY_DISABLE_KEYGUARD_FEATURES, "disable-keyguard-features", com.android.internal.R.string.policylab_disableKeyguardFeatures, com.android.internal.R.string.policydesc_disableKeyguardFeatures))272         sPoliciesDisplayOrder.add(new PolicyInfo(
273                 USES_POLICY_DISABLE_KEYGUARD_FEATURES, "disable-keyguard-features",
274                 com.android.internal.R.string.policylab_disableKeyguardFeatures,
275                 com.android.internal.R.string.policydesc_disableKeyguardFeatures));
276 
277         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
278             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
sRevKnownPolicies.put(pi.ident, pi)279             sRevKnownPolicies.put(pi.ident, pi);
sKnownPolicies.put(pi.tag, pi.ident)280             sKnownPolicies.put(pi.tag, pi.ident);
281         }
282     }
283 
284     /**
285      * The BroadcastReceiver that implements this device admin component.
286      */
287     final ActivityInfo mActivityInfo;
288 
289     /**
290      * Whether this should be visible to the user.
291      */
292     boolean mVisible;
293 
294     /**
295      * The policies this administrator needs access to.
296      */
297     int mUsesPolicies;
298 
299     /**
300      * Whether this administrator can be a target in an ownership transfer.
301      *
302      * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
303      */
304     boolean mSupportsTransferOwnership;
305 
306     @HeadlessDeviceOwnerMode int mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
307 
308     /**
309      * Constructor.
310      *
311      * @param context The Context in which we are parsing the device admin.
312      * @param resolveInfo The ResolveInfo returned from the package manager about
313      * this device admin's component.
314      */
DeviceAdminInfo(Context context, ResolveInfo resolveInfo)315     public DeviceAdminInfo(Context context, ResolveInfo resolveInfo)
316             throws XmlPullParserException, IOException {
317         this(context, resolveInfo.activityInfo);
318     }
319     /**
320      * Constructor.
321      *
322      * @param context The Context in which we are parsing the device admin.
323      * @param activityInfo The ActivityInfo returned from the package manager about
324      * this device admin's component.
325      *
326      * @hide
327      */
DeviceAdminInfo(Context context, ActivityInfo activityInfo)328     public DeviceAdminInfo(Context context, ActivityInfo activityInfo)
329             throws XmlPullParserException, IOException {
330         mActivityInfo = activityInfo;
331 
332         PackageManager pm = context.getPackageManager();
333 
334         XmlResourceParser parser = null;
335         try {
336             parser = mActivityInfo.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
337             if (parser == null) {
338                 throw new XmlPullParserException("No "
339                         + DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
340             }
341 
342             Resources res = pm.getResourcesForApplication(mActivityInfo.applicationInfo);
343 
344             AttributeSet attrs = Xml.asAttributeSet(parser);
345 
346             int type;
347             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
348                     && type != XmlPullParser.START_TAG) {
349             }
350 
351             String nodeName = parser.getName();
352             if (!"device-admin".equals(nodeName)) {
353                 throw new XmlPullParserException(
354                         "Meta-data does not start with device-admin tag");
355             }
356 
357             TypedArray sa = res.obtainAttributes(attrs,
358                     com.android.internal.R.styleable.DeviceAdmin);
359 
360             mVisible = sa.getBoolean(
361                     com.android.internal.R.styleable.DeviceAdmin_visible, true);
362 
363             sa.recycle();
364 
365             int outerDepth = parser.getDepth();
366             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
367                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
368                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
369                     continue;
370                 }
371                 String tagName = parser.getName();
372                 if (tagName.equals("uses-policies")) {
373                     int innerDepth = parser.getDepth();
374                     while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
375                            && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
376                         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
377                             continue;
378                         }
379                         String policyName = parser.getName();
380                         Integer val = sKnownPolicies.get(policyName);
381                         if (val != null) {
382                             mUsesPolicies |= 1 << val.intValue();
383                         } else {
384                             Log.w(TAG, "Unknown tag under uses-policies of "
385                                     + getComponent() + ": " + policyName);
386                         }
387                     }
388                 } else if (tagName.equals("support-transfer-ownership")) {
389                     if (parser.next() != XmlPullParser.END_TAG) {
390                         throw new XmlPullParserException(
391                                 "support-transfer-ownership tag must be empty.");
392                     }
393                     mSupportsTransferOwnership = true;
394                 } else if (tagName.equals("headless-system-user")) {
395                     String deviceOwnerModeStringValue = null;
396                     if (Flags.headlessSingleUserCompatibilityFix()) {
397                         deviceOwnerModeStringValue = parser.getAttributeValue(
398                                  null, "headless-device-owner-mode");
399                     }
400                     if (deviceOwnerModeStringValue == null) {
401                         deviceOwnerModeStringValue =
402                                 parser.getAttributeValue(null, "device-owner-mode");
403                     }
404 
405                     if ("unsupported".equalsIgnoreCase(deviceOwnerModeStringValue)) {
406                         mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
407                     } else if ("affiliated".equalsIgnoreCase(deviceOwnerModeStringValue)) {
408                         mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
409                     } else if ("single_user".equalsIgnoreCase(deviceOwnerModeStringValue)) {
410                         mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
411                     } else {
412                         if (Flags.headlessSingleUserCompatibilityFix()) {
413                             Log.e(TAG, "Unknown headless-system-user mode: "
414                                     + deviceOwnerModeStringValue);
415                         } else {
416                             throw new XmlPullParserException(
417                                     "headless-system-user mode must be valid");
418                         }
419                     }
420                 }
421             }
422         } catch (NameNotFoundException e) {
423             throw new XmlPullParserException(
424                     "Unable to create context for: " + mActivityInfo.packageName);
425         } finally {
426             if (parser != null) parser.close();
427         }
428     }
429 
DeviceAdminInfo(Parcel source)430     DeviceAdminInfo(Parcel source) {
431         mActivityInfo = ActivityInfo.CREATOR.createFromParcel(source);
432         mUsesPolicies = source.readInt();
433         mSupportsTransferOwnership = source.readBoolean();
434         mHeadlessDeviceOwnerMode = source.readInt();
435     }
436 
437     /**
438      * Return the .apk package that implements this device admin.
439      */
getPackageName()440     public String getPackageName() {
441         return mActivityInfo.packageName;
442     }
443 
444     /**
445      * Return the class name of the receiver component that implements
446      * this device admin.
447      */
getReceiverName()448     public String getReceiverName() {
449         return mActivityInfo.name;
450     }
451 
452     /**
453      * Return the raw information about the receiver implementing this
454      * device admin.  Do not modify the returned object.
455      */
getActivityInfo()456     public ActivityInfo getActivityInfo() {
457         return mActivityInfo;
458     }
459 
460     /**
461      * Return the component of the receiver that implements this device admin.
462      */
463     @NonNull
getComponent()464     public ComponentName getComponent() {
465         return new ComponentName(mActivityInfo.packageName,
466                 mActivityInfo.name);
467     }
468 
469     /**
470      * Load the user-displayed label for this device admin.
471      *
472      * @param pm Supply a PackageManager used to load the device admin's
473      * resources.
474      */
loadLabel(PackageManager pm)475     public CharSequence loadLabel(PackageManager pm) {
476         return mActivityInfo.loadLabel(pm);
477     }
478 
479     /**
480      * Load user-visible description associated with this device admin.
481      *
482      * @param pm Supply a PackageManager used to load the device admin's
483      * resources.
484      */
loadDescription(PackageManager pm)485     public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
486         if (mActivityInfo.descriptionRes != 0) {
487             return pm.getText(mActivityInfo.packageName,
488                     mActivityInfo.descriptionRes, mActivityInfo.applicationInfo);
489         }
490         throw new NotFoundException();
491     }
492 
493     /**
494      * Load the user-displayed icon for this device admin.
495      *
496      * @param pm Supply a PackageManager used to load the device admin's
497      * resources.
498      */
loadIcon(PackageManager pm)499     public Drawable loadIcon(PackageManager pm) {
500         return mActivityInfo.loadIcon(pm);
501     }
502 
503     /**
504      * Returns whether this device admin would like to be visible to the
505      * user, even when it is not enabled.
506      */
isVisible()507     public boolean isVisible() {
508         return mVisible;
509     }
510 
511     /**
512      * Return true if the device admin has requested that it be able to use
513      * the given policy control.  The possible policy identifier inputs are:
514      * {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
515      * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
516      * {@link #USES_POLICY_WIPE_DATA},
517      * {@link #USES_POLICY_EXPIRE_PASSWORD}, {@link #USES_ENCRYPTED_STORAGE},
518      * {@link #USES_POLICY_DISABLE_CAMERA}.
519      */
usesPolicy(int policyIdent)520     public boolean usesPolicy(int policyIdent) {
521         return (mUsesPolicies & (1<<policyIdent)) != 0;
522     }
523 
524     /**
525      * Return the XML tag name for the given policy identifier.  Valid identifiers
526      * are as per {@link #usesPolicy(int)}.  If the given identifier is not
527      * known, null is returned.
528      */
getTagForPolicy(int policyIdent)529     public String getTagForPolicy(int policyIdent) {
530         return sRevKnownPolicies.get(policyIdent).tag;
531     }
532 
533     /**
534      * Return true if this administrator can be a target in an ownership transfer.
535      */
supportsTransferOwnership()536     public boolean supportsTransferOwnership() {
537         return mSupportsTransferOwnership;
538     }
539 
540     /**
541      * Returns the mode this DeviceAdmin wishes to use if provisioned as a Device Owner on a
542      * headless system user mode device.
543      */
getHeadlessDeviceOwnerMode()544     public @HeadlessDeviceOwnerMode int getHeadlessDeviceOwnerMode() {
545         return mHeadlessDeviceOwnerMode;
546     }
547 
548     /** @hide */
549     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getUsedPolicies()550     public ArrayList<PolicyInfo> getUsedPolicies() {
551         ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
552         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
553             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
554             if (usesPolicy(pi.ident)) {
555                 res.add(pi);
556             }
557         }
558         return res;
559     }
560 
561     /** @hide */
writePoliciesToXml(TypedXmlSerializer out)562     public void writePoliciesToXml(TypedXmlSerializer out)
563             throws IllegalArgumentException, IllegalStateException, IOException {
564         out.attributeInt(null, "flags", mUsesPolicies);
565     }
566 
567     /** @hide */
readPoliciesFromXml(TypedXmlPullParser parser)568     public void readPoliciesFromXml(TypedXmlPullParser parser)
569             throws XmlPullParserException, IOException {
570         mUsesPolicies = parser.getAttributeInt(null, "flags");
571     }
572 
dump(Printer pw, String prefix)573     public void dump(Printer pw, String prefix) {
574         pw.println(prefix + "Receiver:");
575         mActivityInfo.dump(pw, prefix + "  ");
576     }
577 
578     @Override
toString()579     public String toString() {
580         return "DeviceAdminInfo{" + mActivityInfo.name + "}";
581     }
582 
583     /**
584      * Used to package this object into a {@link Parcel}.
585      *
586      * @param dest The {@link Parcel} to be written.
587      * @param flags The flags used for parceling.
588      */
writeToParcel(Parcel dest, int flags)589     public void writeToParcel(Parcel dest, int flags) {
590         mActivityInfo.writeToParcel(dest, flags);
591         dest.writeInt(mUsesPolicies);
592         dest.writeBoolean(mSupportsTransferOwnership);
593         dest.writeInt(mHeadlessDeviceOwnerMode);
594     }
595 
596     /**
597      * Used to make this class parcelable.
598      */
599     public static final @android.annotation.NonNull Parcelable.Creator<DeviceAdminInfo> CREATOR =
600             new Parcelable.Creator<DeviceAdminInfo>() {
601         public DeviceAdminInfo createFromParcel(Parcel source) {
602             return new DeviceAdminInfo(source);
603         }
604 
605         public DeviceAdminInfo[] newArray(int size) {
606             return new DeviceAdminInfo[size];
607         }
608     };
609 
describeContents()610     public int describeContents() {
611         return 0;
612     }
613 }
614