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