OSDN Git Service

Add network access blocking when in battery save mode.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / SystemConfig.java
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;
18
19 import android.content.pm.FeatureInfo;
20 import android.os.*;
21 import android.os.Process;
22 import android.util.ArrayMap;
23 import android.util.ArraySet;
24 import android.util.Slog;
25 import android.util.SparseArray;
26 import android.util.Xml;
27 import com.android.internal.util.XmlUtils;
28 import org.xmlpull.v1.XmlPullParser;
29 import org.xmlpull.v1.XmlPullParserException;
30
31 import java.io.File;
32 import java.io.FileNotFoundException;
33 import java.io.FileReader;
34 import java.io.IOException;
35 import java.util.HashMap;
36 import java.util.HashSet;
37
38 import static com.android.internal.util.ArrayUtils.appendInt;
39
40 /**
41  * Loads global system configuration info.
42  */
43 public class SystemConfig {
44     static final String TAG = "SystemConfig";
45
46     static SystemConfig sInstance;
47
48     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
49     int[] mGlobalGids;
50
51     // These are the built-in uid -> permission mappings that were read from the
52     // system configuration files.
53     final SparseArray<HashSet<String>> mSystemPermissions =
54             new SparseArray<HashSet<String>>();
55
56     // These are the built-in shared libraries that were read from the
57     // system configuration files.  Keys are the library names; strings are the
58     // paths to the libraries.
59     final ArrayMap<String, String> mSharedLibraries
60             = new ArrayMap<String, String>();
61
62     // These are the features this devices supports that were read from the
63     // system configuration files.
64     final HashMap<String, FeatureInfo> mAvailableFeatures =
65             new HashMap<String, FeatureInfo>();
66
67     public static final class PermissionEntry {
68         public final String name;
69         public int[] gids;
70
71         PermissionEntry(String _name) {
72             name = _name;
73         }
74     }
75
76     // These are the permission -> gid mappings that were read from the
77     // system configuration files.
78     final ArrayMap<String, PermissionEntry> mPermissions =
79             new ArrayMap<String, PermissionEntry>();
80
81     // These are the packages that are white-listed to be able to run in the
82     // background while in power save mode, as read from the configuration files.
83     final ArraySet<String> mAllowInPowerSave = new ArraySet<String>();
84
85     public static SystemConfig getInstance() {
86         synchronized (SystemConfig.class) {
87             if (sInstance == null) {
88                 sInstance = new SystemConfig();
89             }
90             return sInstance;
91         }
92     }
93
94     public int[] getGlobalGids() {
95         return mGlobalGids;
96     }
97
98     public SparseArray<HashSet<String>> getSystemPermissions() {
99         return mSystemPermissions;
100     }
101
102     public ArrayMap<String, String> getSharedLibraries() {
103         return mSharedLibraries;
104     }
105
106     public HashMap<String, FeatureInfo> getAvailableFeatures() {
107         return mAvailableFeatures;
108     }
109
110     public ArrayMap<String, PermissionEntry> getPermissions() {
111         return mPermissions;
112     }
113
114     public ArraySet<String> getAllowInPowerSave() {
115         return mAllowInPowerSave;
116     }
117
118     SystemConfig() {
119         // Read configuration from system
120         readPermissions(Environment.buildPath(
121                 Environment.getRootDirectory(), "etc", "sysconfig"), false);
122         // Read configuration from the old permissions dir
123         readPermissions(Environment.buildPath(
124                 Environment.getRootDirectory(), "etc", "permissions"), false);
125         // Only read features from OEM config
126         readPermissions(Environment.buildPath(
127                 Environment.getOemDirectory(), "etc", "sysconfig"), true);
128         readPermissions(Environment.buildPath(
129                 Environment.getOemDirectory(), "etc", "permissions"), true);
130     }
131
132     void readPermissions(File libraryDir, boolean onlyFeatures) {
133         // Read permissions from given directory.
134         if (!libraryDir.exists() || !libraryDir.isDirectory()) {
135             if (!onlyFeatures) {
136                 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
137             }
138             return;
139         }
140         if (!libraryDir.canRead()) {
141             Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
142             return;
143         }
144
145         // Iterate over the files in the directory and scan .xml files
146         for (File f : libraryDir.listFiles()) {
147             // We'll read platform.xml last
148             if (f.getPath().endsWith("etc/permissions/platform.xml")) {
149                 continue;
150             }
151
152             if (!f.getPath().endsWith(".xml")) {
153                 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
154                 continue;
155             }
156             if (!f.canRead()) {
157                 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
158                 continue;
159             }
160
161             readPermissionsFromXml(f, onlyFeatures);
162         }
163
164         // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
165         final File permFile = new File(Environment.getRootDirectory(),
166                 "etc/permissions/platform.xml");
167         readPermissionsFromXml(permFile, onlyFeatures);
168     }
169
170     private void readPermissionsFromXml(File permFile, boolean onlyFeatures) {
171         FileReader permReader = null;
172         try {
173             permReader = new FileReader(permFile);
174         } catch (FileNotFoundException e) {
175             Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
176             return;
177         }
178
179         try {
180             XmlPullParser parser = Xml.newPullParser();
181             parser.setInput(permReader);
182
183             int type;
184             while ((type=parser.next()) != parser.START_TAG
185                        && type != parser.END_DOCUMENT) {
186                 ;
187             }
188
189             if (type != parser.START_TAG) {
190                 throw new XmlPullParserException("No start tag found");
191             }
192
193             if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
194                 throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
195                         ", expected 'permissions' or 'config'");
196             }
197
198             while (true) {
199                 XmlUtils.nextElement(parser);
200                 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
201                     break;
202                 }
203
204                 String name = parser.getName();
205                 if ("group".equals(name) && !onlyFeatures) {
206                     String gidStr = parser.getAttributeValue(null, "gid");
207                     if (gidStr != null) {
208                         int gid = android.os.Process.getGidForName(gidStr);
209                         mGlobalGids = appendInt(mGlobalGids, gid);
210                     } else {
211                         Slog.w(TAG, "<group> without gid at "
212                                 + parser.getPositionDescription());
213                     }
214
215                     XmlUtils.skipCurrentTag(parser);
216                     continue;
217                 } else if ("permission".equals(name) && !onlyFeatures) {
218                     String perm = parser.getAttributeValue(null, "name");
219                     if (perm == null) {
220                         Slog.w(TAG, "<permission> without name at "
221                                 + parser.getPositionDescription());
222                         XmlUtils.skipCurrentTag(parser);
223                         continue;
224                     }
225                     perm = perm.intern();
226                     readPermission(parser, perm);
227
228                 } else if ("assign-permission".equals(name) && !onlyFeatures) {
229                     String perm = parser.getAttributeValue(null, "name");
230                     if (perm == null) {
231                         Slog.w(TAG, "<assign-permission> without name at "
232                                 + parser.getPositionDescription());
233                         XmlUtils.skipCurrentTag(parser);
234                         continue;
235                     }
236                     String uidStr = parser.getAttributeValue(null, "uid");
237                     if (uidStr == null) {
238                         Slog.w(TAG, "<assign-permission> without uid at "
239                                 + parser.getPositionDescription());
240                         XmlUtils.skipCurrentTag(parser);
241                         continue;
242                     }
243                     int uid = Process.getUidForName(uidStr);
244                     if (uid < 0) {
245                         Slog.w(TAG, "<assign-permission> with unknown uid \""
246                                 + uidStr + "\" at "
247                                 + parser.getPositionDescription());
248                         XmlUtils.skipCurrentTag(parser);
249                         continue;
250                     }
251                     perm = perm.intern();
252                     HashSet<String> perms = mSystemPermissions.get(uid);
253                     if (perms == null) {
254                         perms = new HashSet<String>();
255                         mSystemPermissions.put(uid, perms);
256                     }
257                     perms.add(perm);
258                     XmlUtils.skipCurrentTag(parser);
259
260                 } else if ("library".equals(name) && !onlyFeatures) {
261                     String lname = parser.getAttributeValue(null, "name");
262                     String lfile = parser.getAttributeValue(null, "file");
263                     if (lname == null) {
264                         Slog.w(TAG, "<library> without name at "
265                                 + parser.getPositionDescription());
266                     } else if (lfile == null) {
267                         Slog.w(TAG, "<library> without file at "
268                                 + parser.getPositionDescription());
269                     } else {
270                         //Log.i(TAG, "Got library " + lname + " in " + lfile);
271                         mSharedLibraries.put(lname, lfile);
272                     }
273                     XmlUtils.skipCurrentTag(parser);
274                     continue;
275
276                 } else if ("feature".equals(name)) {
277                     String fname = parser.getAttributeValue(null, "name");
278                     if (fname == null) {
279                         Slog.w(TAG, "<feature> without name at "
280                                 + parser.getPositionDescription());
281                     } else {
282                         //Log.i(TAG, "Got feature " + fname);
283                         FeatureInfo fi = new FeatureInfo();
284                         fi.name = fname;
285                         mAvailableFeatures.put(fname, fi);
286                     }
287                     XmlUtils.skipCurrentTag(parser);
288                     continue;
289
290                 } else if ("allow-in-power-save".equals(name)) {
291                     String pkgname = parser.getAttributeValue(null, "package");
292                     if (pkgname == null) {
293                         Slog.w(TAG, "<allow-in-power-save> without package at "
294                                 + parser.getPositionDescription());
295                     } else {
296                         mAllowInPowerSave.add(pkgname);
297                     }
298                     XmlUtils.skipCurrentTag(parser);
299                     continue;
300
301                 } else {
302                     XmlUtils.skipCurrentTag(parser);
303                     continue;
304                 }
305
306             }
307             permReader.close();
308         } catch (XmlPullParserException e) {
309             Slog.w(TAG, "Got execption parsing permissions.", e);
310         } catch (IOException e) {
311             Slog.w(TAG, "Got execption parsing permissions.", e);
312         }
313     }
314
315     void readPermission(XmlPullParser parser, String name)
316             throws IOException, XmlPullParserException {
317
318         name = name.intern();
319
320         PermissionEntry perm = mPermissions.get(name);
321         if (perm == null) {
322             perm = new PermissionEntry(name);
323             mPermissions.put(name, perm);
324         }
325         int outerDepth = parser.getDepth();
326         int type;
327         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
328                && (type != XmlPullParser.END_TAG
329                        || parser.getDepth() > outerDepth)) {
330             if (type == XmlPullParser.END_TAG
331                     || type == XmlPullParser.TEXT) {
332                 continue;
333             }
334
335             String tagName = parser.getName();
336             if ("group".equals(tagName)) {
337                 String gidStr = parser.getAttributeValue(null, "gid");
338                 if (gidStr != null) {
339                     int gid = Process.getGidForName(gidStr);
340                     perm.gids = appendInt(perm.gids, gid);
341                 } else {
342                     Slog.w(TAG, "<group> without gid at "
343                             + parser.getPositionDescription());
344                 }
345             }
346             XmlUtils.skipCurrentTag(parser);
347         }
348     }
349 }