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