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