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