1 /* 2 * Copyright (C) 2014 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 com.android.server.devicepolicy; 18 19 import android.annotation.Nullable; 20 import android.app.admin.SystemUpdatePolicy; 21 import android.content.ComponentName; 22 import android.content.pm.PackageManagerInternal; 23 import android.content.pm.UserInfo; 24 import android.os.Environment; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.os.UserManagerInternal; 28 import android.util.ArrayMap; 29 import android.util.AtomicFile; 30 import android.util.Log; 31 import android.util.Pair; 32 import android.util.Slog; 33 import android.util.SparseArray; 34 import android.util.Xml; 35 36 import com.android.internal.util.FastXmlSerializer; 37 38 import org.xmlpull.v1.XmlPullParser; 39 import org.xmlpull.v1.XmlPullParserException; 40 import org.xmlpull.v1.XmlSerializer; 41 42 import java.io.File; 43 import java.io.FileOutputStream; 44 import java.io.IOException; 45 import java.io.InputStream; 46 import java.io.PrintWriter; 47 import java.nio.charset.StandardCharsets; 48 import java.util.List; 49 import java.util.Map; 50 import java.util.Set; 51 52 import libcore.io.IoUtils; 53 54 /** 55 * Stores and restores state for the Device and Profile owners. By definition there can be 56 * only one device owner, but there may be a profile owner for each user. 57 * 58 * <p>This class is thread safe, so individual methods can safely be called without locking. 59 * However, caller must still synchronize on their side to ensure integrity between multiple calls. 60 */ 61 class Owners { 62 private static final String TAG = "DevicePolicyManagerService"; 63 64 private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE 65 66 private static final String DEVICE_OWNER_XML_LEGACY = "device_owner.xml"; 67 68 private static final String DEVICE_OWNER_XML = "device_owner_2.xml"; 69 70 private static final String PROFILE_OWNER_XML = "profile_owner.xml"; 71 72 private static final String TAG_ROOT = "root"; 73 74 private static final String TAG_DEVICE_OWNER = "device-owner"; 75 private static final String TAG_DEVICE_INITIALIZER = "device-initializer"; 76 private static final String TAG_PROFILE_OWNER = "profile-owner"; 77 // Holds "context" for device-owner, this must not be show up before device-owner. 78 private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context"; 79 80 private static final String ATTR_NAME = "name"; 81 private static final String ATTR_PACKAGE = "package"; 82 private static final String ATTR_COMPONENT_NAME = "component"; 83 private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri"; 84 private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash"; 85 private static final String ATTR_USERID = "userId"; 86 private static final String ATTR_USER_RESTRICTIONS_MIGRATED = "userRestrictionsMigrated"; 87 88 private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; 89 90 private final UserManager mUserManager; 91 private final UserManagerInternal mUserManagerInternal; 92 private final PackageManagerInternal mPackageManagerInternal; 93 94 // Internal state for the device owner package. 95 private OwnerInfo mDeviceOwner; 96 97 private int mDeviceOwnerUserId = UserHandle.USER_NULL; 98 99 // Internal state for the profile owner packages. 100 private final ArrayMap<Integer, OwnerInfo> mProfileOwners = new ArrayMap<>(); 101 102 // Local system update policy controllable by device owner. 103 private SystemUpdatePolicy mSystemUpdatePolicy; 104 105 private final Object mLock = new Object(); 106 Owners(UserManager userManager, UserManagerInternal userManagerInternal, PackageManagerInternal packageManagerInternal)107 public Owners(UserManager userManager, 108 UserManagerInternal userManagerInternal, 109 PackageManagerInternal packageManagerInternal) { 110 mUserManager = userManager; 111 mUserManagerInternal = userManagerInternal; 112 mPackageManagerInternal = packageManagerInternal; 113 } 114 115 /** 116 * Load configuration from the disk. 117 */ load()118 void load() { 119 synchronized (mLock) { 120 // First, try to read from the legacy file. 121 final File legacy = getLegacyConfigFileWithTestOverride(); 122 123 final List<UserInfo> users = mUserManager.getUsers(true); 124 125 if (readLegacyOwnerFileLocked(legacy)) { 126 if (DEBUG) { 127 Log.d(TAG, "Legacy config file found."); 128 } 129 130 // Legacy file exists, write to new files and remove the legacy one. 131 writeDeviceOwner(); 132 for (int userId : getProfileOwnerKeys()) { 133 writeProfileOwner(userId); 134 } 135 if (DEBUG) { 136 Log.d(TAG, "Deleting legacy config file"); 137 } 138 if (!legacy.delete()) { 139 Slog.e(TAG, "Failed to remove the legacy setting file"); 140 } 141 } else { 142 // No legacy file, read from the new format files. 143 new DeviceOwnerReadWriter().readFromFileLocked(); 144 145 for (UserInfo ui : users) { 146 new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); 147 } 148 } 149 mUserManagerInternal.setDeviceManaged(hasDeviceOwner()); 150 for (UserInfo ui : users) { 151 mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id)); 152 } 153 if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) { 154 Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", 155 getDeviceOwnerUserId())); 156 } 157 pushToPackageManagerLocked(); 158 } 159 } 160 pushToPackageManagerLocked()161 private void pushToPackageManagerLocked() { 162 final SparseArray<String> po = new SparseArray<>(); 163 for (int i = mProfileOwners.size() - 1; i >= 0; i--) { 164 po.put(mProfileOwners.keyAt(i), mProfileOwners.valueAt(i).packageName); 165 } 166 mPackageManagerInternal.setDeviceAndProfileOwnerPackages( 167 mDeviceOwnerUserId, (mDeviceOwner != null ? mDeviceOwner.packageName : null), 168 po); 169 } 170 getDeviceOwnerPackageName()171 String getDeviceOwnerPackageName() { 172 synchronized (mLock) { 173 return mDeviceOwner != null ? mDeviceOwner.packageName : null; 174 } 175 } 176 getDeviceOwnerUserId()177 int getDeviceOwnerUserId() { 178 synchronized (mLock) { 179 return mDeviceOwnerUserId; 180 } 181 } 182 183 @Nullable getDeviceOwnerUserIdAndComponent()184 Pair<Integer, ComponentName> getDeviceOwnerUserIdAndComponent() { 185 synchronized (mLock) { 186 if (mDeviceOwner == null) { 187 return null; 188 } else { 189 return Pair.create(mDeviceOwnerUserId, mDeviceOwner.admin); 190 } 191 } 192 } 193 getDeviceOwnerName()194 String getDeviceOwnerName() { 195 synchronized (mLock) { 196 return mDeviceOwner != null ? mDeviceOwner.name : null; 197 } 198 } 199 getDeviceOwnerComponent()200 ComponentName getDeviceOwnerComponent() { 201 synchronized (mLock) { 202 return mDeviceOwner != null ? mDeviceOwner.admin : null; 203 } 204 } 205 getDeviceOwnerRemoteBugreportUri()206 String getDeviceOwnerRemoteBugreportUri() { 207 synchronized (mLock) { 208 return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null; 209 } 210 } 211 getDeviceOwnerRemoteBugreportHash()212 String getDeviceOwnerRemoteBugreportHash() { 213 synchronized (mLock) { 214 return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null; 215 } 216 } 217 setDeviceOwner(ComponentName admin, String ownerName, int userId)218 void setDeviceOwner(ComponentName admin, String ownerName, int userId) { 219 if (userId < 0) { 220 Slog.e(TAG, "Invalid user id for device owner user: " + userId); 221 return; 222 } 223 synchronized (mLock) { 224 // For a newly set DO, there's no need for migration. 225 setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId, 226 /* userRestrictionsMigrated =*/ true); 227 } 228 } 229 230 // Note this should be only called during migration. Normally when DO is set, 231 // userRestrictionsMigrated should always be true. setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId, boolean userRestrictionsMigrated)232 void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId, 233 boolean userRestrictionsMigrated) { 234 synchronized (mLock) { 235 mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated, 236 /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null); 237 mDeviceOwnerUserId = userId; 238 239 mUserManagerInternal.setDeviceManaged(true); 240 pushToPackageManagerLocked(); 241 } 242 } 243 clearDeviceOwner()244 void clearDeviceOwner() { 245 synchronized (mLock) { 246 mDeviceOwner = null; 247 mDeviceOwnerUserId = UserHandle.USER_NULL; 248 249 mUserManagerInternal.setDeviceManaged(false); 250 pushToPackageManagerLocked(); 251 } 252 } 253 setProfileOwner(ComponentName admin, String ownerName, int userId)254 void setProfileOwner(ComponentName admin, String ownerName, int userId) { 255 synchronized (mLock) { 256 // For a newly set PO, there's no need for migration. 257 mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, 258 /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null, 259 /* remoteBugreportHash =*/ null)); 260 mUserManagerInternal.setUserManaged(userId, true); 261 pushToPackageManagerLocked(); 262 } 263 } 264 removeProfileOwner(int userId)265 void removeProfileOwner(int userId) { 266 synchronized (mLock) { 267 mProfileOwners.remove(userId); 268 mUserManagerInternal.setUserManaged(userId, false); 269 pushToPackageManagerLocked(); 270 } 271 } 272 getProfileOwnerComponent(int userId)273 ComponentName getProfileOwnerComponent(int userId) { 274 synchronized (mLock) { 275 OwnerInfo profileOwner = mProfileOwners.get(userId); 276 return profileOwner != null ? profileOwner.admin : null; 277 } 278 } 279 getProfileOwnerName(int userId)280 String getProfileOwnerName(int userId) { 281 synchronized (mLock) { 282 OwnerInfo profileOwner = mProfileOwners.get(userId); 283 return profileOwner != null ? profileOwner.name : null; 284 } 285 } 286 getProfileOwnerPackage(int userId)287 String getProfileOwnerPackage(int userId) { 288 synchronized (mLock) { 289 OwnerInfo profileOwner = mProfileOwners.get(userId); 290 return profileOwner != null ? profileOwner.packageName : null; 291 } 292 } 293 getProfileOwnerKeys()294 Set<Integer> getProfileOwnerKeys() { 295 synchronized (mLock) { 296 return mProfileOwners.keySet(); 297 } 298 } 299 getSystemUpdatePolicy()300 SystemUpdatePolicy getSystemUpdatePolicy() { 301 synchronized (mLock) { 302 return mSystemUpdatePolicy; 303 } 304 } 305 setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy)306 void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) { 307 synchronized (mLock) { 308 mSystemUpdatePolicy = systemUpdatePolicy; 309 } 310 } 311 clearSystemUpdatePolicy()312 void clearSystemUpdatePolicy() { 313 synchronized (mLock) { 314 mSystemUpdatePolicy = null; 315 } 316 } 317 hasDeviceOwner()318 boolean hasDeviceOwner() { 319 synchronized (mLock) { 320 return mDeviceOwner != null; 321 } 322 } 323 isDeviceOwnerUserId(int userId)324 boolean isDeviceOwnerUserId(int userId) { 325 synchronized (mLock) { 326 return mDeviceOwner != null && mDeviceOwnerUserId == userId; 327 } 328 } 329 hasProfileOwner(int userId)330 boolean hasProfileOwner(int userId) { 331 synchronized (mLock) { 332 return getProfileOwnerComponent(userId) != null; 333 } 334 } 335 336 /** 337 * @return true if user restrictions need to be migrated for DO. 338 */ getDeviceOwnerUserRestrictionsNeedsMigration()339 boolean getDeviceOwnerUserRestrictionsNeedsMigration() { 340 synchronized (mLock) { 341 return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated; 342 } 343 } 344 345 /** 346 * @return true if user restrictions need to be migrated for PO. 347 */ getProfileOwnerUserRestrictionsNeedsMigration(int userId)348 boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) { 349 synchronized (mLock) { 350 OwnerInfo profileOwner = mProfileOwners.get(userId); 351 return profileOwner != null && !profileOwner.userRestrictionsMigrated; 352 } 353 } 354 355 /** Sets the user restrictions migrated flag, and also writes to the file. */ setDeviceOwnerUserRestrictionsMigrated()356 void setDeviceOwnerUserRestrictionsMigrated() { 357 synchronized (mLock) { 358 if (mDeviceOwner != null) { 359 mDeviceOwner.userRestrictionsMigrated = true; 360 } 361 writeDeviceOwner(); 362 } 363 } 364 365 /** Sets the remote bugreport uri and hash, and also writes to the file. */ setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, String remoteBugreportHash)366 void setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, 367 String remoteBugreportHash) { 368 synchronized (mLock) { 369 if (mDeviceOwner != null) { 370 mDeviceOwner.remoteBugreportUri = remoteBugreportUri; 371 mDeviceOwner.remoteBugreportHash = remoteBugreportHash; 372 } 373 writeDeviceOwner(); 374 } 375 } 376 377 /** Sets the user restrictions migrated flag, and also writes to the file. */ setProfileOwnerUserRestrictionsMigrated(int userId)378 void setProfileOwnerUserRestrictionsMigrated(int userId) { 379 synchronized (mLock) { 380 OwnerInfo profileOwner = mProfileOwners.get(userId); 381 if (profileOwner != null) { 382 profileOwner.userRestrictionsMigrated = true; 383 } 384 writeProfileOwner(userId); 385 } 386 } 387 readLegacyOwnerFileLocked(File file)388 private boolean readLegacyOwnerFileLocked(File file) { 389 if (!file.exists()) { 390 // Already migrated or the device has no owners. 391 return false; 392 } 393 try { 394 InputStream input = new AtomicFile(file).openRead(); 395 XmlPullParser parser = Xml.newPullParser(); 396 parser.setInput(input, StandardCharsets.UTF_8.name()); 397 int type; 398 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT) { 399 if (type!=XmlPullParser.START_TAG) { 400 continue; 401 } 402 403 String tag = parser.getName(); 404 if (tag.equals(TAG_DEVICE_OWNER)) { 405 String name = parser.getAttributeValue(null, ATTR_NAME); 406 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 407 mDeviceOwner = new OwnerInfo(name, packageName, 408 /* userRestrictionsMigrated =*/ false, /* remoteBugreportUri =*/ null, 409 /* remoteBugreportHash =*/ null); 410 mDeviceOwnerUserId = UserHandle.USER_SYSTEM; 411 } else if (tag.equals(TAG_DEVICE_INITIALIZER)) { 412 // Deprecated tag 413 } else if (tag.equals(TAG_PROFILE_OWNER)) { 414 String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); 415 String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME); 416 String profileOwnerComponentStr = 417 parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 418 int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID)); 419 OwnerInfo profileOwnerInfo = null; 420 if (profileOwnerComponentStr != null) { 421 ComponentName admin = ComponentName.unflattenFromString( 422 profileOwnerComponentStr); 423 if (admin != null) { 424 profileOwnerInfo = new OwnerInfo(profileOwnerName, admin, 425 /* userRestrictionsMigrated =*/ false, null, null); 426 } else { 427 // This shouldn't happen but switch from package name -> component name 428 // might have written bad device owner files. b/17652534 429 Slog.e(TAG, "Error parsing device-owner file. Bad component name " + 430 profileOwnerComponentStr); 431 } 432 } 433 if (profileOwnerInfo == null) { 434 profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName, 435 /* userRestrictionsMigrated =*/ false, 436 /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null); 437 } 438 mProfileOwners.put(userId, profileOwnerInfo); 439 } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) { 440 mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); 441 } else { 442 throw new XmlPullParserException( 443 "Unexpected tag in device owner file: " + tag); 444 } 445 } 446 input.close(); 447 } catch (XmlPullParserException|IOException e) { 448 Slog.e(TAG, "Error parsing device-owner file", e); 449 } 450 return true; 451 } 452 writeDeviceOwner()453 void writeDeviceOwner() { 454 synchronized (mLock) { 455 if (DEBUG) { 456 Log.d(TAG, "Writing to device owner file"); 457 } 458 new DeviceOwnerReadWriter().writeToFileLocked(); 459 } 460 } 461 writeProfileOwner(int userId)462 void writeProfileOwner(int userId) { 463 synchronized (mLock) { 464 if (DEBUG) { 465 Log.d(TAG, "Writing to profile owner file for user " + userId); 466 } 467 new ProfileOwnerReadWriter(userId).writeToFileLocked(); 468 } 469 } 470 471 private abstract static class FileReadWriter { 472 private final File mFile; 473 FileReadWriter(File file)474 protected FileReadWriter(File file) { 475 mFile = file; 476 } 477 shouldWrite()478 abstract boolean shouldWrite(); 479 writeToFileLocked()480 void writeToFileLocked() { 481 if (!shouldWrite()) { 482 if (DEBUG) { 483 Log.d(TAG, "No need to write to " + mFile); 484 } 485 // No contents, remove the file. 486 if (mFile.exists()) { 487 if (DEBUG) { 488 Log.d(TAG, "Deleting existing " + mFile); 489 } 490 if (!mFile.delete()) { 491 Slog.e(TAG, "Failed to remove " + mFile.getPath()); 492 } 493 } 494 return; 495 } 496 if (DEBUG) { 497 Log.d(TAG, "Writing to " + mFile); 498 } 499 500 final AtomicFile f = new AtomicFile(mFile); 501 FileOutputStream outputStream = null; 502 try { 503 outputStream = f.startWrite(); 504 final XmlSerializer out = new FastXmlSerializer(); 505 out.setOutput(outputStream, StandardCharsets.UTF_8.name()); 506 507 // Root tag 508 out.startDocument(null, true); 509 out.startTag(null, TAG_ROOT); 510 511 // Actual content 512 writeInner(out); 513 514 // Close root 515 out.endTag(null, TAG_ROOT); 516 out.endDocument(); 517 out.flush(); 518 519 // Commit the content. 520 f.finishWrite(outputStream); 521 outputStream = null; 522 523 } catch (IOException e) { 524 Slog.e(TAG, "Exception when writing", e); 525 if (outputStream != null) { 526 f.failWrite(outputStream); 527 } 528 } 529 } 530 readFromFileLocked()531 void readFromFileLocked() { 532 if (!mFile.exists()) { 533 if (DEBUG) { 534 Log.d(TAG, "" + mFile + " doesn't exist"); 535 } 536 return; 537 } 538 if (DEBUG) { 539 Log.d(TAG, "Reading from " + mFile); 540 } 541 final AtomicFile f = new AtomicFile(mFile); 542 InputStream input = null; 543 try { 544 input = f.openRead(); 545 final XmlPullParser parser = Xml.newPullParser(); 546 parser.setInput(input, StandardCharsets.UTF_8.name()); 547 548 int type; 549 int depth = 0; 550 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 551 switch (type) { 552 case XmlPullParser.START_TAG: 553 depth++; 554 break; 555 case XmlPullParser.END_TAG: 556 depth--; 557 // fallthrough 558 default: 559 continue; 560 } 561 // Check the root tag 562 final String tag = parser.getName(); 563 if (depth == 1) { 564 if (!TAG_ROOT.equals(tag)) { 565 Slog.e(TAG, "Invalid root tag: " + tag); 566 return; 567 } 568 continue; 569 } 570 // readInner() will only see START_TAG at depth >= 2. 571 if (!readInner(parser, depth, tag)) { 572 return; // Error 573 } 574 } 575 } catch (XmlPullParserException | IOException e) { 576 Slog.e(TAG, "Error parsing device-owner file", e); 577 } finally { 578 IoUtils.closeQuietly(input); 579 } 580 } 581 writeInner(XmlSerializer out)582 abstract void writeInner(XmlSerializer out) throws IOException; 583 readInner(XmlPullParser parser, int depth, String tag)584 abstract boolean readInner(XmlPullParser parser, int depth, String tag); 585 } 586 587 private class DeviceOwnerReadWriter extends FileReadWriter { 588 DeviceOwnerReadWriter()589 protected DeviceOwnerReadWriter() { 590 super(getDeviceOwnerFileWithTestOverride()); 591 } 592 593 @Override shouldWrite()594 boolean shouldWrite() { 595 return (mDeviceOwner != null) || (mSystemUpdatePolicy != null); 596 } 597 598 @Override writeInner(XmlSerializer out)599 void writeInner(XmlSerializer out) throws IOException { 600 if (mDeviceOwner != null) { 601 mDeviceOwner.writeToXml(out, TAG_DEVICE_OWNER); 602 out.startTag(null, TAG_DEVICE_OWNER_CONTEXT); 603 out.attribute(null, ATTR_USERID, String.valueOf(mDeviceOwnerUserId)); 604 out.endTag(null, TAG_DEVICE_OWNER_CONTEXT); 605 } 606 607 if (mSystemUpdatePolicy != null) { 608 out.startTag(null, TAG_SYSTEM_UPDATE_POLICY); 609 mSystemUpdatePolicy.saveToXml(out); 610 out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); 611 } 612 } 613 614 @Override readInner(XmlPullParser parser, int depth, String tag)615 boolean readInner(XmlPullParser parser, int depth, String tag) { 616 if (depth > 2) { 617 return true; // Ignore 618 } 619 switch (tag) { 620 case TAG_DEVICE_OWNER: 621 mDeviceOwner = OwnerInfo.readFromXml(parser); 622 mDeviceOwnerUserId = UserHandle.USER_SYSTEM; // Set default 623 break; 624 case TAG_DEVICE_OWNER_CONTEXT: { 625 final String userIdString = 626 parser.getAttributeValue(null, ATTR_USERID); 627 try { 628 mDeviceOwnerUserId = Integer.parseInt(userIdString); 629 } catch (NumberFormatException e) { 630 Slog.e(TAG, "Error parsing user-id " + userIdString); 631 } 632 break; 633 } 634 case TAG_DEVICE_INITIALIZER: 635 // Deprecated tag 636 break; 637 case TAG_SYSTEM_UPDATE_POLICY: 638 mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); 639 break; 640 default: 641 Slog.e(TAG, "Unexpected tag: " + tag); 642 return false; 643 644 } 645 return true; 646 } 647 } 648 649 private class ProfileOwnerReadWriter extends FileReadWriter { 650 private final int mUserId; 651 ProfileOwnerReadWriter(int userId)652 ProfileOwnerReadWriter(int userId) { 653 super(getProfileOwnerFileWithTestOverride(userId)); 654 mUserId = userId; 655 } 656 657 @Override shouldWrite()658 boolean shouldWrite() { 659 return mProfileOwners.get(mUserId) != null; 660 } 661 662 @Override writeInner(XmlSerializer out)663 void writeInner(XmlSerializer out) throws IOException { 664 final OwnerInfo profileOwner = mProfileOwners.get(mUserId); 665 if (profileOwner != null) { 666 profileOwner.writeToXml(out, TAG_PROFILE_OWNER); 667 } 668 } 669 670 @Override readInner(XmlPullParser parser, int depth, String tag)671 boolean readInner(XmlPullParser parser, int depth, String tag) { 672 if (depth > 2) { 673 return true; // Ignore 674 } 675 switch (tag) { 676 case TAG_PROFILE_OWNER: 677 mProfileOwners.put(mUserId, OwnerInfo.readFromXml(parser)); 678 break; 679 default: 680 Slog.e(TAG, "Unexpected tag: " + tag); 681 return false; 682 683 } 684 return true; 685 } 686 } 687 688 static class OwnerInfo { 689 public final String name; 690 public final String packageName; 691 public final ComponentName admin; 692 public boolean userRestrictionsMigrated; 693 public String remoteBugreportUri; 694 public String remoteBugreportHash; 695 OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated, String remoteBugreportUri, String remoteBugreportHash)696 public OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated, 697 String remoteBugreportUri, String remoteBugreportHash) { 698 this.name = name; 699 this.packageName = packageName; 700 this.admin = new ComponentName(packageName, ""); 701 this.userRestrictionsMigrated = userRestrictionsMigrated; 702 this.remoteBugreportUri = remoteBugreportUri; 703 this.remoteBugreportHash = remoteBugreportHash; 704 } 705 OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated, String remoteBugreportUri, String remoteBugreportHash)706 public OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated, 707 String remoteBugreportUri, String remoteBugreportHash) { 708 this.name = name; 709 this.admin = admin; 710 this.packageName = admin.getPackageName(); 711 this.userRestrictionsMigrated = userRestrictionsMigrated; 712 this.remoteBugreportUri = remoteBugreportUri; 713 this.remoteBugreportHash = remoteBugreportHash; 714 } 715 writeToXml(XmlSerializer out, String tag)716 public void writeToXml(XmlSerializer out, String tag) throws IOException { 717 out.startTag(null, tag); 718 out.attribute(null, ATTR_PACKAGE, packageName); 719 if (name != null) { 720 out.attribute(null, ATTR_NAME, name); 721 } 722 if (admin != null) { 723 out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString()); 724 } 725 out.attribute(null, ATTR_USER_RESTRICTIONS_MIGRATED, 726 String.valueOf(userRestrictionsMigrated)); 727 if (remoteBugreportUri != null) { 728 out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri); 729 } 730 if (remoteBugreportHash != null) { 731 out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash); 732 } 733 out.endTag(null, tag); 734 } 735 readFromXml(XmlPullParser parser)736 public static OwnerInfo readFromXml(XmlPullParser parser) { 737 final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 738 final String name = parser.getAttributeValue(null, ATTR_NAME); 739 final String componentName = 740 parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 741 final String userRestrictionsMigratedStr = 742 parser.getAttributeValue(null, ATTR_USER_RESTRICTIONS_MIGRATED); 743 final boolean userRestrictionsMigrated = 744 ("true".equals(userRestrictionsMigratedStr)); 745 final String remoteBugreportUri = parser.getAttributeValue(null, 746 ATTR_REMOTE_BUGREPORT_URI); 747 final String remoteBugreportHash = parser.getAttributeValue(null, 748 ATTR_REMOTE_BUGREPORT_HASH); 749 750 // Has component name? If so, return [name, component] 751 if (componentName != null) { 752 final ComponentName admin = ComponentName.unflattenFromString(componentName); 753 if (admin != null) { 754 return new OwnerInfo(name, admin, userRestrictionsMigrated, 755 remoteBugreportUri, remoteBugreportHash); 756 } else { 757 // This shouldn't happen but switch from package name -> component name 758 // might have written bad device owner files. b/17652534 759 Slog.e(TAG, "Error parsing owner file. Bad component name " + 760 componentName); 761 } 762 } 763 764 // Else, build with [name, package] 765 return new OwnerInfo(name, packageName, userRestrictionsMigrated, remoteBugreportUri, 766 remoteBugreportHash); 767 } 768 dump(String prefix, PrintWriter pw)769 public void dump(String prefix, PrintWriter pw) { 770 pw.println(prefix + "admin=" + admin); 771 pw.println(prefix + "name=" + name); 772 pw.println(prefix + "package=" + packageName); 773 } 774 } 775 dump(String prefix, PrintWriter pw)776 public void dump(String prefix, PrintWriter pw) { 777 boolean needBlank = false; 778 if (mDeviceOwner != null) { 779 pw.println(prefix + "Device Owner: "); 780 mDeviceOwner.dump(prefix + " ", pw); 781 pw.println(prefix + " User ID: " + mDeviceOwnerUserId); 782 needBlank = true; 783 } 784 if (mSystemUpdatePolicy != null) { 785 if (needBlank) { 786 needBlank = false; 787 pw.println(); 788 } 789 pw.println(prefix + "System Update Policy: " + mSystemUpdatePolicy); 790 needBlank = true; 791 } 792 if (mProfileOwners != null) { 793 for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) { 794 if (needBlank) { 795 needBlank = false; 796 pw.println(); 797 } 798 pw.println(prefix + "Profile Owner (User " + entry.getKey() + "): "); 799 entry.getValue().dump(prefix + " ", pw); 800 needBlank = true; 801 } 802 } 803 } 804 getLegacyConfigFileWithTestOverride()805 File getLegacyConfigFileWithTestOverride() { 806 return new File(Environment.getDataSystemDirectory(), DEVICE_OWNER_XML_LEGACY); 807 } 808 getDeviceOwnerFileWithTestOverride()809 File getDeviceOwnerFileWithTestOverride() { 810 return new File(Environment.getDataSystemDirectory(), DEVICE_OWNER_XML); 811 } 812 getProfileOwnerFileWithTestOverride(int userId)813 File getProfileOwnerFileWithTestOverride(int userId) { 814 return new File(Environment.getUserSystemDirectory(userId), PROFILE_OWNER_XML); 815 } 816 } 817