Home | History | Annotate | Download | only in devicepolicy
      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 
    129     public Owners(UserManager userManager,
    130             UserManagerInternal userManagerInternal,
    131             PackageManagerInternal packageManagerInternal) {
    132         this(userManager, userManagerInternal, packageManagerInternal, new Injector());
    133     }
    134 
    135     @VisibleForTesting
    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      */
    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 
    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 
    203     String getDeviceOwnerPackageName() {
    204         synchronized (mLock) {
    205             return mDeviceOwner != null ? mDeviceOwner.packageName : null;
    206         }
    207     }
    208 
    209     int getDeviceOwnerUserId() {
    210         synchronized (mLock) {
    211             return mDeviceOwnerUserId;
    212         }
    213     }
    214 
    215     @Nullable
    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 
    226     String getDeviceOwnerName() {
    227         synchronized (mLock) {
    228             return mDeviceOwner != null ? mDeviceOwner.name : null;
    229         }
    230     }
    231 
    232     ComponentName getDeviceOwnerComponent() {
    233         synchronized (mLock) {
    234             return mDeviceOwner != null ? mDeviceOwner.admin : null;
    235         }
    236     }
    237 
    238     String getDeviceOwnerRemoteBugreportUri() {
    239         synchronized (mLock) {
    240             return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null;
    241         }
    242     }
    243 
    244     String getDeviceOwnerRemoteBugreportHash() {
    245         synchronized (mLock) {
    246             return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null;
    247         }
    248     }
    249 
    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.
    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 
    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 
    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 
    300     void removeProfileOwner(int userId) {
    301         synchronized (mLock) {
    302             mProfileOwners.remove(userId);
    303             mUserManagerInternal.setUserManaged(userId, false);
    304             pushToPackageManagerLocked();
    305             pushToAppOpsLocked();
    306         }
    307     }
    308 
    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 
    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 
    333     ComponentName getProfileOwnerComponent(int userId) {
    334         synchronized (mLock) {
    335             OwnerInfo profileOwner = mProfileOwners.get(userId);
    336             return profileOwner != null ? profileOwner.admin : null;
    337         }
    338     }
    339 
    340     String getProfileOwnerName(int userId) {
    341         synchronized (mLock) {
    342             OwnerInfo profileOwner = mProfileOwners.get(userId);
    343             return profileOwner != null ? profileOwner.name : null;
    344         }
    345     }
    346 
    347     String getProfileOwnerPackage(int userId) {
    348         synchronized (mLock) {
    349             OwnerInfo profileOwner = mProfileOwners.get(userId);
    350             return profileOwner != null ? profileOwner.packageName : null;
    351         }
    352     }
    353 
    354     Set<Integer> getProfileOwnerKeys() {
    355         synchronized (mLock) {
    356             return mProfileOwners.keySet();
    357         }
    358     }
    359 
    360     SystemUpdatePolicy getSystemUpdatePolicy() {
    361         synchronized (mLock) {
    362             return mSystemUpdatePolicy;
    363         }
    364     }
    365 
    366     void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) {
    367         synchronized (mLock) {
    368             mSystemUpdatePolicy = systemUpdatePolicy;
    369         }
    370     }
    371 
    372     void clearSystemUpdatePolicy() {
    373         synchronized (mLock) {
    374             mSystemUpdatePolicy = null;
    375         }
    376     }
    377 
    378     Pair<LocalDate, LocalDate> getSystemUpdateFreezePeriodRecord() {
    379         synchronized (mLock) {
    380             return new Pair<>(mSystemUpdateFreezeStart, mSystemUpdateFreezeEnd);
    381         }
    382     }
    383 
    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      */
    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 
    419     boolean hasDeviceOwner() {
    420         synchronized (mLock) {
    421             return mDeviceOwner != null;
    422         }
    423     }
    424 
    425     boolean isDeviceOwnerUserId(int userId) {
    426         synchronized (mLock) {
    427             return mDeviceOwner != null && mDeviceOwnerUserId == userId;
    428         }
    429     }
    430 
    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      */
    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      */
    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. */
    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. */
    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.  */
    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 
    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 
    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 
    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      */
    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
    592     public SystemUpdateInfo getSystemUpdateInfo() {
    593         synchronized (mLock) {
    594             return mSystemUpdateInfo;
    595         }
    596     }
    597 
    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 
    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 
    643         protected FileReadWriter(File file) {
    644             mFile = file;
    645         }
    646 
    647         abstract boolean shouldWrite();
    648 
    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 
    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 
    751         abstract void writeInner(XmlSerializer out) throws IOException;
    752 
    753         abstract boolean readInner(XmlPullParser parser, int depth, String tag);
    754     }
    755 
    756     private class DeviceOwnerReadWriter extends FileReadWriter {
    757 
    758         protected DeviceOwnerReadWriter() {
    759             super(getDeviceOwnerFile());
    760         }
    761 
    762         @Override
    763         boolean shouldWrite() {
    764             return (mDeviceOwner != null) || (mSystemUpdatePolicy != null)
    765                     || (mSystemUpdateInfo != null);
    766         }
    767 
    768         @Override
    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
    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 
    854         ProfileOwnerReadWriter(int userId) {
    855             super(getProfileOwnerFile(userId));
    856             mUserId = userId;
    857         }
    858 
    859         @Override
    860         boolean shouldWrite() {
    861             return mProfileOwners.get(mUserId) != null;
    862         }
    863 
    864         @Override
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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
   1021     File getLegacyConfigFile() {
   1022         return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML_LEGACY);
   1023     }
   1024 
   1025     @VisibleForTesting
   1026     File getDeviceOwnerFile() {
   1027         return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML);
   1028     }
   1029 
   1030     @VisibleForTesting
   1031     File getProfileOwnerFile(int userId) {
   1032         return new File(mInjector.environmentGetUserSystemDirectory(userId), PROFILE_OWNER_XML);
   1033     }
   1034 
   1035     @VisibleForTesting
   1036     public static class Injector {
   1037         File environmentGetDataSystemDirectory() {
   1038             return Environment.getDataSystemDirectory();
   1039         }
   1040 
   1041         File environmentGetUserSystemDirectory(int userId) {
   1042             return Environment.getUserSystemDirectory(userId);
   1043         }
   1044     }
   1045 }
   1046