• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, 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.managedprovisioning.task.nonrequiredapps;
18 
19 import static com.android.internal.util.Preconditions.checkNotNull;
20 
21 import android.annotation.Nullable;
22 import android.app.AppGlobals;
23 import android.content.Context;
24 import android.content.pm.IPackageManager;
25 import android.util.Xml;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.internal.util.FastXmlSerializer;
29 import com.android.managedprovisioning.common.ProvisionLogger;
30 import com.android.managedprovisioning.common.Utils;
31 
32 import java.io.File;
33 import java.io.FileInputStream;
34 import java.io.FileOutputStream;
35 import java.io.IOException;
36 import java.util.Collections;
37 import java.util.HashSet;
38 import java.util.Set;
39 
40 import org.xmlpull.v1.XmlPullParser;
41 import org.xmlpull.v1.XmlPullParserException;
42 import org.xmlpull.v1.XmlSerializer;
43 
44 /**
45  * Stores and retrieves the system apps that were on the device during provisioning and on
46  * subsequent OTAs.
47  */
48 public class SystemAppsSnapshot {
49     private static final String TAG_SYSTEM_APPS = "system-apps";
50     private static final String TAG_PACKAGE_LIST_ITEM = "item";
51     private static final String ATTR_VALUE = "value";
52 
53     private final Context mContext;
54     private final IPackageManager mIPackageManager;
55     private final Utils mUtils;
56 
SystemAppsSnapshot(Context context)57     public SystemAppsSnapshot(Context context) {
58         this(context, AppGlobals.getPackageManager(), new Utils());
59     }
60 
61     @VisibleForTesting
SystemAppsSnapshot( Context context, IPackageManager iPackageManager, Utils utils)62     SystemAppsSnapshot(
63             Context context,
64             IPackageManager iPackageManager,
65             Utils utils) {
66         mContext = checkNotNull(context);
67         mIPackageManager = checkNotNull(iPackageManager);
68         mUtils = checkNotNull(utils);
69     }
70 
71     /**
72      * Returns whether currently a snapshot exists for the given user.
73      *
74      * @param userId the user id for which the snapshot is requested.
75      */
hasSnapshot(int userId)76     public boolean hasSnapshot(int userId) {
77         return getSystemAppsFile(mContext, userId).exists();
78     }
79 
80     /**
81      * Returns the last stored snapshot for the given user.
82      *
83      * @param userId the user id for which the snapshot is requested.
84      */
getSnapshot(int userId)85     public Set<String> getSnapshot(int userId) {
86         return readSystemApps(getSystemAppsFile(mContext, userId));
87     }
88 
89     /**
90      * Call this method to take a snapshot of the current set of system apps.
91      *
92      * @param userId the user id for which the snapshot should be taken.
93      */
takeNewSnapshot(int userId)94     public void takeNewSnapshot(int userId) {
95         final File systemAppsFile = getSystemAppsFile(mContext, userId);
96         systemAppsFile.getParentFile().mkdirs(); // Creating the folder if it does not exist
97         writeSystemApps(mUtils.getCurrentSystemApps(mIPackageManager, userId), systemAppsFile);
98     }
99 
writeSystemApps(Set<String> packageNames, File systemAppsFile)100     private void writeSystemApps(Set<String> packageNames, File systemAppsFile) {
101         try {
102             FileOutputStream stream = new FileOutputStream(systemAppsFile, false);
103             XmlSerializer serializer = new FastXmlSerializer();
104             serializer.setOutput(stream, "utf-8");
105             serializer.startDocument(null, true);
106             serializer.startTag(null, TAG_SYSTEM_APPS);
107             for (String packageName : packageNames) {
108                 serializer.startTag(null, TAG_PACKAGE_LIST_ITEM);
109                 serializer.attribute(null, ATTR_VALUE, packageName);
110                 serializer.endTag(null, TAG_PACKAGE_LIST_ITEM);
111             }
112             serializer.endTag(null, TAG_SYSTEM_APPS);
113             serializer.endDocument();
114             stream.close();
115         } catch (IOException e) {
116             ProvisionLogger.loge("IOException trying to write the system apps", e);
117         }
118     }
119 
readSystemApps(File systemAppsFile)120     private Set<String> readSystemApps(File systemAppsFile) {
121         Set<String> result = new HashSet<>();
122         if (!systemAppsFile.exists()) {
123             return result;
124         }
125         try {
126             FileInputStream stream = new FileInputStream(systemAppsFile);
127 
128             XmlPullParser parser = Xml.newPullParser();
129             parser.setInput(stream, null);
130             parser.next();
131 
132             int type;
133             int outerDepth = parser.getDepth();
134             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
135                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
136                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
137                     continue;
138                 }
139                 String tag = parser.getName();
140                 if (tag.equals(TAG_PACKAGE_LIST_ITEM)) {
141                     result.add(parser.getAttributeValue(null, ATTR_VALUE));
142                 } else {
143                     ProvisionLogger.loge("Unknown tag: " + tag);
144                 }
145             }
146             stream.close();
147         } catch (IOException e) {
148             ProvisionLogger.loge("IOException trying to read the system apps", e);
149         } catch (XmlPullParserException e) {
150             ProvisionLogger.loge("XmlPullParserException trying to read the system apps", e);
151         }
152         return result;
153     }
154 
155     @VisibleForTesting
getSystemAppsFile(Context context, int userId)156     static File getSystemAppsFile(Context context, int userId) {
157         return new File(context.getFilesDir() + File.separator + "system_apps"
158                 + File.separator + "user" + userId + ".xml");
159     }
160 }
161