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