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