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