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.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 
    175         public PolicyInfo(int ident, String tag, int label, int description) {
    176             this(ident, tag, label, description, label, description);
    177         }
    178 
    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 {
    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                 ));
    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));
    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));
    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         ));
    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));
    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));
    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));
    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));
    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));
    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);
    235             sRevKnownPolicies.put(pi.ident, pi);
    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      */
    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      */
    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 
    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      */
    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      */
    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      */
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    443     public String getTagForPolicy(int policyIdent) {
    444         return sRevKnownPolicies.get(policyIdent).tag;
    445     }
    446 
    447     /** @hide */
    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 */
    460     public void writePoliciesToXml(XmlSerializer out)
    461             throws IllegalArgumentException, IllegalStateException, IOException {
    462         out.attribute(null, "flags", Integer.toString(mUsesPolicies));
    463     }
    464 
    465     /** @hide */
    466     public void readPoliciesFromXml(XmlPullParser parser)
    467             throws XmlPullParserException, IOException {
    468         mUsesPolicies = Integer.parseInt(
    469                 parser.getAttributeValue(null, "flags"));
    470     }
    471 
    472     public void dump(Printer pw, String prefix) {
    473         pw.println(prefix + "Receiver:");
    474         mActivityInfo.dump(pw, prefix + "  ");
    475     }
    476 
    477     @Override
    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      */
    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 
    507     public int describeContents() {
    508         return 0;
    509     }
    510 }
    511