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