• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 package com.android.server.devicepolicy;
17 
18 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
19 
20 import android.annotation.Nullable;
21 import android.app.admin.SystemUpdateInfo;
22 import android.app.admin.SystemUpdatePolicy;
23 import android.app.admin.flags.Flags;
24 import android.content.ComponentName;
25 import android.os.UserHandle;
26 import android.util.ArrayMap;
27 import android.util.AtomicFile;
28 import android.util.IndentingPrintWriter;
29 import android.util.Log;
30 import android.util.Slog;
31 import android.util.Xml;
32 
33 import com.android.internal.annotations.VisibleForTesting;
34 import com.android.modules.utils.TypedXmlPullParser;
35 import com.android.modules.utils.TypedXmlSerializer;
36 
37 import libcore.io.IoUtils;
38 
39 import org.xmlpull.v1.XmlPullParserException;
40 
41 import java.io.File;
42 import java.io.FileOutputStream;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.time.LocalDate;
46 import java.util.ArrayList;
47 import java.util.List;
48 import java.util.Map;
49 
50 class OwnersData {
51     private static final String TAG = "DevicePolicyManagerService";
52 
53     private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE
54 
55     // XML storing device owner info, system update policy and pending OTA update information.
56     private static final String DEVICE_OWNER_XML = "device_owner_2.xml";
57     private static final String PROFILE_OWNER_XML = "profile_owner.xml";
58 
59     private static final String TAG_ROOT = "root";
60     private static final String TAG_DEVICE_OWNER = "device-owner";
61     private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy";
62     private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record";
63     private static final String TAG_PENDING_OTA_INFO = "pending-ota-info";
64     private static final String TAG_PROFILE_OWNER = "profile-owner";
65     // Holds "context" for device-owner, this must not be show up before device-owner.
66     private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context";
67     private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type";
68     private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES =
69             "device-owner-protected-packages";
70     private static final String TAG_POLICY_ENGINE_MIGRATION = "policy-engine-migration";
71 
72     private static final String ATTR_NAME = "name";
73     private static final String ATTR_PACKAGE = "package";
74     private static final String ATTR_COMPONENT_NAME = "component";
75     private static final String ATTR_SIZE = "size";
76     private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri";
77     private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash";
78     private static final String ATTR_USERID = "userId";
79     private static final String ATTR_FREEZE_RECORD_START = "start";
80     private static final String ATTR_FREEZE_RECORD_END = "end";
81     // Legacy attribute, its presence would mean the profile owner associated with it is
82     // managing a profile on an organization-owned device.
83     private static final String ATTR_CAN_ACCESS_DEVICE_IDS = "canAccessDeviceIds";
84     // New attribute for profile owner of organization-owned device.
85     private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE =
86             "isPoOrganizationOwnedDevice";
87     private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value";
88 
89     private static final String ATTR_MIGRATED_TO_POLICY_ENGINE = "migratedToPolicyEngine";
90     private static final String ATTR_SECURITY_LOG_MIGRATED = "securityLogMigrated";
91     private static final String ATTR_REQUIRED_PASSWORD_COMPLEXITY_MIGRATED =
92             "passwordComplexityMigrated";
93     private static final String ATTR_SUSPENDED_PACKAGES_MIGRATED = "suspendedPackagesMigrated";
94     private static final String ATTR_RESET_PASSWORD_WITH_TOKEN_MIGRATED =
95             "resetPasswordWithTokenMigrated";
96     private static final String ATTR_MEMORY_TAGGING_MIGRATED =
97             "memoryTaggingMigrated";
98     private static final String ATTR_SET_KEYGUARD_DISABLED_FEATURES_MIGRATED =
99             "setKeyguardDisabledFeaturesMigrated";
100 
101     private static final String ATTR_MIGRATED_POST_UPGRADE = "migratedPostUpgrade";
102 
103     // Internal state for the device owner package.
104     OwnerInfo mDeviceOwner;
105     int mDeviceOwnerUserId = UserHandle.USER_NULL;
106 
107     // Device owner type for a managed device.
108     final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();
109 
110     /** @deprecated moved to {@link ActiveAdmin#protectedPackages}. */
111     @Deprecated
112     @Nullable
113     ArrayMap<String, List<String>> mDeviceOwnerProtectedPackages;
114 
115     // Internal state for the profile owner packages.
116     final ArrayMap<Integer, OwnerInfo> mProfileOwners = new ArrayMap<>();
117 
118     // Local system update policy controllable by device owner.
119     SystemUpdatePolicy mSystemUpdatePolicy;
120     LocalDate mSystemUpdateFreezeStart;
121     LocalDate mSystemUpdateFreezeEnd;
122 
123     // Pending OTA info if there is one.
124     @Nullable
125     SystemUpdateInfo mSystemUpdateInfo;
126     private final PolicyPathProvider mPathProvider;
127 
128     boolean mMigratedToPolicyEngine = false;
129     boolean mSecurityLoggingMigrated = false;
130     boolean mRequiredPasswordComplexityMigrated = false;
131     boolean mSuspendedPackagesMigrated = false;
132     boolean mResetPasswordWithTokenMigrated = false;
133     boolean mMemoryTaggingMigrated = false;
134     boolean mSetKeyguardDisabledFeaturesMigrated = false;
135 
136     boolean mPoliciesMigratedPostUpdate = false;
137 
OwnersData(PolicyPathProvider pathProvider)138     OwnersData(PolicyPathProvider pathProvider) {
139         mPathProvider = pathProvider;
140     }
141 
load(int[] allUsers)142     void load(int[] allUsers) {
143         new DeviceOwnerReadWriter().readFromFileLocked();
144 
145         for (int userId : allUsers) {
146             new ProfileOwnerReadWriter(userId).readFromFileLocked();
147         }
148 
149         OwnerInfo profileOwner = mProfileOwners.get(mDeviceOwnerUserId);
150         ComponentName admin = profileOwner != null ? profileOwner.admin : null;
151         if (mDeviceOwner != null && admin != null) {
152             Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
153                     mDeviceOwnerUserId));
154         }
155     }
156 
157     /**
158      * @return true upon success, false otherwise.
159      */
writeDeviceOwner()160     boolean writeDeviceOwner() {
161         if (DEBUG) {
162             Log.d(TAG, "Writing to device owner file");
163         }
164         return new DeviceOwnerReadWriter().writeToFileLocked();
165     }
166 
167     /**
168      * @return true upon success, false otherwise.
169      */
writeProfileOwner(int userId)170     boolean writeProfileOwner(int userId) {
171         if (DEBUG) {
172             Log.d(TAG, "Writing to profile owner file for user " + userId);
173         }
174         return new ProfileOwnerReadWriter(userId).writeToFileLocked();
175     }
176 
dump(IndentingPrintWriter pw)177     void dump(IndentingPrintWriter pw) {
178         boolean needBlank = false;
179         if (mDeviceOwner != null) {
180             pw.println("Device Owner: ");
181             pw.increaseIndent();
182             mDeviceOwner.dump(pw);
183             pw.println("User ID: " + mDeviceOwnerUserId);
184             pw.decreaseIndent();
185             needBlank = true;
186         }
187         if (mSystemUpdatePolicy != null) {
188             if (needBlank) {
189                 pw.println();
190             }
191             pw.println("System Update Policy: " + mSystemUpdatePolicy);
192             needBlank = true;
193         }
194         if (mProfileOwners != null) {
195             for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) {
196                 if (needBlank) {
197                     pw.println();
198                 }
199                 pw.println("Profile Owner (User " + entry.getKey() + "): ");
200                 pw.increaseIndent();
201                 entry.getValue().dump(pw);
202                 pw.decreaseIndent();
203                 needBlank = true;
204             }
205         }
206         if (mSystemUpdateInfo != null) {
207             if (needBlank) {
208                 pw.println();
209             }
210             pw.println("Pending System Update: " + mSystemUpdateInfo);
211             needBlank = true;
212         }
213         if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) {
214             if (needBlank) {
215                 pw.println();
216             }
217             pw.println("System update freeze record: "
218                     + getSystemUpdateFreezePeriodRecordAsString());
219             needBlank = true;
220         }
221     }
222 
getSystemUpdateFreezePeriodRecordAsString()223     String getSystemUpdateFreezePeriodRecordAsString() {
224         StringBuilder freezePeriodRecord = new StringBuilder();
225         freezePeriodRecord.append("start: ");
226         if (mSystemUpdateFreezeStart != null) {
227             freezePeriodRecord.append(mSystemUpdateFreezeStart.toString());
228         } else {
229             freezePeriodRecord.append("null");
230         }
231         freezePeriodRecord.append("; end: ");
232         if (mSystemUpdateFreezeEnd != null) {
233             freezePeriodRecord.append(mSystemUpdateFreezeEnd.toString());
234         } else {
235             freezePeriodRecord.append("null");
236         }
237         return freezePeriodRecord.toString();
238     }
239 
240     @VisibleForTesting
getDeviceOwnerFile()241     File getDeviceOwnerFile() {
242         return new File(mPathProvider.getDataSystemDirectory(), DEVICE_OWNER_XML);
243     }
244 
245     @VisibleForTesting
getProfileOwnerFile(int userId)246     File getProfileOwnerFile(int userId) {
247         return new File(mPathProvider.getUserSystemDirectory(userId), PROFILE_OWNER_XML);
248     }
249 
250     private abstract static class FileReadWriter {
251         private final File mFile;
252 
FileReadWriter(File file)253         protected FileReadWriter(File file) {
254             mFile = file;
255         }
256 
shouldWrite()257         abstract boolean shouldWrite();
258 
writeToFileLocked()259         boolean writeToFileLocked() {
260             if (!shouldWrite()) {
261                 if (DEBUG) {
262                     Log.d(TAG, "No need to write to " + mFile);
263                 }
264                 // No contents, remove the file.
265                 if (mFile.exists()) {
266                     if (DEBUG) {
267                         Log.d(TAG, "Deleting existing " + mFile);
268                     }
269                     if (!mFile.delete()) {
270                         Slog.e(TAG, "Failed to remove " + mFile.getPath());
271                     }
272                 }
273                 return true;
274             }
275             if (DEBUG) {
276                 Log.d(TAG, "Writing to " + mFile);
277             }
278 
279             final AtomicFile f = new AtomicFile(mFile);
280             FileOutputStream outputStream = null;
281             try {
282                 outputStream = f.startWrite();
283                 final TypedXmlSerializer out = Xml.resolveSerializer(outputStream);
284 
285                 // Root tag
286                 out.startDocument(null, true);
287                 out.startTag(null, TAG_ROOT);
288 
289                 // Actual content
290                 writeInner(out);
291 
292                 // Close root
293                 out.endTag(null, TAG_ROOT);
294                 out.endDocument();
295                 out.flush();
296 
297                 // Commit the content.
298                 f.finishWrite(outputStream);
299                 outputStream = null;
300 
301             } catch (IOException e) {
302                 Slog.e(TAG, "Exception when writing", e);
303                 if (outputStream != null) {
304                     f.failWrite(outputStream);
305                 }
306                 return false;
307             }
308             return true;
309         }
310 
readFromFileLocked()311         void readFromFileLocked() {
312             if (!mFile.exists()) {
313                 if (DEBUG) {
314                     Log.d(TAG, "" + mFile + " doesn't exist");
315                 }
316                 return;
317             }
318             if (DEBUG) {
319                 Log.d(TAG, "Reading from " + mFile);
320             }
321             final AtomicFile f = new AtomicFile(mFile);
322             InputStream input = null;
323             try {
324                 input = f.openRead();
325                 final TypedXmlPullParser parser = Xml.resolvePullParser(input);
326 
327                 int type;
328                 int depth = 0;
329                 while ((type = parser.next()) != TypedXmlPullParser.END_DOCUMENT) {
330                     switch (type) {
331                         case TypedXmlPullParser.START_TAG:
332                             depth++;
333                             break;
334                         case TypedXmlPullParser.END_TAG:
335                             depth--;
336                             // fallthrough
337                         default:
338                             continue;
339                     }
340                     // Check the root tag
341                     final String tag = parser.getName();
342                     if (depth == 1) {
343                         if (!TAG_ROOT.equals(tag)) {
344                             Slog.e(TAG, "Invalid root tag: " + tag);
345                             return;
346                         }
347                         continue;
348                     }
349                     // readInner() will only see START_TAG at depth >= 2.
350                     if (!readInner(parser, depth, tag)) {
351                         return; // Error
352                     }
353                 }
354             } catch (XmlPullParserException | IOException e) {
355                 Slog.e(TAG, "Error parsing owners information file", e);
356             } finally {
357                 IoUtils.closeQuietly(input);
358             }
359         }
360 
writeInner(TypedXmlSerializer out)361         abstract void writeInner(TypedXmlSerializer out) throws IOException;
362 
readInner(TypedXmlPullParser parser, int depth, String tag)363         abstract boolean readInner(TypedXmlPullParser parser, int depth, String tag);
364     }
365 
366     private class DeviceOwnerReadWriter extends FileReadWriter {
367 
DeviceOwnerReadWriter()368         protected DeviceOwnerReadWriter() {
369             super(getDeviceOwnerFile());
370         }
371 
372         @Override
shouldWrite()373         boolean shouldWrite() {
374             return true;
375         }
376 
377         @Override
writeInner(TypedXmlSerializer out)378         void writeInner(TypedXmlSerializer out) throws IOException {
379             if (mDeviceOwner != null) {
380                 mDeviceOwner.writeToXml(out, TAG_DEVICE_OWNER);
381                 out.startTag(null, TAG_DEVICE_OWNER_CONTEXT);
382                 out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId);
383                 out.endTag(null, TAG_DEVICE_OWNER_CONTEXT);
384 
385             }
386 
387             if (!mDeviceOwnerTypes.isEmpty()) {
388                 for (ArrayMap.Entry<String, Integer> entry : mDeviceOwnerTypes.entrySet()) {
389                     out.startTag(null, TAG_DEVICE_OWNER_TYPE);
390                     out.attribute(null, ATTR_PACKAGE, entry.getKey());
391                     out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue());
392                     out.endTag(null, TAG_DEVICE_OWNER_TYPE);
393                 }
394             }
395 
396             if (mSystemUpdatePolicy != null) {
397                 out.startTag(null, TAG_SYSTEM_UPDATE_POLICY);
398                 mSystemUpdatePolicy.saveToXml(out);
399                 out.endTag(null, TAG_SYSTEM_UPDATE_POLICY);
400             }
401 
402             if (mSystemUpdateInfo != null) {
403                 mSystemUpdateInfo.writeToXml(out, TAG_PENDING_OTA_INFO);
404             }
405 
406             if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) {
407                 out.startTag(null, TAG_FREEZE_PERIOD_RECORD);
408                 if (mSystemUpdateFreezeStart != null) {
409                     out.attribute(
410                             null, ATTR_FREEZE_RECORD_START, mSystemUpdateFreezeStart.toString());
411                 }
412                 if (mSystemUpdateFreezeEnd != null) {
413                     out.attribute(null, ATTR_FREEZE_RECORD_END, mSystemUpdateFreezeEnd.toString());
414                 }
415                 out.endTag(null, TAG_FREEZE_PERIOD_RECORD);
416             }
417 
418             out.startTag(null, TAG_POLICY_ENGINE_MIGRATION);
419             out.attributeBoolean(null, ATTR_MIGRATED_TO_POLICY_ENGINE, mMigratedToPolicyEngine);
420             out.attributeBoolean(null, ATTR_MIGRATED_POST_UPGRADE, mPoliciesMigratedPostUpdate);
421             out.attributeBoolean(null, ATTR_SECURITY_LOG_MIGRATED, mSecurityLoggingMigrated);
422 
423             if (Flags.unmanagedModeMigration()) {
424                 out.attributeBoolean(null, ATTR_REQUIRED_PASSWORD_COMPLEXITY_MIGRATED,
425                         mRequiredPasswordComplexityMigrated);
426             }
427             if (Flags.suspendPackagesCoexistence()) {
428                 out.attributeBoolean(null, ATTR_SUSPENDED_PACKAGES_MIGRATED,
429                         mSuspendedPackagesMigrated);
430 
431             }
432             if (Flags.resetPasswordWithTokenCoexistence()) {
433                 out.attributeBoolean(null, ATTR_RESET_PASSWORD_WITH_TOKEN_MIGRATED,
434                         mResetPasswordWithTokenMigrated);
435             }
436             out.attributeBoolean(null, ATTR_MEMORY_TAGGING_MIGRATED,
437                     mMemoryTaggingMigrated);
438             if (Flags.setKeyguardDisabledFeaturesCoexistence()) {
439                 out.attributeBoolean(null, ATTR_SET_KEYGUARD_DISABLED_FEATURES_MIGRATED,
440                         mSetKeyguardDisabledFeaturesMigrated);
441             }
442             out.endTag(null, TAG_POLICY_ENGINE_MIGRATION);
443 
444         }
445 
446         @Override
readInner(TypedXmlPullParser parser, int depth, String tag)447         boolean readInner(TypedXmlPullParser parser, int depth, String tag) {
448             if (depth > 2) {
449                 return true; // Ignore
450             }
451             switch (tag) {
452                 case TAG_DEVICE_OWNER:
453                     mDeviceOwner = OwnerInfo.readFromXml(parser);
454                     mDeviceOwnerUserId = UserHandle.USER_SYSTEM; // Set default
455                     break;
456                 case TAG_DEVICE_OWNER_CONTEXT: {
457                     mDeviceOwnerUserId =
458                             parser.getAttributeInt(null, ATTR_USERID, mDeviceOwnerUserId);
459                     break;
460                 }
461                 case TAG_SYSTEM_UPDATE_POLICY:
462                     mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser);
463                     break;
464                 case TAG_PENDING_OTA_INFO:
465                     mSystemUpdateInfo = SystemUpdateInfo.readFromXml(parser);
466                     break;
467                 case TAG_FREEZE_PERIOD_RECORD:
468                     String startDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_START);
469                     String endDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_END);
470                     if (startDate != null && endDate != null) {
471                         mSystemUpdateFreezeStart = LocalDate.parse(startDate);
472                         mSystemUpdateFreezeEnd = LocalDate.parse(endDate);
473                         if (mSystemUpdateFreezeStart.isAfter(mSystemUpdateFreezeEnd)) {
474                             Slog.e(TAG, "Invalid system update freeze record loaded");
475                             mSystemUpdateFreezeStart = null;
476                             mSystemUpdateFreezeEnd = null;
477                         }
478                     }
479                     break;
480                 case TAG_DEVICE_OWNER_TYPE:
481                     String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
482                     int deviceOwnerType = parser.getAttributeInt(
483                             null, ATTR_DEVICE_OWNER_TYPE_VALUE, DEVICE_OWNER_TYPE_DEFAULT);
484                     mDeviceOwnerTypes.put(packageName, deviceOwnerType);
485                     break;
486                 // Deprecated fields below.
487                 case TAG_DEVICE_OWNER_PROTECTED_PACKAGES:
488                     packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
489                     int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0);
490                     List<String> protectedPackages = new ArrayList<>();
491                     for (int i = 0; i < protectedPackagesSize; i++) {
492                         protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i));
493                     }
494                     if (mDeviceOwnerProtectedPackages == null) {
495                         mDeviceOwnerProtectedPackages = new ArrayMap<>();
496                     }
497                     mDeviceOwnerProtectedPackages.put(packageName, protectedPackages);
498                     break;
499                 case TAG_POLICY_ENGINE_MIGRATION:
500                     mMigratedToPolicyEngine = parser.getAttributeBoolean(
501                             null, ATTR_MIGRATED_TO_POLICY_ENGINE, false);
502                     mPoliciesMigratedPostUpdate = parser.getAttributeBoolean(
503                             null, ATTR_MIGRATED_POST_UPGRADE, false);
504                     mSecurityLoggingMigrated =
505                             parser.getAttributeBoolean(null, ATTR_SECURITY_LOG_MIGRATED, false);
506                     mRequiredPasswordComplexityMigrated = Flags.unmanagedModeMigration()
507                             && parser.getAttributeBoolean(null,
508                                     ATTR_REQUIRED_PASSWORD_COMPLEXITY_MIGRATED, false);
509                     mSuspendedPackagesMigrated = Flags.suspendPackagesCoexistence()
510                             && parser.getAttributeBoolean(null,
511                                     ATTR_SUSPENDED_PACKAGES_MIGRATED, false);
512                     mResetPasswordWithTokenMigrated = Flags.resetPasswordWithTokenCoexistence()
513                             && parser.getAttributeBoolean(null,
514                             ATTR_RESET_PASSWORD_WITH_TOKEN_MIGRATED, false);
515                     mMemoryTaggingMigrated = parser.getAttributeBoolean(null,
516                             ATTR_MEMORY_TAGGING_MIGRATED, false);
517                     mSetKeyguardDisabledFeaturesMigrated =
518                             Flags.setKeyguardDisabledFeaturesCoexistence()
519                                     && parser.getAttributeBoolean(null,
520                                     ATTR_SET_KEYGUARD_DISABLED_FEATURES_MIGRATED, false);
521                     break;
522                 default:
523                     Slog.e(TAG, "Unexpected tag: " + tag);
524                     return false;
525 
526             }
527             return true;
528         }
529     }
530 
531     private class ProfileOwnerReadWriter extends FileReadWriter {
532         private final int mUserId;
533 
ProfileOwnerReadWriter(int userId)534         ProfileOwnerReadWriter(int userId) {
535             super(getProfileOwnerFile(userId));
536             mUserId = userId;
537         }
538 
539         @Override
shouldWrite()540         boolean shouldWrite() {
541             return mProfileOwners.get(mUserId) != null;
542         }
543 
544         @Override
writeInner(TypedXmlSerializer out)545         void writeInner(TypedXmlSerializer out) throws IOException {
546             final OwnerInfo profileOwner = mProfileOwners.get(mUserId);
547             if (profileOwner != null) {
548                 profileOwner.writeToXml(out, TAG_PROFILE_OWNER);
549             }
550         }
551 
552         @Override
readInner(TypedXmlPullParser parser, int depth, String tag)553         boolean readInner(TypedXmlPullParser parser, int depth, String tag) {
554             if (depth > 2) {
555                 return true; // Ignore
556             }
557             switch (tag) {
558                 case TAG_PROFILE_OWNER:
559                     mProfileOwners.put(mUserId, OwnerInfo.readFromXml(parser));
560                     break;
561                 default:
562                     Slog.e(TAG, "Unexpected tag: " + tag);
563                     return false;
564 
565             }
566             return true;
567         }
568     }
569 
570     static class OwnerInfo {
571         public final String packageName;
572         public final ComponentName admin;
573         public String remoteBugreportUri;
574         public String remoteBugreportHash;
575         public boolean isOrganizationOwnedDevice;
576 
OwnerInfo(ComponentName admin, String remoteBugreportUri, String remoteBugreportHash, boolean isOrganizationOwnedDevice)577         OwnerInfo(ComponentName admin, String remoteBugreportUri,
578                 String remoteBugreportHash, boolean isOrganizationOwnedDevice) {
579             this.admin = admin;
580             this.packageName = admin.getPackageName();
581             this.remoteBugreportUri = remoteBugreportUri;
582             this.remoteBugreportHash = remoteBugreportHash;
583             this.isOrganizationOwnedDevice = isOrganizationOwnedDevice;
584         }
585 
writeToXml(TypedXmlSerializer out, String tag)586         public void writeToXml(TypedXmlSerializer out, String tag) throws IOException {
587             out.startTag(null, tag);
588             if (admin != null) {
589                 out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString());
590             }
591             if (remoteBugreportUri != null) {
592                 out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri);
593             }
594             if (remoteBugreportHash != null) {
595                 out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash);
596             }
597             if (isOrganizationOwnedDevice) {
598                 out.attributeBoolean(
599                         null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE, isOrganizationOwnedDevice);
600             }
601             out.endTag(null, tag);
602         }
603 
readFromXml(TypedXmlPullParser parser)604         public static OwnerInfo readFromXml(TypedXmlPullParser parser) {
605             final String componentName = parser.getAttributeValue(null, ATTR_COMPONENT_NAME);
606             final String remoteBugreportUri =
607                     parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_URI);
608             final String remoteBugreportHash =
609                     parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_HASH);
610             final String canAccessDeviceIdsStr =
611                     parser.getAttributeValue(null, ATTR_CAN_ACCESS_DEVICE_IDS);
612             final boolean canAccessDeviceIds = "true".equals(canAccessDeviceIdsStr);
613             final String isOrgOwnedDeviceStr =
614                     parser.getAttributeValue(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE);
615             final boolean isOrgOwnedDevice =
616                     "true".equals(isOrgOwnedDeviceStr) | canAccessDeviceIds;
617 
618             if (componentName == null) {
619                 Slog.e(TAG, "Owner component not found");
620                 return null;
621             }
622             final ComponentName admin = ComponentName.unflattenFromString(componentName);
623             if (admin == null) {
624                 Slog.e(TAG, "Owner component not parsable: " + componentName);
625                 return null;
626             }
627 
628             return new OwnerInfo(admin, remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice);
629         }
630 
dump(IndentingPrintWriter pw)631         public void dump(IndentingPrintWriter pw) {
632             pw.println("admin=" + admin);
633             pw.println("package=" + packageName);
634             pw.println("isOrganizationOwnedDevice=" + isOrganizationOwnedDevice);
635         }
636     }
637 }
638