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