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