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.AppOpsManagerInternal; 21 import android.app.admin.SystemUpdateInfo; 22 import android.app.admin.SystemUpdatePolicy; 23 import android.content.ComponentName; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManagerInternal; 26 import android.content.pm.UserInfo; 27 import android.os.Binder; 28 import android.os.Environment; 29 import android.os.UserHandle; 30 import android.os.UserManager; 31 import android.os.UserManagerInternal; 32 import android.util.ArrayMap; 33 import android.util.AtomicFile; 34 import android.util.Log; 35 import android.util.Pair; 36 import android.util.Slog; 37 import android.util.SparseArray; 38 import android.util.SparseIntArray; 39 import android.util.Xml; 40 41 import com.android.internal.annotations.VisibleForTesting; 42 import com.android.internal.util.FastXmlSerializer; 43 import com.android.server.LocalServices; 44 45 import org.xmlpull.v1.XmlPullParser; 46 import org.xmlpull.v1.XmlPullParserException; 47 import org.xmlpull.v1.XmlSerializer; 48 49 import java.io.File; 50 import java.io.FileOutputStream; 51 import java.io.IOException; 52 import java.io.InputStream; 53 import java.io.PrintWriter; 54 import java.nio.charset.StandardCharsets; 55 import java.time.LocalDate; 56 import java.util.List; 57 import java.util.Map; 58 import java.util.Objects; 59 import java.util.Set; 60 61 import libcore.io.IoUtils; 62 63 /** 64 * Stores and restores state for the Device and Profile owners and related device-wide information. 65 * By definition there can be only one device owner, but there may be a profile owner for each user. 66 * 67 * <p>This class is thread safe, so individual methods can safely be called without locking. 68 * However, caller must still synchronize on their side to ensure integrity between multiple calls. 69 */ 70 class Owners { 71 private static final String TAG = "DevicePolicyManagerService"; 72 73 private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE 74 75 private static final String DEVICE_OWNER_XML_LEGACY = "device_owner.xml"; 76 77 // XML storing device owner info, system update policy and pending OTA update information. 78 private static final String DEVICE_OWNER_XML = "device_owner_2.xml"; 79 80 private static final String PROFILE_OWNER_XML = "profile_owner.xml"; 81 82 private static final String TAG_ROOT = "root"; 83 84 private static final String TAG_DEVICE_OWNER = "device-owner"; 85 private static final String TAG_DEVICE_INITIALIZER = "device-initializer"; 86 private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; 87 private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record"; 88 private static final String TAG_PENDING_OTA_INFO = "pending-ota-info"; 89 private static final String TAG_PROFILE_OWNER = "profile-owner"; 90 // Holds "context" for device-owner, this must not be show up before device-owner. 91 private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context"; 92 93 private static final String ATTR_NAME = "name"; 94 private static final String ATTR_PACKAGE = "package"; 95 private static final String ATTR_COMPONENT_NAME = "component"; 96 private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri"; 97 private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash"; 98 private static final String ATTR_USERID = "userId"; 99 private static final String ATTR_USER_RESTRICTIONS_MIGRATED = "userRestrictionsMigrated"; 100 private static final String ATTR_FREEZE_RECORD_START = "start"; 101 private static final String ATTR_FREEZE_RECORD_END = "end"; 102 103 private final UserManager mUserManager; 104 private final UserManagerInternal mUserManagerInternal; 105 private final PackageManagerInternal mPackageManagerInternal; 106 107 private boolean mSystemReady; 108 109 // Internal state for the device owner package. 110 private OwnerInfo mDeviceOwner; 111 112 private int mDeviceOwnerUserId = UserHandle.USER_NULL; 113 114 // Internal state for the profile owner packages. 115 private final ArrayMap<Integer, OwnerInfo> mProfileOwners = new ArrayMap<>(); 116 117 // Local system update policy controllable by device owner. 118 private SystemUpdatePolicy mSystemUpdatePolicy; 119 private LocalDate mSystemUpdateFreezeStart; 120 private LocalDate mSystemUpdateFreezeEnd; 121 122 // Pending OTA info if there is one. 123 @Nullable 124 private SystemUpdateInfo mSystemUpdateInfo; 125 126 private final Object mLock = new Object(); 127 private final Injector mInjector; 128 Owners(UserManager userManager, UserManagerInternal userManagerInternal, PackageManagerInternal packageManagerInternal)129 public Owners(UserManager userManager, 130 UserManagerInternal userManagerInternal, 131 PackageManagerInternal packageManagerInternal) { 132 this(userManager, userManagerInternal, packageManagerInternal, new Injector()); 133 } 134 135 @VisibleForTesting Owners(UserManager userManager, UserManagerInternal userManagerInternal, PackageManagerInternal packageManagerInternal, Injector injector)136 Owners(UserManager userManager, 137 UserManagerInternal userManagerInternal, 138 PackageManagerInternal packageManagerInternal, 139 Injector injector) { 140 mUserManager = userManager; 141 mUserManagerInternal = userManagerInternal; 142 mPackageManagerInternal = packageManagerInternal; 143 mInjector = injector; 144 } 145 146 /** 147 * Load configuration from the disk. 148 */ load()149 void load() { 150 synchronized (mLock) { 151 // First, try to read from the legacy file. 152 final File legacy = getLegacyConfigFile(); 153 154 final List<UserInfo> users = mUserManager.getUsers(true); 155 156 if (readLegacyOwnerFileLocked(legacy)) { 157 if (DEBUG) { 158 Log.d(TAG, "Legacy config file found."); 159 } 160 161 // Legacy file exists, write to new files and remove the legacy one. 162 writeDeviceOwner(); 163 for (int userId : getProfileOwnerKeys()) { 164 writeProfileOwner(userId); 165 } 166 if (DEBUG) { 167 Log.d(TAG, "Deleting legacy config file"); 168 } 169 if (!legacy.delete()) { 170 Slog.e(TAG, "Failed to remove the legacy setting file"); 171 } 172 } else { 173 // No legacy file, read from the new format files. 174 new DeviceOwnerReadWriter().readFromFileLocked(); 175 176 for (UserInfo ui : users) { 177 new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); 178 } 179 } 180 mUserManagerInternal.setDeviceManaged(hasDeviceOwner()); 181 for (UserInfo ui : users) { 182 mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id)); 183 } 184 if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) { 185 Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", 186 getDeviceOwnerUserId())); 187 } 188 pushToPackageManagerLocked(); 189 pushToAppOpsLocked(); 190 } 191 } 192 pushToPackageManagerLocked()193 private void pushToPackageManagerLocked() { 194 final SparseArray<String> po = new SparseArray<>(); 195 for (int i = mProfileOwners.size() - 1; i >= 0; i--) { 196 po.put(mProfileOwners.keyAt(i), mProfileOwners.valueAt(i).packageName); 197 } 198 mPackageManagerInternal.setDeviceAndProfileOwnerPackages( 199 mDeviceOwnerUserId, (mDeviceOwner != null ? mDeviceOwner.packageName : null), 200 po); 201 } 202 getDeviceOwnerPackageName()203 String getDeviceOwnerPackageName() { 204 synchronized (mLock) { 205 return mDeviceOwner != null ? mDeviceOwner.packageName : null; 206 } 207 } 208 getDeviceOwnerUserId()209 int getDeviceOwnerUserId() { 210 synchronized (mLock) { 211 return mDeviceOwnerUserId; 212 } 213 } 214 215 @Nullable getDeviceOwnerUserIdAndComponent()216 Pair<Integer, ComponentName> getDeviceOwnerUserIdAndComponent() { 217 synchronized (mLock) { 218 if (mDeviceOwner == null) { 219 return null; 220 } else { 221 return Pair.create(mDeviceOwnerUserId, mDeviceOwner.admin); 222 } 223 } 224 } 225 getDeviceOwnerName()226 String getDeviceOwnerName() { 227 synchronized (mLock) { 228 return mDeviceOwner != null ? mDeviceOwner.name : null; 229 } 230 } 231 getDeviceOwnerComponent()232 ComponentName getDeviceOwnerComponent() { 233 synchronized (mLock) { 234 return mDeviceOwner != null ? mDeviceOwner.admin : null; 235 } 236 } 237 getDeviceOwnerRemoteBugreportUri()238 String getDeviceOwnerRemoteBugreportUri() { 239 synchronized (mLock) { 240 return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null; 241 } 242 } 243 getDeviceOwnerRemoteBugreportHash()244 String getDeviceOwnerRemoteBugreportHash() { 245 synchronized (mLock) { 246 return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null; 247 } 248 } 249 setDeviceOwner(ComponentName admin, String ownerName, int userId)250 void setDeviceOwner(ComponentName admin, String ownerName, int userId) { 251 if (userId < 0) { 252 Slog.e(TAG, "Invalid user id for device owner user: " + userId); 253 return; 254 } 255 synchronized (mLock) { 256 // For a newly set DO, there's no need for migration. 257 setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId, 258 /* userRestrictionsMigrated =*/ true); 259 } 260 } 261 262 // Note this should be only called during migration. Normally when DO is set, 263 // userRestrictionsMigrated should always be true. setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId, boolean userRestrictionsMigrated)264 void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId, 265 boolean userRestrictionsMigrated) { 266 synchronized (mLock) { 267 mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated, 268 /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null); 269 mDeviceOwnerUserId = userId; 270 271 mUserManagerInternal.setDeviceManaged(true); 272 pushToPackageManagerLocked(); 273 pushToAppOpsLocked(); 274 } 275 } 276 clearDeviceOwner()277 void clearDeviceOwner() { 278 synchronized (mLock) { 279 mDeviceOwner = null; 280 mDeviceOwnerUserId = UserHandle.USER_NULL; 281 282 mUserManagerInternal.setDeviceManaged(false); 283 pushToPackageManagerLocked(); 284 pushToAppOpsLocked(); 285 } 286 } 287 setProfileOwner(ComponentName admin, String ownerName, int userId)288 void setProfileOwner(ComponentName admin, String ownerName, int userId) { 289 synchronized (mLock) { 290 // For a newly set PO, there's no need for migration. 291 mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, 292 /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null, 293 /* remoteBugreportHash =*/ null)); 294 mUserManagerInternal.setUserManaged(userId, true); 295 pushToPackageManagerLocked(); 296 pushToAppOpsLocked(); 297 } 298 } 299 removeProfileOwner(int userId)300 void removeProfileOwner(int userId) { 301 synchronized (mLock) { 302 mProfileOwners.remove(userId); 303 mUserManagerInternal.setUserManaged(userId, false); 304 pushToPackageManagerLocked(); 305 pushToAppOpsLocked(); 306 } 307 } 308 transferProfileOwner(ComponentName target, int userId)309 void transferProfileOwner(ComponentName target, int userId) { 310 synchronized (mLock) { 311 final OwnerInfo ownerInfo = mProfileOwners.get(userId); 312 final OwnerInfo newOwnerInfo = new OwnerInfo(target.getPackageName(), target, 313 ownerInfo.userRestrictionsMigrated, ownerInfo.remoteBugreportUri, 314 ownerInfo.remoteBugreportHash); 315 mProfileOwners.put(userId, newOwnerInfo); 316 pushToPackageManagerLocked(); 317 pushToAppOpsLocked(); 318 } 319 } 320 transferDeviceOwnership(ComponentName target)321 void transferDeviceOwnership(ComponentName target) { 322 synchronized (mLock) { 323 // We don't set a name because it's not used anyway. 324 // See DevicePolicyManagerService#getDeviceOwnerName 325 mDeviceOwner = new OwnerInfo(null, target, 326 mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri, 327 mDeviceOwner.remoteBugreportHash); 328 pushToPackageManagerLocked(); 329 pushToAppOpsLocked(); 330 } 331 } 332 getProfileOwnerComponent(int userId)333 ComponentName getProfileOwnerComponent(int userId) { 334 synchronized (mLock) { 335 OwnerInfo profileOwner = mProfileOwners.get(userId); 336 return profileOwner != null ? profileOwner.admin : null; 337 } 338 } 339 getProfileOwnerName(int userId)340 String getProfileOwnerName(int userId) { 341 synchronized (mLock) { 342 OwnerInfo profileOwner = mProfileOwners.get(userId); 343 return profileOwner != null ? profileOwner.name : null; 344 } 345 } 346 getProfileOwnerPackage(int userId)347 String getProfileOwnerPackage(int userId) { 348 synchronized (mLock) { 349 OwnerInfo profileOwner = mProfileOwners.get(userId); 350 return profileOwner != null ? profileOwner.packageName : null; 351 } 352 } 353 getProfileOwnerKeys()354 Set<Integer> getProfileOwnerKeys() { 355 synchronized (mLock) { 356 return mProfileOwners.keySet(); 357 } 358 } 359 getSystemUpdatePolicy()360 SystemUpdatePolicy getSystemUpdatePolicy() { 361 synchronized (mLock) { 362 return mSystemUpdatePolicy; 363 } 364 } 365 setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy)366 void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) { 367 synchronized (mLock) { 368 mSystemUpdatePolicy = systemUpdatePolicy; 369 } 370 } 371 clearSystemUpdatePolicy()372 void clearSystemUpdatePolicy() { 373 synchronized (mLock) { 374 mSystemUpdatePolicy = null; 375 } 376 } 377 getSystemUpdateFreezePeriodRecord()378 Pair<LocalDate, LocalDate> getSystemUpdateFreezePeriodRecord() { 379 synchronized (mLock) { 380 return new Pair<>(mSystemUpdateFreezeStart, mSystemUpdateFreezeEnd); 381 } 382 } 383 getSystemUpdateFreezePeriodRecordAsString()384 String getSystemUpdateFreezePeriodRecordAsString() { 385 StringBuilder freezePeriodRecord = new StringBuilder(); 386 freezePeriodRecord.append("start: "); 387 if (mSystemUpdateFreezeStart != null) { 388 freezePeriodRecord.append(mSystemUpdateFreezeStart.toString()); 389 } else { 390 freezePeriodRecord.append("null"); 391 } 392 freezePeriodRecord.append("; end: "); 393 if (mSystemUpdateFreezeEnd != null) { 394 freezePeriodRecord.append(mSystemUpdateFreezeEnd.toString()); 395 } else { 396 freezePeriodRecord.append("null"); 397 } 398 return freezePeriodRecord.toString(); 399 } 400 401 /** 402 * Returns {@code true} if the freeze period record is changed, {@code false} otherwise. 403 */ setSystemUpdateFreezePeriodRecord(LocalDate start, LocalDate end)404 boolean setSystemUpdateFreezePeriodRecord(LocalDate start, LocalDate end) { 405 boolean changed = false; 406 synchronized (mLock) { 407 if (!Objects.equals(mSystemUpdateFreezeStart, start)) { 408 mSystemUpdateFreezeStart = start; 409 changed = true; 410 } 411 if (!Objects.equals(mSystemUpdateFreezeEnd, end)) { 412 mSystemUpdateFreezeEnd = end; 413 changed = true; 414 } 415 } 416 return changed; 417 } 418 hasDeviceOwner()419 boolean hasDeviceOwner() { 420 synchronized (mLock) { 421 return mDeviceOwner != null; 422 } 423 } 424 isDeviceOwnerUserId(int userId)425 boolean isDeviceOwnerUserId(int userId) { 426 synchronized (mLock) { 427 return mDeviceOwner != null && mDeviceOwnerUserId == userId; 428 } 429 } 430 hasProfileOwner(int userId)431 boolean hasProfileOwner(int userId) { 432 synchronized (mLock) { 433 return getProfileOwnerComponent(userId) != null; 434 } 435 } 436 437 /** 438 * @return true if user restrictions need to be migrated for DO. 439 */ getDeviceOwnerUserRestrictionsNeedsMigration()440 boolean getDeviceOwnerUserRestrictionsNeedsMigration() { 441 synchronized (mLock) { 442 return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated; 443 } 444 } 445 446 /** 447 * @return true if user restrictions need to be migrated for PO. 448 */ getProfileOwnerUserRestrictionsNeedsMigration(int userId)449 boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) { 450 synchronized (mLock) { 451 OwnerInfo profileOwner = mProfileOwners.get(userId); 452 return profileOwner != null && !profileOwner.userRestrictionsMigrated; 453 } 454 } 455 456 /** Sets the user restrictions migrated flag, and also writes to the file. */ setDeviceOwnerUserRestrictionsMigrated()457 void setDeviceOwnerUserRestrictionsMigrated() { 458 synchronized (mLock) { 459 if (mDeviceOwner != null) { 460 mDeviceOwner.userRestrictionsMigrated = true; 461 } 462 writeDeviceOwner(); 463 } 464 } 465 466 /** Sets the remote bugreport uri and hash, and also writes to the file. */ setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, String remoteBugreportHash)467 void setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, 468 String remoteBugreportHash) { 469 synchronized (mLock) { 470 if (mDeviceOwner != null) { 471 mDeviceOwner.remoteBugreportUri = remoteBugreportUri; 472 mDeviceOwner.remoteBugreportHash = remoteBugreportHash; 473 } 474 writeDeviceOwner(); 475 } 476 } 477 478 /** Sets the user restrictions migrated flag, and also writes to the file. */ setProfileOwnerUserRestrictionsMigrated(int userId)479 void setProfileOwnerUserRestrictionsMigrated(int userId) { 480 synchronized (mLock) { 481 OwnerInfo profileOwner = mProfileOwners.get(userId); 482 if (profileOwner != null) { 483 profileOwner.userRestrictionsMigrated = true; 484 } 485 writeProfileOwner(userId); 486 } 487 } 488 readLegacyOwnerFileLocked(File file)489 private boolean readLegacyOwnerFileLocked(File file) { 490 if (!file.exists()) { 491 // Already migrated or the device has no owners. 492 return false; 493 } 494 try { 495 InputStream input = new AtomicFile(file).openRead(); 496 XmlPullParser parser = Xml.newPullParser(); 497 parser.setInput(input, StandardCharsets.UTF_8.name()); 498 int type; 499 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT) { 500 if (type!=XmlPullParser.START_TAG) { 501 continue; 502 } 503 504 String tag = parser.getName(); 505 if (tag.equals(TAG_DEVICE_OWNER)) { 506 String name = parser.getAttributeValue(null, ATTR_NAME); 507 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 508 mDeviceOwner = new OwnerInfo(name, packageName, 509 /* userRestrictionsMigrated =*/ false, /* remoteBugreportUri =*/ null, 510 /* remoteBugreportHash =*/ null); 511 mDeviceOwnerUserId = UserHandle.USER_SYSTEM; 512 } else if (tag.equals(TAG_DEVICE_INITIALIZER)) { 513 // Deprecated tag 514 } else if (tag.equals(TAG_PROFILE_OWNER)) { 515 String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); 516 String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME); 517 String profileOwnerComponentStr = 518 parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 519 int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID)); 520 OwnerInfo profileOwnerInfo = null; 521 if (profileOwnerComponentStr != null) { 522 ComponentName admin = ComponentName.unflattenFromString( 523 profileOwnerComponentStr); 524 if (admin != null) { 525 profileOwnerInfo = new OwnerInfo(profileOwnerName, admin, 526 /* userRestrictionsMigrated =*/ false, null, null); 527 } else { 528 // This shouldn't happen but switch from package name -> component name 529 // might have written bad device owner files. b/17652534 530 Slog.e(TAG, "Error parsing device-owner file. Bad component name " + 531 profileOwnerComponentStr); 532 } 533 } 534 if (profileOwnerInfo == null) { 535 profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName, 536 /* userRestrictionsMigrated =*/ false, 537 /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null); 538 } 539 mProfileOwners.put(userId, profileOwnerInfo); 540 } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) { 541 mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); 542 } else { 543 throw new XmlPullParserException( 544 "Unexpected tag in device owner file: " + tag); 545 } 546 } 547 input.close(); 548 } catch (XmlPullParserException|IOException e) { 549 Slog.e(TAG, "Error parsing device-owner file", e); 550 } 551 return true; 552 } 553 writeDeviceOwner()554 void writeDeviceOwner() { 555 synchronized (mLock) { 556 if (DEBUG) { 557 Log.d(TAG, "Writing to device owner file"); 558 } 559 new DeviceOwnerReadWriter().writeToFileLocked(); 560 } 561 } 562 writeProfileOwner(int userId)563 void writeProfileOwner(int userId) { 564 synchronized (mLock) { 565 if (DEBUG) { 566 Log.d(TAG, "Writing to profile owner file for user " + userId); 567 } 568 new ProfileOwnerReadWriter(userId).writeToFileLocked(); 569 } 570 } 571 572 /** 573 * Saves the given {@link SystemUpdateInfo} if it is different from the existing one, or if 574 * none exists. 575 * 576 * @return Whether the saved system update information has changed. 577 */ saveSystemUpdateInfo(@ullable SystemUpdateInfo newInfo)578 boolean saveSystemUpdateInfo(@Nullable SystemUpdateInfo newInfo) { 579 synchronized (mLock) { 580 // Check if we already have the same update information. 581 if (Objects.equals(newInfo, mSystemUpdateInfo)) { 582 return false; 583 } 584 585 mSystemUpdateInfo = newInfo; 586 new DeviceOwnerReadWriter().writeToFileLocked(); 587 return true; 588 } 589 } 590 591 @Nullable getSystemUpdateInfo()592 public SystemUpdateInfo getSystemUpdateInfo() { 593 synchronized (mLock) { 594 return mSystemUpdateInfo; 595 } 596 } 597 pushToAppOpsLocked()598 void pushToAppOpsLocked() { 599 if (!mSystemReady) { 600 return; 601 } 602 final long ident = Binder.clearCallingIdentity(); 603 try { 604 final SparseIntArray owners = new SparseIntArray(); 605 if (mDeviceOwner != null) { 606 final int uid = mPackageManagerInternal.getPackageUid(mDeviceOwner.packageName, 607 PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, 608 mDeviceOwnerUserId); 609 if (uid >= 0) { 610 owners.put(mDeviceOwnerUserId, uid); 611 } 612 } 613 if (mProfileOwners != null) { 614 for (int poi = mProfileOwners.size() - 1; poi >= 0; poi--) { 615 final int uid = mPackageManagerInternal.getPackageUid( 616 mProfileOwners.valueAt(poi).packageName, 617 PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, 618 mProfileOwners.keyAt(poi)); 619 if (uid >= 0) { 620 owners.put(mProfileOwners.keyAt(poi), uid); 621 } 622 } 623 } 624 AppOpsManagerInternal appops = LocalServices.getService(AppOpsManagerInternal.class); 625 if (appops != null) { 626 appops.setDeviceAndProfileOwners(owners.size() > 0 ? owners : null); 627 } 628 } finally { 629 Binder.restoreCallingIdentity(ident); 630 } 631 } 632 systemReady()633 public void systemReady() { 634 synchronized (mLock) { 635 mSystemReady = true; 636 pushToAppOpsLocked(); 637 } 638 } 639 640 private abstract static class FileReadWriter { 641 private final File mFile; 642 FileReadWriter(File file)643 protected FileReadWriter(File file) { 644 mFile = file; 645 } 646 shouldWrite()647 abstract boolean shouldWrite(); 648 writeToFileLocked()649 void writeToFileLocked() { 650 if (!shouldWrite()) { 651 if (DEBUG) { 652 Log.d(TAG, "No need to write to " + mFile); 653 } 654 // No contents, remove the file. 655 if (mFile.exists()) { 656 if (DEBUG) { 657 Log.d(TAG, "Deleting existing " + mFile); 658 } 659 if (!mFile.delete()) { 660 Slog.e(TAG, "Failed to remove " + mFile.getPath()); 661 } 662 } 663 return; 664 } 665 if (DEBUG) { 666 Log.d(TAG, "Writing to " + mFile); 667 } 668 669 final AtomicFile f = new AtomicFile(mFile); 670 FileOutputStream outputStream = null; 671 try { 672 outputStream = f.startWrite(); 673 final XmlSerializer out = new FastXmlSerializer(); 674 out.setOutput(outputStream, StandardCharsets.UTF_8.name()); 675 676 // Root tag 677 out.startDocument(null, true); 678 out.startTag(null, TAG_ROOT); 679 680 // Actual content 681 writeInner(out); 682 683 // Close root 684 out.endTag(null, TAG_ROOT); 685 out.endDocument(); 686 out.flush(); 687 688 // Commit the content. 689 f.finishWrite(outputStream); 690 outputStream = null; 691 692 } catch (IOException e) { 693 Slog.e(TAG, "Exception when writing", e); 694 if (outputStream != null) { 695 f.failWrite(outputStream); 696 } 697 } 698 } 699 readFromFileLocked()700 void readFromFileLocked() { 701 if (!mFile.exists()) { 702 if (DEBUG) { 703 Log.d(TAG, "" + mFile + " doesn't exist"); 704 } 705 return; 706 } 707 if (DEBUG) { 708 Log.d(TAG, "Reading from " + mFile); 709 } 710 final AtomicFile f = new AtomicFile(mFile); 711 InputStream input = null; 712 try { 713 input = f.openRead(); 714 final XmlPullParser parser = Xml.newPullParser(); 715 parser.setInput(input, StandardCharsets.UTF_8.name()); 716 717 int type; 718 int depth = 0; 719 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 720 switch (type) { 721 case XmlPullParser.START_TAG: 722 depth++; 723 break; 724 case XmlPullParser.END_TAG: 725 depth--; 726 // fallthrough 727 default: 728 continue; 729 } 730 // Check the root tag 731 final String tag = parser.getName(); 732 if (depth == 1) { 733 if (!TAG_ROOT.equals(tag)) { 734 Slog.e(TAG, "Invalid root tag: " + tag); 735 return; 736 } 737 continue; 738 } 739 // readInner() will only see START_TAG at depth >= 2. 740 if (!readInner(parser, depth, tag)) { 741 return; // Error 742 } 743 } 744 } catch (XmlPullParserException | IOException e) { 745 Slog.e(TAG, "Error parsing owners information file", e); 746 } finally { 747 IoUtils.closeQuietly(input); 748 } 749 } 750 writeInner(XmlSerializer out)751 abstract void writeInner(XmlSerializer out) throws IOException; 752 readInner(XmlPullParser parser, int depth, String tag)753 abstract boolean readInner(XmlPullParser parser, int depth, String tag); 754 } 755 756 private class DeviceOwnerReadWriter extends FileReadWriter { 757 DeviceOwnerReadWriter()758 protected DeviceOwnerReadWriter() { 759 super(getDeviceOwnerFile()); 760 } 761 762 @Override shouldWrite()763 boolean shouldWrite() { 764 return (mDeviceOwner != null) || (mSystemUpdatePolicy != null) 765 || (mSystemUpdateInfo != null); 766 } 767 768 @Override writeInner(XmlSerializer out)769 void writeInner(XmlSerializer out) throws IOException { 770 if (mDeviceOwner != null) { 771 mDeviceOwner.writeToXml(out, TAG_DEVICE_OWNER); 772 out.startTag(null, TAG_DEVICE_OWNER_CONTEXT); 773 out.attribute(null, ATTR_USERID, String.valueOf(mDeviceOwnerUserId)); 774 out.endTag(null, TAG_DEVICE_OWNER_CONTEXT); 775 } 776 777 if (mSystemUpdatePolicy != null) { 778 out.startTag(null, TAG_SYSTEM_UPDATE_POLICY); 779 mSystemUpdatePolicy.saveToXml(out); 780 out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); 781 } 782 783 if (mSystemUpdateInfo != null) { 784 mSystemUpdateInfo.writeToXml(out, TAG_PENDING_OTA_INFO); 785 } 786 787 if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { 788 out.startTag(null, TAG_FREEZE_PERIOD_RECORD); 789 if (mSystemUpdateFreezeStart != null) { 790 out.attribute(null, ATTR_FREEZE_RECORD_START, 791 mSystemUpdateFreezeStart.toString()); 792 } 793 if (mSystemUpdateFreezeEnd != null) { 794 out.attribute(null, ATTR_FREEZE_RECORD_END, mSystemUpdateFreezeEnd.toString()); 795 } 796 out.endTag(null, TAG_FREEZE_PERIOD_RECORD); 797 } 798 } 799 800 @Override readInner(XmlPullParser parser, int depth, String tag)801 boolean readInner(XmlPullParser parser, int depth, String tag) { 802 if (depth > 2) { 803 return true; // Ignore 804 } 805 switch (tag) { 806 case TAG_DEVICE_OWNER: 807 mDeviceOwner = OwnerInfo.readFromXml(parser); 808 mDeviceOwnerUserId = UserHandle.USER_SYSTEM; // Set default 809 break; 810 case TAG_DEVICE_OWNER_CONTEXT: { 811 final String userIdString = 812 parser.getAttributeValue(null, ATTR_USERID); 813 try { 814 mDeviceOwnerUserId = Integer.parseInt(userIdString); 815 } catch (NumberFormatException e) { 816 Slog.e(TAG, "Error parsing user-id " + userIdString); 817 } 818 break; 819 } 820 case TAG_DEVICE_INITIALIZER: 821 // Deprecated tag 822 break; 823 case TAG_SYSTEM_UPDATE_POLICY: 824 mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); 825 break; 826 case TAG_PENDING_OTA_INFO: 827 mSystemUpdateInfo = SystemUpdateInfo.readFromXml(parser); 828 break; 829 case TAG_FREEZE_PERIOD_RECORD: 830 String startDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_START); 831 String endDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_END); 832 if (startDate != null && endDate != null) { 833 mSystemUpdateFreezeStart = LocalDate.parse(startDate); 834 mSystemUpdateFreezeEnd = LocalDate.parse(endDate); 835 if (mSystemUpdateFreezeStart.isAfter(mSystemUpdateFreezeEnd)) { 836 Slog.e(TAG, "Invalid system update freeze record loaded"); 837 mSystemUpdateFreezeStart = null; 838 mSystemUpdateFreezeEnd = null; 839 } 840 } 841 break; 842 default: 843 Slog.e(TAG, "Unexpected tag: " + tag); 844 return false; 845 846 } 847 return true; 848 } 849 } 850 851 private class ProfileOwnerReadWriter extends FileReadWriter { 852 private final int mUserId; 853 ProfileOwnerReadWriter(int userId)854 ProfileOwnerReadWriter(int userId) { 855 super(getProfileOwnerFile(userId)); 856 mUserId = userId; 857 } 858 859 @Override shouldWrite()860 boolean shouldWrite() { 861 return mProfileOwners.get(mUserId) != null; 862 } 863 864 @Override writeInner(XmlSerializer out)865 void writeInner(XmlSerializer out) throws IOException { 866 final OwnerInfo profileOwner = mProfileOwners.get(mUserId); 867 if (profileOwner != null) { 868 profileOwner.writeToXml(out, TAG_PROFILE_OWNER); 869 } 870 } 871 872 @Override readInner(XmlPullParser parser, int depth, String tag)873 boolean readInner(XmlPullParser parser, int depth, String tag) { 874 if (depth > 2) { 875 return true; // Ignore 876 } 877 switch (tag) { 878 case TAG_PROFILE_OWNER: 879 mProfileOwners.put(mUserId, OwnerInfo.readFromXml(parser)); 880 break; 881 default: 882 Slog.e(TAG, "Unexpected tag: " + tag); 883 return false; 884 885 } 886 return true; 887 } 888 } 889 890 static class OwnerInfo { 891 public final String name; 892 public final String packageName; 893 public final ComponentName admin; 894 public boolean userRestrictionsMigrated; 895 public String remoteBugreportUri; 896 public String remoteBugreportHash; 897 OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated, String remoteBugreportUri, String remoteBugreportHash)898 public OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated, 899 String remoteBugreportUri, String remoteBugreportHash) { 900 this.name = name; 901 this.packageName = packageName; 902 this.admin = new ComponentName(packageName, ""); 903 this.userRestrictionsMigrated = userRestrictionsMigrated; 904 this.remoteBugreportUri = remoteBugreportUri; 905 this.remoteBugreportHash = remoteBugreportHash; 906 } 907 OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated, String remoteBugreportUri, String remoteBugreportHash)908 public OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated, 909 String remoteBugreportUri, String remoteBugreportHash) { 910 this.name = name; 911 this.admin = admin; 912 this.packageName = admin.getPackageName(); 913 this.userRestrictionsMigrated = userRestrictionsMigrated; 914 this.remoteBugreportUri = remoteBugreportUri; 915 this.remoteBugreportHash = remoteBugreportHash; 916 } 917 writeToXml(XmlSerializer out, String tag)918 public void writeToXml(XmlSerializer out, String tag) throws IOException { 919 out.startTag(null, tag); 920 out.attribute(null, ATTR_PACKAGE, packageName); 921 if (name != null) { 922 out.attribute(null, ATTR_NAME, name); 923 } 924 if (admin != null) { 925 out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString()); 926 } 927 out.attribute(null, ATTR_USER_RESTRICTIONS_MIGRATED, 928 String.valueOf(userRestrictionsMigrated)); 929 if (remoteBugreportUri != null) { 930 out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri); 931 } 932 if (remoteBugreportHash != null) { 933 out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash); 934 } 935 out.endTag(null, tag); 936 } 937 readFromXml(XmlPullParser parser)938 public static OwnerInfo readFromXml(XmlPullParser parser) { 939 final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 940 final String name = parser.getAttributeValue(null, ATTR_NAME); 941 final String componentName = 942 parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 943 final String userRestrictionsMigratedStr = 944 parser.getAttributeValue(null, ATTR_USER_RESTRICTIONS_MIGRATED); 945 final boolean userRestrictionsMigrated = 946 ("true".equals(userRestrictionsMigratedStr)); 947 final String remoteBugreportUri = parser.getAttributeValue(null, 948 ATTR_REMOTE_BUGREPORT_URI); 949 final String remoteBugreportHash = parser.getAttributeValue(null, 950 ATTR_REMOTE_BUGREPORT_HASH); 951 952 // Has component name? If so, return [name, component] 953 if (componentName != null) { 954 final ComponentName admin = ComponentName.unflattenFromString(componentName); 955 if (admin != null) { 956 return new OwnerInfo(name, admin, userRestrictionsMigrated, 957 remoteBugreportUri, remoteBugreportHash); 958 } else { 959 // This shouldn't happen but switch from package name -> component name 960 // might have written bad device owner files. b/17652534 961 Slog.e(TAG, "Error parsing owner file. Bad component name " + 962 componentName); 963 } 964 } 965 966 // Else, build with [name, package] 967 return new OwnerInfo(name, packageName, userRestrictionsMigrated, remoteBugreportUri, 968 remoteBugreportHash); 969 } 970 dump(String prefix, PrintWriter pw)971 public void dump(String prefix, PrintWriter pw) { 972 pw.println(prefix + "admin=" + admin); 973 pw.println(prefix + "name=" + name); 974 pw.println(prefix + "package=" + packageName); 975 } 976 } 977 dump(String prefix, PrintWriter pw)978 public void dump(String prefix, PrintWriter pw) { 979 boolean needBlank = false; 980 if (mDeviceOwner != null) { 981 pw.println(prefix + "Device Owner: "); 982 mDeviceOwner.dump(prefix + " ", pw); 983 pw.println(prefix + " User ID: " + mDeviceOwnerUserId); 984 needBlank = true; 985 } 986 if (mSystemUpdatePolicy != null) { 987 if (needBlank) { 988 pw.println(); 989 } 990 pw.println(prefix + "System Update Policy: " + mSystemUpdatePolicy); 991 needBlank = true; 992 } 993 if (mProfileOwners != null) { 994 for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) { 995 if (needBlank) { 996 pw.println(); 997 } 998 pw.println(prefix + "Profile Owner (User " + entry.getKey() + "): "); 999 entry.getValue().dump(prefix + " ", pw); 1000 needBlank = true; 1001 } 1002 } 1003 if (mSystemUpdateInfo != null) { 1004 if (needBlank) { 1005 pw.println(); 1006 } 1007 pw.println(prefix + "Pending System Update: " + mSystemUpdateInfo); 1008 needBlank = true; 1009 } 1010 if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { 1011 if (needBlank) { 1012 pw.println(); 1013 } 1014 pw.println(prefix + "System update freeze record: " 1015 + getSystemUpdateFreezePeriodRecordAsString()); 1016 needBlank = true; 1017 } 1018 } 1019 1020 @VisibleForTesting getLegacyConfigFile()1021 File getLegacyConfigFile() { 1022 return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML_LEGACY); 1023 } 1024 1025 @VisibleForTesting getDeviceOwnerFile()1026 File getDeviceOwnerFile() { 1027 return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML); 1028 } 1029 1030 @VisibleForTesting getProfileOwnerFile(int userId)1031 File getProfileOwnerFile(int userId) { 1032 return new File(mInjector.environmentGetUserSystemDirectory(userId), PROFILE_OWNER_XML); 1033 } 1034 1035 @VisibleForTesting 1036 public static class Injector { environmentGetDataSystemDirectory()1037 File environmentGetDataSystemDirectory() { 1038 return Environment.getDataSystemDirectory(); 1039 } 1040 environmentGetUserSystemDirectory(int userId)1041 File environmentGetUserSystemDirectory(int userId) { 1042 return Environment.getUserSystemDirectory(userId); 1043 } 1044 } 1045 } 1046