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     /** @hide */
    142     public static class PolicyInfo {
    143         public final int ident;
    144         final public String tag;
    145         final public int label;
    146         final public int description;
    147 
    148         public PolicyInfo(int identIn, String tagIn, int labelIn, int descriptionIn) {
    149             ident = identIn;
    150             tag = tagIn;
    151             label = labelIn;
    152             description = descriptionIn;
    153         }
    154     }
    155 
    156     static ArrayList<PolicyInfo> sPoliciesDisplayOrder = new ArrayList<PolicyInfo>();
    157     static HashMap<String, Integer> sKnownPolicies = new HashMap<String, Integer>();
    158     static SparseArray<PolicyInfo> sRevKnownPolicies = new SparseArray<PolicyInfo>();
    159 
    160     static {
    161         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data",
    162                 com.android.internal.R.string.policylab_wipeData,
    163                 com.android.internal.R.string.policydesc_wipeData));
    164         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_RESET_PASSWORD, "reset-password",
    165                 com.android.internal.R.string.policylab_resetPassword,
    166                 com.android.internal.R.string.policydesc_resetPassword));
    167         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_LIMIT_PASSWORD, "limit-password",
    168                 com.android.internal.R.string.policylab_limitPassword,
    169                 com.android.internal.R.string.policydesc_limitPassword));
    170         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WATCH_LOGIN, "watch-login",
    171                 com.android.internal.R.string.policylab_watchLogin,
    172                 com.android.internal.R.string.policydesc_watchLogin));
    173         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_FORCE_LOCK, "force-lock",
    174                 com.android.internal.R.string.policylab_forceLock,
    175                 com.android.internal.R.string.policydesc_forceLock));
    176         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_SETS_GLOBAL_PROXY, "set-global-proxy",
    177                 com.android.internal.R.string.policylab_setGlobalProxy,
    178                 com.android.internal.R.string.policydesc_setGlobalProxy));
    179         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_EXPIRE_PASSWORD, "expire-password",
    180                 com.android.internal.R.string.policylab_expirePassword,
    181                 com.android.internal.R.string.policydesc_expirePassword));
    182         sPoliciesDisplayOrder.add(new PolicyInfo(USES_ENCRYPTED_STORAGE, "encrypted-storage",
    183                 com.android.internal.R.string.policylab_encryptedStorage,
    184                 com.android.internal.R.string.policydesc_encryptedStorage));
    185         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_DISABLE_CAMERA, "disable-camera",
    186                 com.android.internal.R.string.policylab_disableCamera,
    187                 com.android.internal.R.string.policydesc_disableCamera));
    188 
    189         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
    190             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
    191             sRevKnownPolicies.put(pi.ident, pi);
    192             sKnownPolicies.put(pi.tag, pi.ident);
    193         }
    194     }
    195 
    196     /**
    197      * The BroadcastReceiver that implements this device admin component.
    198      */
    199     final ResolveInfo mReceiver;
    200 
    201     /**
    202      * Whether this should be visible to the user.
    203      */
    204     boolean mVisible;
    205 
    206     /**
    207      * The policies this administrator needs access to.
    208      */
    209     int mUsesPolicies;
    210 
    211     /**
    212      * Constructor.
    213      *
    214      * @param context The Context in which we are parsing the device admin.
    215      * @param receiver The ResolveInfo returned from the package manager about
    216      * this device admin's component.
    217      */
    218     public DeviceAdminInfo(Context context, ResolveInfo receiver)
    219             throws XmlPullParserException, IOException {
    220         mReceiver = receiver;
    221         ActivityInfo ai = receiver.activityInfo;
    222 
    223         PackageManager pm = context.getPackageManager();
    224 
    225         XmlResourceParser parser = null;
    226         try {
    227             parser = ai.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
    228             if (parser == null) {
    229                 throw new XmlPullParserException("No "
    230                         + DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
    231             }
    232 
    233             Resources res = pm.getResourcesForApplication(ai.applicationInfo);
    234 
    235             AttributeSet attrs = Xml.asAttributeSet(parser);
    236 
    237             int type;
    238             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    239                     && type != XmlPullParser.START_TAG) {
    240             }
    241 
    242             String nodeName = parser.getName();
    243             if (!"device-admin".equals(nodeName)) {
    244                 throw new XmlPullParserException(
    245                         "Meta-data does not start with device-admin tag");
    246             }
    247 
    248             TypedArray sa = res.obtainAttributes(attrs,
    249                     com.android.internal.R.styleable.DeviceAdmin);
    250 
    251             mVisible = sa.getBoolean(
    252                     com.android.internal.R.styleable.DeviceAdmin_visible, true);
    253 
    254             sa.recycle();
    255 
    256             int outerDepth = parser.getDepth();
    257             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    258                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    259                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    260                     continue;
    261                 }
    262                 String tagName = parser.getName();
    263                 if (tagName.equals("uses-policies")) {
    264                     int innerDepth = parser.getDepth();
    265                     while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    266                            && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
    267                         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    268                             continue;
    269                         }
    270                         String policyName = parser.getName();
    271                         Integer val = sKnownPolicies.get(policyName);
    272                         if (val != null) {
    273                             mUsesPolicies |= 1 << val.intValue();
    274                         } else {
    275                             Log.w(TAG, "Unknown tag under uses-policies of "
    276                                     + getComponent() + ": " + policyName);
    277                         }
    278                     }
    279                 }
    280             }
    281         } catch (NameNotFoundException e) {
    282             throw new XmlPullParserException(
    283                     "Unable to create context for: " + ai.packageName);
    284         } finally {
    285             if (parser != null) parser.close();
    286         }
    287     }
    288 
    289     DeviceAdminInfo(Parcel source) {
    290         mReceiver = ResolveInfo.CREATOR.createFromParcel(source);
    291         mUsesPolicies = source.readInt();
    292     }
    293 
    294     /**
    295      * Return the .apk package that implements this device admin.
    296      */
    297     public String getPackageName() {
    298         return mReceiver.activityInfo.packageName;
    299     }
    300 
    301     /**
    302      * Return the class name of the receiver component that implements
    303      * this device admin.
    304      */
    305     public String getReceiverName() {
    306         return mReceiver.activityInfo.name;
    307     }
    308 
    309     /**
    310      * Return the raw information about the receiver implementing this
    311      * device admin.  Do not modify the returned object.
    312      */
    313     public ActivityInfo getActivityInfo() {
    314         return mReceiver.activityInfo;
    315     }
    316 
    317     /**
    318      * Return the component of the receiver that implements this device admin.
    319      */
    320     public ComponentName getComponent() {
    321         return new ComponentName(mReceiver.activityInfo.packageName,
    322                 mReceiver.activityInfo.name);
    323     }
    324 
    325     /**
    326      * Load the user-displayed label for this device admin.
    327      *
    328      * @param pm Supply a PackageManager used to load the device admin's
    329      * resources.
    330      */
    331     public CharSequence loadLabel(PackageManager pm) {
    332         return mReceiver.loadLabel(pm);
    333     }
    334 
    335     /**
    336      * Load user-visible description associated with this device admin.
    337      *
    338      * @param pm Supply a PackageManager used to load the device admin's
    339      * resources.
    340      */
    341     public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
    342         if (mReceiver.activityInfo.descriptionRes != 0) {
    343             String packageName = mReceiver.resolvePackageName;
    344             ApplicationInfo applicationInfo = null;
    345             if (packageName == null) {
    346                 packageName = mReceiver.activityInfo.packageName;
    347                 applicationInfo = mReceiver.activityInfo.applicationInfo;
    348             }
    349             return pm.getText(packageName,
    350                     mReceiver.activityInfo.descriptionRes, applicationInfo);
    351         }
    352         throw new NotFoundException();
    353     }
    354 
    355     /**
    356      * Load the user-displayed icon for this device admin.
    357      *
    358      * @param pm Supply a PackageManager used to load the device admin's
    359      * resources.
    360      */
    361     public Drawable loadIcon(PackageManager pm) {
    362         return mReceiver.loadIcon(pm);
    363     }
    364 
    365     /**
    366      * Returns whether this device admin would like to be visible to the
    367      * user, even when it is not enabled.
    368      */
    369     public boolean isVisible() {
    370         return mVisible;
    371     }
    372 
    373     /**
    374      * Return true if the device admin has requested that it be able to use
    375      * the given policy control.  The possible policy identifier inputs are:
    376      * {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
    377      * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
    378      * {@link #USES_POLICY_WIPE_DATA},
    379      * {@link #USES_POLICY_EXPIRE_PASSWORD}, {@link #USES_ENCRYPTED_STORAGE},
    380      * {@link #USES_POLICY_DISABLE_CAMERA}.
    381      */
    382     public boolean usesPolicy(int policyIdent) {
    383         return (mUsesPolicies & (1<<policyIdent)) != 0;
    384     }
    385 
    386     /**
    387      * Return the XML tag name for the given policy identifier.  Valid identifiers
    388      * are as per {@link #usesPolicy(int)}.  If the given identifier is not
    389      * known, null is returned.
    390      */
    391     public String getTagForPolicy(int policyIdent) {
    392         return sRevKnownPolicies.get(policyIdent).tag;
    393     }
    394 
    395     /** @hide */
    396     public ArrayList<PolicyInfo> getUsedPolicies() {
    397         ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
    398         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
    399             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
    400             if (usesPolicy(pi.ident)) {
    401                 res.add(pi);
    402             }
    403         }
    404         return res;
    405     }
    406 
    407     /** @hide */
    408     public void writePoliciesToXml(XmlSerializer out)
    409             throws IllegalArgumentException, IllegalStateException, IOException {
    410         out.attribute(null, "flags", Integer.toString(mUsesPolicies));
    411     }
    412 
    413     /** @hide */
    414     public void readPoliciesFromXml(XmlPullParser parser)
    415             throws XmlPullParserException, IOException {
    416         mUsesPolicies = Integer.parseInt(
    417                 parser.getAttributeValue(null, "flags"));
    418     }
    419 
    420     public void dump(Printer pw, String prefix) {
    421         pw.println(prefix + "Receiver:");
    422         mReceiver.dump(pw, prefix + "  ");
    423     }
    424 
    425     @Override
    426     public String toString() {
    427         return "DeviceAdminInfo{" + mReceiver.activityInfo.name + "}";
    428     }
    429 
    430     /**
    431      * Used to package this object into a {@link Parcel}.
    432      *
    433      * @param dest The {@link Parcel} to be written.
    434      * @param flags The flags used for parceling.
    435      */
    436     public void writeToParcel(Parcel dest, int flags) {
    437         mReceiver.writeToParcel(dest, flags);
    438         dest.writeInt(mUsesPolicies);
    439     }
    440 
    441     /**
    442      * Used to make this class parcelable.
    443      */
    444     public static final Parcelable.Creator<DeviceAdminInfo> CREATOR =
    445             new Parcelable.Creator<DeviceAdminInfo>() {
    446         public DeviceAdminInfo createFromParcel(Parcel source) {
    447             return new DeviceAdminInfo(source);
    448         }
    449 
    450         public DeviceAdminInfo[] newArray(int size) {
    451             return new DeviceAdminInfo[size];
    452         }
    453     };
    454 
    455     public int describeContents() {
    456         return 0;
    457     }
    458 }
    459