summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ben Gruver <bgruv@google.com> 2013-08-06 20:02:30 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2013-08-06 20:02:30 +0000
commit0dff7064897afd4e07993bac28ae877aaeb1b5e3 (patch)
tree72babedd3360513f6d8c1053741e4ac6d20ccb69
parent4373232037606285fc44b816b57c34c95ca444b4 (diff)
parentb7c1a17846a306deef62855630bca9f061dc9372 (diff)
Merge "Read intent firewall rules from any xml file in the ifw directory"
-rw-r--r--services/java/com/android/server/firewall/IntentFirewall.java150
-rw-r--r--services/java/com/android/server/updates/IntentFirewallInstallReceiver.java5
2 files changed, 75 insertions, 80 deletions
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/java/com/android/server/firewall/IntentFirewall.java
index 4496aae7b6e4..ab4ac042dce1 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/java/com/android/server/firewall/IntentFirewall.java
@@ -48,9 +48,8 @@ import java.util.List;
public class IntentFirewall {
private static final String TAG = "IntentFirewall";
- // e.g. /data/system/ifw/ifw.xml or /data/secure/system/ifw/ifw.xml
- private static final File RULES_FILE =
- new File(Environment.getSystemSecureDirectory(), "ifw/ifw.xml");
+ // e.g. /data/system/ifw or /data/secure/system/ifw
+ private static final File RULES_DIR = new File(Environment.getSystemSecureDirectory(), "ifw");
private static final int LOG_PACKAGES_MAX_LENGTH = 150;
private static final int LOG_PACKAGES_SUFFICIENT_LENGTH = 125;
@@ -106,12 +105,12 @@ public class IntentFirewall {
public IntentFirewall(AMSInterface ams) {
mAms = ams;
- File rulesFile = getRulesFile();
- rulesFile.getParentFile().mkdirs();
+ File rulesDir = getRulesDir();
+ rulesDir.mkdirs();
- readRules(rulesFile);
+ readRulesDir(rulesDir);
- mObserver = new RuleObserver(rulesFile);
+ mObserver = new RuleObserver(rulesDir);
mObserver.startWatching();
}
@@ -216,22 +215,58 @@ public class IntentFirewall {
return null;
}
- public static File getRulesFile() {
- return RULES_FILE;
+ public static File getRulesDir() {
+ return RULES_DIR;
}
/**
- * Reads rules from the given file and replaces our set of rules with the newly read rules
+ * Reads rules from all xml files (*.xml) in the given directory, and replaces our set of rules
+ * with the newly read rules.
+ *
+ * We only check for files ending in ".xml", to allow for temporary files that are atomically
+ * renamed to .xml
*
* All calls to this method from the file observer come through a handler and are inherently
* serialized
*/
- private void readRules(File rulesFile) {
+ private void readRulesDir(File rulesDir) {
FirewallIntentResolver[] resolvers = new FirewallIntentResolver[3];
for (int i=0; i<resolvers.length; i++) {
resolvers[i] = new FirewallIntentResolver();
}
+ File[] files = rulesDir.listFiles();
+ for (int i=0; i<files.length; i++) {
+ File file = files[i];
+
+ if (file.getName().endsWith(".xml")) {
+ readRules(file, resolvers);
+ }
+ }
+
+ Slog.i(TAG, "Read new rules (A:" + resolvers[TYPE_ACTIVITY].filterSet().size() +
+ " B:" + resolvers[TYPE_BROADCAST].filterSet().size() +
+ " S:" + resolvers[TYPE_SERVICE].filterSet().size() + ")");
+
+ synchronized (mAms.getAMSLock()) {
+ mActivityResolver = resolvers[TYPE_ACTIVITY];
+ mBroadcastResolver = resolvers[TYPE_BROADCAST];
+ mServiceResolver = resolvers[TYPE_SERVICE];
+ }
+ }
+
+ /**
+ * Reads rules from the given file and add them to the given resolvers
+ */
+ private void readRules(File rulesFile, FirewallIntentResolver[] resolvers) {
+ // some temporary lists to hold the rules while we parse the xml file, so that we can
+ // add the rules all at once, after we know there weren't any major structural problems
+ // with the xml file
+ List<List<Rule>> rulesByType = new ArrayList<List<Rule>>(3);
+ for (int i=0; i<3; i++) {
+ rulesByType.add(new ArrayList<Rule>());
+ }
+
FileInputStream fis;
try {
fis = new FileInputStream(rulesFile);
@@ -247,8 +282,6 @@ public class IntentFirewall {
XmlUtils.beginDocument(parser, TAG_RULES);
- int[] numRules = new int[3];
-
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
int ruleType = -1;
@@ -265,41 +298,28 @@ public class IntentFirewall {
if (ruleType != -1) {
Rule rule = new Rule();
- FirewallIntentResolver resolver = resolvers[ruleType];
+ List<Rule> rules = rulesByType.get(ruleType);
// if we get an error while parsing a particular rule, we'll just ignore
// that rule and continue on with the next rule
try {
rule.readFromXml(parser);
} catch (XmlPullParserException ex) {
- Slog.e(TAG, "Error reading intent firewall rule", ex);
+ Slog.e(TAG, "Error reading an intent firewall rule from " + rulesFile, ex);
continue;
}
- numRules[ruleType]++;
-
- for (int i=0; i<rule.getIntentFilterCount(); i++) {
- resolver.addFilter(rule.getIntentFilter(i));
- }
+ rules.add(rule);
}
}
-
- Slog.i(TAG, "Read new rules (A:" + numRules[TYPE_ACTIVITY] +
- " B:" + numRules[TYPE_BROADCAST] + " S:" + numRules[TYPE_SERVICE] + ")");
-
- synchronized (mAms.getAMSLock()) {
- mActivityResolver = resolvers[TYPE_ACTIVITY];
- mBroadcastResolver = resolvers[TYPE_BROADCAST];
- mServiceResolver = resolvers[TYPE_SERVICE];
- }
} catch (XmlPullParserException ex) {
// if there was an error outside of a specific rule, then there are probably
// structural problems with the xml file, and we should completely ignore it
- Slog.e(TAG, "Error reading intent firewall rules", ex);
- clearRules();
+ Slog.e(TAG, "Error reading intent firewall rules from " + rulesFile, ex);
+ return;
} catch (IOException ex) {
- Slog.e(TAG, "Error reading intent firewall rules", ex);
- clearRules();
+ Slog.e(TAG, "Error reading intent firewall rules from " + rulesFile, ex);
+ return;
} finally {
try {
fis.close();
@@ -307,21 +327,17 @@ public class IntentFirewall {
Slog.e(TAG, "Error while closing " + rulesFile, ex);
}
}
- }
- /**
- * Clears out all of our rules
- *
- * All calls to this method from the file observer come through a handler and are inherently
- * serialized
- */
- private void clearRules() {
- Slog.i(TAG, "Clearing all rules");
+ for (int ruleType=0; ruleType<rulesByType.size(); ruleType++) {
+ List<Rule> rules = rulesByType.get(ruleType);
+ FirewallIntentResolver resolver = resolvers[ruleType];
- synchronized (mAms.getAMSLock()) {
- mActivityResolver = new FirewallIntentResolver();
- mBroadcastResolver = new FirewallIntentResolver();
- mServiceResolver = new FirewallIntentResolver();
+ for (int ruleIndex=0; ruleIndex<rules.size(); ruleIndex++) {
+ Rule rule = rules.get(ruleIndex);
+ for (int filterIndex=0; filterIndex<rule.getIntentFilterCount(); filterIndex++) {
+ resolver.addFilter(rule.getIntentFilter(filterIndex));
+ }
+ }
}
}
@@ -421,54 +437,32 @@ public class IntentFirewall {
}
}
- private static final int READ_RULES = 0;
- private static final int CLEAR_RULES = 1;
-
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case READ_RULES:
- readRules(getRulesFile());
- break;
- case CLEAR_RULES:
- clearRules();
- break;
- }
+ readRulesDir(getRulesDir());
}
};
/**
- * Monitors for the creation/deletion/modification of the rule file
+ * Monitors for the creation/deletion/modification of any .xml files in the rule directory
*/
private class RuleObserver extends FileObserver {
- // The file name we're monitoring, with no path component
- private final String mMonitoredFile;
+ private static final int MONITORED_EVENTS = FileObserver.CREATE|FileObserver.MOVED_TO|
+ FileObserver.CLOSE_WRITE|FileObserver.DELETE|FileObserver.MOVED_FROM;
- private static final int CREATED_FLAGS = FileObserver.CREATE|FileObserver.MOVED_TO|
- FileObserver.CLOSE_WRITE;
- private static final int DELETED_FLAGS = FileObserver.DELETE|FileObserver.MOVED_FROM;
-
- public RuleObserver(File monitoredFile) {
- super(monitoredFile.getParentFile().getAbsolutePath(), CREATED_FLAGS|DELETED_FLAGS);
- mMonitoredFile = monitoredFile.getName();
+ public RuleObserver(File monitoredDir) {
+ super(monitoredDir.getAbsolutePath(), MONITORED_EVENTS);
}
@Override
public void onEvent(int event, String path) {
- if (path.equals(mMonitoredFile)) {
+ if (path.endsWith(".xml")) {
// we wait 250ms before taking any action on an event, in order to dedup multiple
// events. E.g. a delete event followed by a create event followed by a subsequent
- // write+close event;
- if ((event & CREATED_FLAGS) != 0) {
- mHandler.removeMessages(READ_RULES);
- mHandler.removeMessages(CLEAR_RULES);
- mHandler.sendEmptyMessageDelayed(READ_RULES, 250);
- } else if ((event & DELETED_FLAGS) != 0) {
- mHandler.removeMessages(READ_RULES);
- mHandler.removeMessages(CLEAR_RULES);
- mHandler.sendEmptyMessageDelayed(CLEAR_RULES, 250);
- }
+ // write+close event
+ mHandler.removeMessages(0);
+ mHandler.sendEmptyMessageDelayed(0, 250);
}
}
}
diff --git a/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java b/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java
index 91859033272a..0b54f92103dd 100644
--- a/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java
+++ b/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java
@@ -21,7 +21,8 @@ import com.android.server.firewall.IntentFirewall;
public class IntentFirewallInstallReceiver extends ConfigUpdateInstallReceiver {
public IntentFirewallInstallReceiver() {
- super(IntentFirewall.getRulesFile().getParent(), IntentFirewall.getRulesFile().getName(),
- "metadata/", "version");
+ // TODO: should we dynamically generate a filename and store the name in metadata?
+ super(IntentFirewall.getRulesDir().getAbsolutePath(), "ifw.xml", "metadata/",
+ "gservices.version");
}
}