Adding attributes and intent filters to BroadcastReceiverData and ServiceData as parsed from the Android manifest.
diff --git a/resources/src/main/java/org/robolectric/manifest/ActivityData.java b/resources/src/main/java/org/robolectric/manifest/ActivityData.java
index 7088115..0da5d19 100644
--- a/resources/src/main/java/org/robolectric/manifest/ActivityData.java
+++ b/resources/src/main/java/org/robolectric/manifest/ActivityData.java
@@ -15,7 +15,6 @@
   private static final String EXPORTED = "exported";
   private static final String FINISH_ON_TASK_LAUNCH = "finishOnTaskLaunch";
   private static final String HARDWARE_ACCELERATED = "hardwareAccelerated";
-  private static final String ICON = "icon";
   private static final String LABEL = "label";
   private static final String LAUNCH_MODE = "launchMode";
   private static final String MULTIPROCESS = "multiprocess";
@@ -86,7 +85,7 @@
   }
 
   public boolean isExported() {
-    boolean defaultValue = false;
+    boolean defaultValue = !intentFilters.isEmpty();
     return getBooleanAttr(withXMLNS(EXPORTED), defaultValue);
   }
 
diff --git a/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java b/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java
index e4f6b41..7fb1054 100644
--- a/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java
+++ b/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java
@@ -243,15 +243,32 @@
     return attributeNode == null ? null : attributeNode.getTextContent();
   }
 
+  private static HashMap<String, String> parseNodeAttributes(Node node) {
+    final NamedNodeMap attributes = node.getAttributes();
+    final int attrCount = attributes.getLength();
+    final HashMap<String, String> receiverAttrs = new HashMap<>(attributes.getLength());
+    for (int i = 0; i < attrCount; i++) {
+      Node attribute = attributes.item(i);
+      String value = attribute.getNodeValue();
+      if (value != null) {
+        receiverAttrs.put(attribute.getNodeName(), value);
+      }
+    }
+    return receiverAttrs;
+  }
+
   private void parseReceivers(Node applicationNode) {
     for (Node receiverNode : getChildrenTags(applicationNode, "receiver")) {
-      Node namedItem = receiverNode.getAttributes().getNamedItem("android:name");
-      if (namedItem == null) continue;
+      final HashMap<String, String> receiverAttrs = parseNodeAttributes(receiverNode);
 
-      String receiverName = resolveClassRef(namedItem.getTextContent());
+      String receiverName = resolveClassRef(receiverAttrs.get("android:name"));
+      receiverAttrs.put("android:name", receiverName);
+
       MetaData metaData = new MetaData(getChildrenTags(receiverNode, "meta-data"));
 
-      BroadcastReceiverData receiver = new BroadcastReceiverData(receiverName, metaData);
+      final List<IntentFilterData> intentFilterData = parseIntentFilters(receiverNode);
+      BroadcastReceiverData receiver =
+          new BroadcastReceiverData(receiverAttrs, metaData, intentFilterData);
       List<Node> intentFilters = getChildrenTags(receiverNode, "intent-filter");
       for (Node intentFilterNode : intentFilters) {
         for (Node actionNode : getChildrenTags(intentFilterNode, "action")) {
@@ -261,26 +278,22 @@
           }
         }
       }
-      
-      Node permissionItem = receiverNode.getAttributes().getNamedItem("android:permission");
-      if (permissionItem != null) {
-        receiver.setPermission(permissionItem.getTextContent());
-      }
-      
+
       receivers.add(receiver);
     }
   }
 
   private void parseServices(Node applicationNode) {
     for (Node serviceNode : getChildrenTags(applicationNode, "service")) {
-      Node namedItem = serviceNode.getAttributes().getNamedItem("android:name");
-      if (namedItem == null) continue;
+      final HashMap<String, String> serviceAttrs = parseNodeAttributes(serviceNode);
 
-      String serviceName = resolveClassRef(namedItem.getTextContent());
+      String serviceName = resolveClassRef(serviceAttrs.get("android:name"));
+      serviceAttrs.put("android:name", serviceName);
+
       MetaData metaData = new MetaData(getChildrenTags(serviceNode, "meta-data"));
 
       final List<IntentFilterData> intentFilterData = parseIntentFilters(serviceNode);
-      ServiceData service = new ServiceData(serviceName, metaData, intentFilterData);
+      ServiceData service = new ServiceData(serviceAttrs, metaData, intentFilterData);
       List<Node> intentFilters = getChildrenTags(serviceNode, "intent-filter");
       for (Node intentFilterNode : intentFilters) {
         for (Node actionNode : getChildrenTags(intentFilterNode, "action")) {
@@ -291,10 +304,6 @@
         }
       }
 
-      Node permissionItem = serviceNode.getAttributes().getNamedItem("android:permission");
-      if (permissionItem != null) {
-        service.setPermission(permissionItem.getTextContent());
-      }
       serviceDatas.put(serviceName, service);
     }
   }
@@ -318,18 +327,9 @@
   }
 
   private void parseActivity(Node activityNode, boolean isAlias) {
-    final NamedNodeMap attributes = activityNode.getAttributes();
-    final int attrCount = attributes.getLength();
     final List<IntentFilterData> intentFilterData = parseIntentFilters(activityNode);
     final MetaData metaData = new MetaData(getChildrenTags(activityNode, "meta-data"));
-    final HashMap<String, String> activityAttrs = new HashMap<>(attrCount);
-    for(int i = 0; i < attrCount; i++) {
-      Node attr = attributes.item(i);
-      String v = attr.getNodeValue();
-      if( v != null) {
-        activityAttrs.put(attr.getNodeName(), v);
-      }
-    }
+    final HashMap<String, String> activityAttrs = parseNodeAttributes(activityNode);
 
     String activityName = resolveClassRef(activityAttrs.get(ActivityData.getNameAttr("android")));
     if (activityName == null) {
@@ -596,6 +596,7 @@
   }
 
   public ServiceData getServiceData(String serviceClassName) {
+    parseAndroidManifest();
     return serviceDatas.get(serviceClassName);
   }
 
@@ -659,4 +660,21 @@
     parseAndroidManifest();
     return permissions;
   }
+
+  /**
+   * Returns data for the broadcast receiver with the provided name from this manifest. If no
+   * receiver with the class name can be found, returns null.
+   *
+   * @param className the fully resolved class name of the receiver
+   * @return data for the receiver or null if it cannot be found
+   */
+  public @Nullable BroadcastReceiverData getBroadcastReceiver(String className) {
+    parseAndroidManifest();
+    for (BroadcastReceiverData receiver : receivers) {
+      if (receiver.getClassName().equals(className)) {
+        return receiver;
+      }
+    }
+    return null;
+  }
 }
diff --git a/resources/src/main/java/org/robolectric/manifest/BroadcastReceiverData.java b/resources/src/main/java/org/robolectric/manifest/BroadcastReceiverData.java
index 9d549de..37b0863 100644
--- a/resources/src/main/java/org/robolectric/manifest/BroadcastReceiverData.java
+++ b/resources/src/main/java/org/robolectric/manifest/BroadcastReceiverData.java
@@ -1,15 +1,35 @@
 package org.robolectric.manifest;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
 
 public class BroadcastReceiverData extends PackageItemData {
+
+  private static final String EXPORTED = "android:exported";
+  private static final String NAME = "android:name";
+  private static final String PERMISSION = "android:permission";
+
+  private final Map<String, String> attributes;
   private final List<String> actions;
-  private String permission;
+  private List<IntentFilterData> intentFilters;
+
+  public BroadcastReceiverData(
+      Map<String, String> attributes, MetaData metaData, List<IntentFilterData> intentFilters) {
+    super(attributes.get(NAME), metaData);
+    this.attributes = attributes;
+    this.actions = new ArrayList<>();
+    this.intentFilters = new LinkedList<>(intentFilters);
+  }
 
   public BroadcastReceiverData(String className, MetaData metaData) {
     super(className, metaData);
     this.actions = new ArrayList<>();
+    this.attributes = new HashMap<>();
+    intentFilters = new LinkedList<>();
   }
 
   public List<String> getActions() {
@@ -21,10 +41,42 @@
   }
 
   public void setPermission(final String permission) {
-    this.permission = permission;
+    attributes.put(PERMISSION, permission);
   }
 
   public String getPermission() {
-    return permission;
+    return attributes.get(PERMISSION);
+  }
+
+  /**
+   * Get the intent filters defined for the broadcast receiver.
+   *
+   * @return A list of intent filters.
+   */
+  @Nonnull
+  public List<IntentFilterData> getIntentFilters() {
+    return intentFilters;
+  }
+
+  /**
+   * Get the map for all attributes defined for the broadcast receiver.
+   *
+   * @return map of attributes names to values from the manifest.
+   */
+  @Nonnull
+  public Map<String, String> getAllAttributes() {
+    return attributes;
+  }
+
+  /**
+   * Returns whether this broadcast receiver is exported by checking the XML attribute.
+   *
+   * @return true if the broadcast receiver is exported
+   */
+  public boolean isExported() {
+    boolean defaultValue = !intentFilters.isEmpty();
+    return (attributes.containsKey(EXPORTED)
+        ? Boolean.parseBoolean(attributes.get(EXPORTED))
+        : defaultValue);
   }
 }
diff --git a/resources/src/main/java/org/robolectric/manifest/ServiceData.java b/resources/src/main/java/org/robolectric/manifest/ServiceData.java
index cde5bcc..b763595 100644
--- a/resources/src/main/java/org/robolectric/manifest/ServiceData.java
+++ b/resources/src/main/java/org/robolectric/manifest/ServiceData.java
@@ -1,25 +1,41 @@
 package org.robolectric.manifest;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
 
 public class ServiceData {
-  private final String className;
+
+  private static final String EXPORTED = "android:exported";
+  private static final String NAME = "android:name";
+  private static final String PERMISSION = "android:permission";
+
+  private final Map<String, String> attributes;
   private final MetaData metaData;
   private final List<String> actions;
-  private String permission;
   private List<IntentFilterData> intentFilters;
 
-  public ServiceData(String className, MetaData metaData, List<IntentFilterData> intentFilterData) {
+  public ServiceData(
+      Map<String, String> attributes, MetaData metaData, List<IntentFilterData> intentFilters) {
+    this.attributes = attributes;
     this.actions = new ArrayList<>();
-    this.className = className;
+    this.metaData = metaData;
+    this.intentFilters = new LinkedList<>(intentFilters);
+  }
+
+  public ServiceData(String className, MetaData metaData, List<IntentFilterData> intentFilterData) {
+    this.attributes = new HashMap<>();
+    this.attributes.put(NAME, className);
+    this.actions = new ArrayList<>();
     this.metaData = metaData;
     intentFilters = new LinkedList<>(intentFilterData);
   }
 
   public String getClassName() {
-    return className;
+    return attributes.get(NAME);
   }
 
   public List<String> getActions() {
@@ -35,18 +51,42 @@
   }
 
   public void setPermission(final String permission) {
-    this.permission = permission;
+    attributes.put(PERMISSION, permission);
   }
 
   public String getPermission() {
-    return permission;
+    return attributes.get(PERMISSION);
   }
 
   /**
-   * Get the intent filters defined for activity.
-   * @return A list of intent filters. Not null.
+   * Get the intent filters defined for the service.
+   *
+   * @return A list of intent filters.
    */
+  @Nonnull
   public List<IntentFilterData> getIntentFilters() {
     return intentFilters;
   }
+
+  /**
+   * Get the map for all attributes defined for the service.
+   *
+   * @return map of attributes names to values from the manifest.
+   */
+  @Nonnull
+  public Map<String, String> getAllAttributes() {
+    return attributes;
+  }
+
+  /**
+   * Returns whether this service is exported by checking the XML attribute.
+   *
+   * @return true if the service is exported
+   */
+  public boolean isExported() {
+    boolean defaultValue = !intentFilters.isEmpty();
+    return (attributes.containsKey(EXPORTED)
+        ? Boolean.parseBoolean(attributes.get(EXPORTED))
+        : defaultValue);
+  }
 }
diff --git a/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java b/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java
index b95f867..5536648 100644
--- a/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java
+++ b/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java
@@ -76,6 +76,9 @@
 
     assertThat(config.getBroadcastReceivers().get(5).getClassName()).isEqualTo("com.foo.Receiver");
     assertThat(config.getBroadcastReceivers().get(5).getActions()).contains("org.robolectric.ACTION_DIFFERENT_PACKAGE");
+    assertThat(config.getBroadcastReceivers().get(5).getIntentFilters()).hasSize(1);
+    IntentFilterData filter = config.getBroadcastReceivers().get(5).getIntentFilters().get(0);
+    assertThat(filter.getActions()).containsExactly("org.robolectric.ACTION_DIFFERENT_PACKAGE");
 
     assertThat(config.getBroadcastReceivers().get(6).getClassName()).isEqualTo("com.bar.ReceiverWithoutIntentFilter");
     assertThat(config.getBroadcastReceivers().get(6).getActions()).isEmpty();
@@ -100,7 +103,7 @@
 
     assertThat(config.getServiceData("com.foo.Service").getClassName()).isEqualTo("com.foo.Service");
     assertThat(config.getServiceData("com.bar.ServiceWithoutIntentFilter").getClassName()).isEqualTo("com.bar.ServiceWithoutIntentFilter");
-    assertEquals(config.getServiceData("com.foo.Service").getPermission(), "com.foo.Permission");
+    assertThat(config.getServiceData("com.foo.Service").getPermission()).isEqualTo("com.foo.Permission");
   }
 
   @Test
@@ -248,7 +251,7 @@
   @Test
   public void shouldTolerateMissingRFile() throws Exception {
     AndroidManifest appManifest = new AndroidManifest(resourceFile("TestAndroidManifestWithNoRFile.xml"), resourceFile("res"), resourceFile("assets"));
-    assertEquals(appManifest.getPackageName(), "org.no.resources.for.me");
+    assertThat(appManifest.getPackageName()).isEqualTo("org.no.resources.for.me");
     assertThat(appManifest.getRClass()).isNull();
   }
 
@@ -424,6 +427,51 @@
     assertThat(wrongFields).isEmpty();
   }
 
+  @Test
+  public void activitiesWithoutIntentFiltersNotExportedByDefault() throws Exception {
+    AndroidManifest config = newConfig("TestAndroidManifestForActivities.xml");
+    ActivityData activityData = config.getActivityData("org.robolectric.shadows.TestActivity");
+    assertThat(activityData.isExported()).isFalse();
+  }
+
+  @Test
+  public void activitiesWithIntentFiltersExportedByDefault() throws Exception {
+    AndroidManifest config = newConfig("TestAndroidManifestForActivitiesWithIntentFilter.xml");
+    ActivityData activityData = config.getActivityData("org.robolectric.shadows.TestActivity");
+    assertThat(activityData.isExported()).isTrue();
+  }
+
+  @Test
+  public void servicesWithoutIntentFiltersNotExportedByDefault() throws Exception {
+    AndroidManifest config = newConfig("TestAndroidManifestWithServices.xml");
+    ServiceData serviceData = config.getServiceData("com.bar.ServiceWithoutIntentFilter");
+    assertThat(serviceData.isExported()).isFalse();
+  }
+
+  @Test
+  public void servicesWithIntentFiltersExportedByDefault() throws Exception {
+    AndroidManifest config = newConfig("TestAndroidManifestWithServices.xml");
+    ServiceData serviceData = config.getServiceData("com.foo.Service");
+    assertThat(serviceData.isExported()).isTrue();
+  }
+
+  @Test
+  public void receiversWithoutIntentFiltersNotExportedByDefault() throws Exception {
+    AndroidManifest config = newConfig("TestAndroidManifestWithReceivers.xml");
+    BroadcastReceiverData receiverData =
+        config.getBroadcastReceiver("com.bar.ReceiverWithoutIntentFilter");
+    assertThat(receiverData).isNotNull();
+    assertThat(receiverData.isExported()).isFalse();
+  }
+
+  @Test
+  public void receiversWithIntentFiltersExportedByDefault() throws Exception {
+    AndroidManifest config = newConfig("TestAndroidManifestWithReceivers.xml");
+    BroadcastReceiverData receiverData = config.getBroadcastReceiver("com.foo.Receiver");
+    assertThat(receiverData).isNotNull();
+    assertThat(receiverData.isExported()).isTrue();
+  }
+
   /////////////////////////////
 
   private AndroidManifest newConfigWith(String fileName, String usesSdkAttrs) throws IOException {