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