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