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