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