1 /* 2 * Copyright (C) 2022 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 package com.android.server.devicepolicy; 17 18 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; 19 20 import android.annotation.Nullable; 21 import android.app.admin.SystemUpdateInfo; 22 import android.app.admin.SystemUpdatePolicy; 23 import android.app.admin.flags.Flags; 24 import android.content.ComponentName; 25 import android.os.UserHandle; 26 import android.util.ArrayMap; 27 import android.util.AtomicFile; 28 import android.util.IndentingPrintWriter; 29 import android.util.Log; 30 import android.util.Slog; 31 import android.util.Xml; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.modules.utils.TypedXmlPullParser; 35 import com.android.modules.utils.TypedXmlSerializer; 36 37 import libcore.io.IoUtils; 38 39 import org.xmlpull.v1.XmlPullParserException; 40 41 import java.io.File; 42 import java.io.FileOutputStream; 43 import java.io.IOException; 44 import java.io.InputStream; 45 import java.time.LocalDate; 46 import java.util.ArrayList; 47 import java.util.List; 48 import java.util.Map; 49 50 class OwnersData { 51 private static final String TAG = "DevicePolicyManagerService"; 52 53 private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE 54 55 // XML storing device owner info, system update policy and pending OTA update information. 56 private static final String DEVICE_OWNER_XML = "device_owner_2.xml"; 57 private static final String PROFILE_OWNER_XML = "profile_owner.xml"; 58 59 private static final String TAG_ROOT = "root"; 60 private static final String TAG_DEVICE_OWNER = "device-owner"; 61 private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; 62 private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record"; 63 private static final String TAG_PENDING_OTA_INFO = "pending-ota-info"; 64 private static final String TAG_PROFILE_OWNER = "profile-owner"; 65 // Holds "context" for device-owner, this must not be show up before device-owner. 66 private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context"; 67 private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type"; 68 private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES = 69 "device-owner-protected-packages"; 70 private static final String TAG_POLICY_ENGINE_MIGRATION = "policy-engine-migration"; 71 72 private static final String ATTR_NAME = "name"; 73 private static final String ATTR_PACKAGE = "package"; 74 private static final String ATTR_COMPONENT_NAME = "component"; 75 private static final String ATTR_SIZE = "size"; 76 private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri"; 77 private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash"; 78 private static final String ATTR_USERID = "userId"; 79 private static final String ATTR_FREEZE_RECORD_START = "start"; 80 private static final String ATTR_FREEZE_RECORD_END = "end"; 81 // Legacy attribute, its presence would mean the profile owner associated with it is 82 // managing a profile on an organization-owned device. 83 private static final String ATTR_CAN_ACCESS_DEVICE_IDS = "canAccessDeviceIds"; 84 // New attribute for profile owner of organization-owned device. 85 private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE = 86 "isPoOrganizationOwnedDevice"; 87 private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value"; 88 89 private static final String ATTR_MIGRATED_TO_POLICY_ENGINE = "migratedToPolicyEngine"; 90 private static final String ATTR_SECURITY_LOG_MIGRATED = "securityLogMigrated"; 91 private static final String ATTR_REQUIRED_PASSWORD_COMPLEXITY_MIGRATED = 92 "passwordComplexityMigrated"; 93 private static final String ATTR_SUSPENDED_PACKAGES_MIGRATED = "suspendedPackagesMigrated"; 94 private static final String ATTR_MIGRATED_POST_UPGRADE = "migratedPostUpgrade"; 95 96 // Internal state for the device owner package. 97 OwnerInfo mDeviceOwner; 98 int mDeviceOwnerUserId = UserHandle.USER_NULL; 99 100 // Device owner type for a managed device. 101 final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>(); 102 103 /** @deprecated moved to {@link ActiveAdmin#protectedPackages}. */ 104 @Deprecated 105 @Nullable 106 ArrayMap<String, List<String>> mDeviceOwnerProtectedPackages; 107 108 // Internal state for the profile owner packages. 109 final ArrayMap<Integer, OwnerInfo> mProfileOwners = new ArrayMap<>(); 110 111 // Local system update policy controllable by device owner. 112 SystemUpdatePolicy mSystemUpdatePolicy; 113 LocalDate mSystemUpdateFreezeStart; 114 LocalDate mSystemUpdateFreezeEnd; 115 116 // Pending OTA info if there is one. 117 @Nullable 118 SystemUpdateInfo mSystemUpdateInfo; 119 private final PolicyPathProvider mPathProvider; 120 121 boolean mMigratedToPolicyEngine = false; 122 boolean mSecurityLoggingMigrated = false; 123 boolean mRequiredPasswordComplexityMigrated = false; 124 boolean mSuspendedPackagesMigrated = false; 125 126 boolean mPoliciesMigratedPostUpdate = false; 127 OwnersData(PolicyPathProvider pathProvider)128 OwnersData(PolicyPathProvider pathProvider) { 129 mPathProvider = pathProvider; 130 } 131 load(int[] allUsers)132 void load(int[] allUsers) { 133 new DeviceOwnerReadWriter().readFromFileLocked(); 134 135 for (int userId : allUsers) { 136 new ProfileOwnerReadWriter(userId).readFromFileLocked(); 137 } 138 139 OwnerInfo profileOwner = mProfileOwners.get(mDeviceOwnerUserId); 140 ComponentName admin = profileOwner != null ? profileOwner.admin : null; 141 if (mDeviceOwner != null && admin != null) { 142 Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", 143 mDeviceOwnerUserId)); 144 } 145 } 146 147 /** 148 * @return true upon success, false otherwise. 149 */ writeDeviceOwner()150 boolean writeDeviceOwner() { 151 if (DEBUG) { 152 Log.d(TAG, "Writing to device owner file"); 153 } 154 return new DeviceOwnerReadWriter().writeToFileLocked(); 155 } 156 157 /** 158 * @return true upon success, false otherwise. 159 */ writeProfileOwner(int userId)160 boolean writeProfileOwner(int userId) { 161 if (DEBUG) { 162 Log.d(TAG, "Writing to profile owner file for user " + userId); 163 } 164 return new ProfileOwnerReadWriter(userId).writeToFileLocked(); 165 } 166 dump(IndentingPrintWriter pw)167 void dump(IndentingPrintWriter pw) { 168 boolean needBlank = false; 169 if (mDeviceOwner != null) { 170 pw.println("Device Owner: "); 171 pw.increaseIndent(); 172 mDeviceOwner.dump(pw); 173 pw.println("User ID: " + mDeviceOwnerUserId); 174 pw.decreaseIndent(); 175 needBlank = true; 176 } 177 if (mSystemUpdatePolicy != null) { 178 if (needBlank) { 179 pw.println(); 180 } 181 pw.println("System Update Policy: " + mSystemUpdatePolicy); 182 needBlank = true; 183 } 184 if (mProfileOwners != null) { 185 for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) { 186 if (needBlank) { 187 pw.println(); 188 } 189 pw.println("Profile Owner (User " + entry.getKey() + "): "); 190 pw.increaseIndent(); 191 entry.getValue().dump(pw); 192 pw.decreaseIndent(); 193 needBlank = true; 194 } 195 } 196 if (mSystemUpdateInfo != null) { 197 if (needBlank) { 198 pw.println(); 199 } 200 pw.println("Pending System Update: " + mSystemUpdateInfo); 201 needBlank = true; 202 } 203 if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { 204 if (needBlank) { 205 pw.println(); 206 } 207 pw.println("System update freeze record: " 208 + getSystemUpdateFreezePeriodRecordAsString()); 209 needBlank = true; 210 } 211 } 212 getSystemUpdateFreezePeriodRecordAsString()213 String getSystemUpdateFreezePeriodRecordAsString() { 214 StringBuilder freezePeriodRecord = new StringBuilder(); 215 freezePeriodRecord.append("start: "); 216 if (mSystemUpdateFreezeStart != null) { 217 freezePeriodRecord.append(mSystemUpdateFreezeStart.toString()); 218 } else { 219 freezePeriodRecord.append("null"); 220 } 221 freezePeriodRecord.append("; end: "); 222 if (mSystemUpdateFreezeEnd != null) { 223 freezePeriodRecord.append(mSystemUpdateFreezeEnd.toString()); 224 } else { 225 freezePeriodRecord.append("null"); 226 } 227 return freezePeriodRecord.toString(); 228 } 229 230 @VisibleForTesting getDeviceOwnerFile()231 File getDeviceOwnerFile() { 232 return new File(mPathProvider.getDataSystemDirectory(), DEVICE_OWNER_XML); 233 } 234 235 @VisibleForTesting getProfileOwnerFile(int userId)236 File getProfileOwnerFile(int userId) { 237 return new File(mPathProvider.getUserSystemDirectory(userId), PROFILE_OWNER_XML); 238 } 239 240 private abstract static class FileReadWriter { 241 private final File mFile; 242 FileReadWriter(File file)243 protected FileReadWriter(File file) { 244 mFile = file; 245 } 246 shouldWrite()247 abstract boolean shouldWrite(); 248 writeToFileLocked()249 boolean writeToFileLocked() { 250 if (!shouldWrite()) { 251 if (DEBUG) { 252 Log.d(TAG, "No need to write to " + mFile); 253 } 254 // No contents, remove the file. 255 if (mFile.exists()) { 256 if (DEBUG) { 257 Log.d(TAG, "Deleting existing " + mFile); 258 } 259 if (!mFile.delete()) { 260 Slog.e(TAG, "Failed to remove " + mFile.getPath()); 261 } 262 } 263 return true; 264 } 265 if (DEBUG) { 266 Log.d(TAG, "Writing to " + mFile); 267 } 268 269 final AtomicFile f = new AtomicFile(mFile); 270 FileOutputStream outputStream = null; 271 try { 272 outputStream = f.startWrite(); 273 final TypedXmlSerializer out = Xml.resolveSerializer(outputStream); 274 275 // Root tag 276 out.startDocument(null, true); 277 out.startTag(null, TAG_ROOT); 278 279 // Actual content 280 writeInner(out); 281 282 // Close root 283 out.endTag(null, TAG_ROOT); 284 out.endDocument(); 285 out.flush(); 286 287 // Commit the content. 288 f.finishWrite(outputStream); 289 outputStream = null; 290 291 } catch (IOException e) { 292 Slog.e(TAG, "Exception when writing", e); 293 if (outputStream != null) { 294 f.failWrite(outputStream); 295 } 296 return false; 297 } 298 return true; 299 } 300 readFromFileLocked()301 void readFromFileLocked() { 302 if (!mFile.exists()) { 303 if (DEBUG) { 304 Log.d(TAG, "" + mFile + " doesn't exist"); 305 } 306 return; 307 } 308 if (DEBUG) { 309 Log.d(TAG, "Reading from " + mFile); 310 } 311 final AtomicFile f = new AtomicFile(mFile); 312 InputStream input = null; 313 try { 314 input = f.openRead(); 315 final TypedXmlPullParser parser = Xml.resolvePullParser(input); 316 317 int type; 318 int depth = 0; 319 while ((type = parser.next()) != TypedXmlPullParser.END_DOCUMENT) { 320 switch (type) { 321 case TypedXmlPullParser.START_TAG: 322 depth++; 323 break; 324 case TypedXmlPullParser.END_TAG: 325 depth--; 326 // fallthrough 327 default: 328 continue; 329 } 330 // Check the root tag 331 final String tag = parser.getName(); 332 if (depth == 1) { 333 if (!TAG_ROOT.equals(tag)) { 334 Slog.e(TAG, "Invalid root tag: " + tag); 335 return; 336 } 337 continue; 338 } 339 // readInner() will only see START_TAG at depth >= 2. 340 if (!readInner(parser, depth, tag)) { 341 return; // Error 342 } 343 } 344 } catch (XmlPullParserException | IOException e) { 345 Slog.e(TAG, "Error parsing owners information file", e); 346 } finally { 347 IoUtils.closeQuietly(input); 348 } 349 } 350 writeInner(TypedXmlSerializer out)351 abstract void writeInner(TypedXmlSerializer out) throws IOException; 352 readInner(TypedXmlPullParser parser, int depth, String tag)353 abstract boolean readInner(TypedXmlPullParser parser, int depth, String tag); 354 } 355 356 private class DeviceOwnerReadWriter extends FileReadWriter { 357 DeviceOwnerReadWriter()358 protected DeviceOwnerReadWriter() { 359 super(getDeviceOwnerFile()); 360 } 361 362 @Override shouldWrite()363 boolean shouldWrite() { 364 return Flags.alwaysPersistDo() 365 || (mDeviceOwner != null) || (mSystemUpdatePolicy != null) 366 || (mSystemUpdateInfo != null); 367 } 368 369 @Override writeInner(TypedXmlSerializer out)370 void writeInner(TypedXmlSerializer out) throws IOException { 371 if (mDeviceOwner != null) { 372 mDeviceOwner.writeToXml(out, TAG_DEVICE_OWNER); 373 out.startTag(null, TAG_DEVICE_OWNER_CONTEXT); 374 out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId); 375 out.endTag(null, TAG_DEVICE_OWNER_CONTEXT); 376 377 } 378 379 if (!mDeviceOwnerTypes.isEmpty()) { 380 for (ArrayMap.Entry<String, Integer> entry : mDeviceOwnerTypes.entrySet()) { 381 out.startTag(null, TAG_DEVICE_OWNER_TYPE); 382 out.attribute(null, ATTR_PACKAGE, entry.getKey()); 383 out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue()); 384 out.endTag(null, TAG_DEVICE_OWNER_TYPE); 385 } 386 } 387 388 if (mSystemUpdatePolicy != null) { 389 out.startTag(null, TAG_SYSTEM_UPDATE_POLICY); 390 mSystemUpdatePolicy.saveToXml(out); 391 out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); 392 } 393 394 if (mSystemUpdateInfo != null) { 395 mSystemUpdateInfo.writeToXml(out, TAG_PENDING_OTA_INFO); 396 } 397 398 if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { 399 out.startTag(null, TAG_FREEZE_PERIOD_RECORD); 400 if (mSystemUpdateFreezeStart != null) { 401 out.attribute( 402 null, ATTR_FREEZE_RECORD_START, mSystemUpdateFreezeStart.toString()); 403 } 404 if (mSystemUpdateFreezeEnd != null) { 405 out.attribute(null, ATTR_FREEZE_RECORD_END, mSystemUpdateFreezeEnd.toString()); 406 } 407 out.endTag(null, TAG_FREEZE_PERIOD_RECORD); 408 } 409 410 out.startTag(null, TAG_POLICY_ENGINE_MIGRATION); 411 out.attributeBoolean(null, ATTR_MIGRATED_TO_POLICY_ENGINE, mMigratedToPolicyEngine); 412 out.attributeBoolean(null, ATTR_MIGRATED_POST_UPGRADE, mPoliciesMigratedPostUpdate); 413 if (Flags.securityLogV2Enabled()) { 414 out.attributeBoolean(null, ATTR_SECURITY_LOG_MIGRATED, mSecurityLoggingMigrated); 415 } 416 if (Flags.unmanagedModeMigration()) { 417 out.attributeBoolean(null, ATTR_REQUIRED_PASSWORD_COMPLEXITY_MIGRATED, 418 mRequiredPasswordComplexityMigrated); 419 out.attributeBoolean(null, ATTR_SUSPENDED_PACKAGES_MIGRATED, 420 mSuspendedPackagesMigrated); 421 422 } 423 424 out.endTag(null, TAG_POLICY_ENGINE_MIGRATION); 425 426 } 427 428 @Override readInner(TypedXmlPullParser parser, int depth, String tag)429 boolean readInner(TypedXmlPullParser parser, int depth, String tag) { 430 if (depth > 2) { 431 return true; // Ignore 432 } 433 switch (tag) { 434 case TAG_DEVICE_OWNER: 435 mDeviceOwner = OwnerInfo.readFromXml(parser); 436 mDeviceOwnerUserId = UserHandle.USER_SYSTEM; // Set default 437 break; 438 case TAG_DEVICE_OWNER_CONTEXT: { 439 mDeviceOwnerUserId = 440 parser.getAttributeInt(null, ATTR_USERID, mDeviceOwnerUserId); 441 break; 442 } 443 case TAG_SYSTEM_UPDATE_POLICY: 444 mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); 445 break; 446 case TAG_PENDING_OTA_INFO: 447 mSystemUpdateInfo = SystemUpdateInfo.readFromXml(parser); 448 break; 449 case TAG_FREEZE_PERIOD_RECORD: 450 String startDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_START); 451 String endDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_END); 452 if (startDate != null && endDate != null) { 453 mSystemUpdateFreezeStart = LocalDate.parse(startDate); 454 mSystemUpdateFreezeEnd = LocalDate.parse(endDate); 455 if (mSystemUpdateFreezeStart.isAfter(mSystemUpdateFreezeEnd)) { 456 Slog.e(TAG, "Invalid system update freeze record loaded"); 457 mSystemUpdateFreezeStart = null; 458 mSystemUpdateFreezeEnd = null; 459 } 460 } 461 break; 462 case TAG_DEVICE_OWNER_TYPE: 463 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 464 int deviceOwnerType = parser.getAttributeInt( 465 null, ATTR_DEVICE_OWNER_TYPE_VALUE, DEVICE_OWNER_TYPE_DEFAULT); 466 mDeviceOwnerTypes.put(packageName, deviceOwnerType); 467 break; 468 // Deprecated fields below. 469 case TAG_DEVICE_OWNER_PROTECTED_PACKAGES: 470 packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 471 int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0); 472 List<String> protectedPackages = new ArrayList<>(); 473 for (int i = 0; i < protectedPackagesSize; i++) { 474 protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i)); 475 } 476 if (mDeviceOwnerProtectedPackages == null) { 477 mDeviceOwnerProtectedPackages = new ArrayMap<>(); 478 } 479 mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); 480 break; 481 case TAG_POLICY_ENGINE_MIGRATION: 482 mMigratedToPolicyEngine = parser.getAttributeBoolean( 483 null, ATTR_MIGRATED_TO_POLICY_ENGINE, false); 484 mPoliciesMigratedPostUpdate = parser.getAttributeBoolean( 485 null, ATTR_MIGRATED_POST_UPGRADE, false); 486 mSecurityLoggingMigrated = Flags.securityLogV2Enabled() 487 && parser.getAttributeBoolean(null, ATTR_SECURITY_LOG_MIGRATED, false); 488 mRequiredPasswordComplexityMigrated = Flags.unmanagedModeMigration() 489 && parser.getAttributeBoolean(null, 490 ATTR_REQUIRED_PASSWORD_COMPLEXITY_MIGRATED, false); 491 mSuspendedPackagesMigrated = Flags.unmanagedModeMigration() 492 && parser.getAttributeBoolean(null, 493 ATTR_SUSPENDED_PACKAGES_MIGRATED, false); 494 495 break; 496 default: 497 Slog.e(TAG, "Unexpected tag: " + tag); 498 return false; 499 500 } 501 return true; 502 } 503 } 504 505 private class ProfileOwnerReadWriter extends FileReadWriter { 506 private final int mUserId; 507 ProfileOwnerReadWriter(int userId)508 ProfileOwnerReadWriter(int userId) { 509 super(getProfileOwnerFile(userId)); 510 mUserId = userId; 511 } 512 513 @Override shouldWrite()514 boolean shouldWrite() { 515 return mProfileOwners.get(mUserId) != null; 516 } 517 518 @Override writeInner(TypedXmlSerializer out)519 void writeInner(TypedXmlSerializer out) throws IOException { 520 final OwnerInfo profileOwner = mProfileOwners.get(mUserId); 521 if (profileOwner != null) { 522 profileOwner.writeToXml(out, TAG_PROFILE_OWNER); 523 } 524 } 525 526 @Override readInner(TypedXmlPullParser parser, int depth, String tag)527 boolean readInner(TypedXmlPullParser parser, int depth, String tag) { 528 if (depth > 2) { 529 return true; // Ignore 530 } 531 switch (tag) { 532 case TAG_PROFILE_OWNER: 533 mProfileOwners.put(mUserId, OwnerInfo.readFromXml(parser)); 534 break; 535 default: 536 Slog.e(TAG, "Unexpected tag: " + tag); 537 return false; 538 539 } 540 return true; 541 } 542 } 543 544 static class OwnerInfo { 545 public final String packageName; 546 public final ComponentName admin; 547 public String remoteBugreportUri; 548 public String remoteBugreportHash; 549 public boolean isOrganizationOwnedDevice; 550 OwnerInfo(ComponentName admin, String remoteBugreportUri, String remoteBugreportHash, boolean isOrganizationOwnedDevice)551 OwnerInfo(ComponentName admin, String remoteBugreportUri, 552 String remoteBugreportHash, boolean isOrganizationOwnedDevice) { 553 this.admin = admin; 554 this.packageName = admin.getPackageName(); 555 this.remoteBugreportUri = remoteBugreportUri; 556 this.remoteBugreportHash = remoteBugreportHash; 557 this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; 558 } 559 writeToXml(TypedXmlSerializer out, String tag)560 public void writeToXml(TypedXmlSerializer out, String tag) throws IOException { 561 out.startTag(null, tag); 562 if (admin != null) { 563 out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString()); 564 } 565 if (remoteBugreportUri != null) { 566 out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri); 567 } 568 if (remoteBugreportHash != null) { 569 out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash); 570 } 571 if (isOrganizationOwnedDevice) { 572 out.attributeBoolean( 573 null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE, isOrganizationOwnedDevice); 574 } 575 out.endTag(null, tag); 576 } 577 readFromXml(TypedXmlPullParser parser)578 public static OwnerInfo readFromXml(TypedXmlPullParser parser) { 579 final String componentName = parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 580 final String remoteBugreportUri = 581 parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_URI); 582 final String remoteBugreportHash = 583 parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_HASH); 584 final String canAccessDeviceIdsStr = 585 parser.getAttributeValue(null, ATTR_CAN_ACCESS_DEVICE_IDS); 586 final boolean canAccessDeviceIds = "true".equals(canAccessDeviceIdsStr); 587 final String isOrgOwnedDeviceStr = 588 parser.getAttributeValue(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE); 589 final boolean isOrgOwnedDevice = 590 "true".equals(isOrgOwnedDeviceStr) | canAccessDeviceIds; 591 592 if (componentName == null) { 593 Slog.e(TAG, "Owner component not found"); 594 return null; 595 } 596 final ComponentName admin = ComponentName.unflattenFromString(componentName); 597 if (admin == null) { 598 Slog.e(TAG, "Owner component not parsable: " + componentName); 599 return null; 600 } 601 602 return new OwnerInfo(admin, remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice); 603 } 604 dump(IndentingPrintWriter pw)605 public void dump(IndentingPrintWriter pw) { 606 pw.println("admin=" + admin); 607 pw.println("package=" + packageName); 608 pw.println("isOrganizationOwnedDevice=" + isOrganizationOwnedDevice); 609 } 610 } 611 } 612