summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoravellore <avellore@google.com>2015-12-08 19:12:29 -0800
committeravellore <avellore@google.com>2016-01-11 13:49:25 -0800
commit47682ace745705d3592a5681fa6400661991ca16 (patch)
tree2aeac825ac501292b7df5a44b374eb03d963e50f
parent902c545fe48ec077ca17fde629e9b5e655e83d15 (diff)
downloadloganalysis-47682ace745705d3592a5681fa6400661991ca16.tar.gz
Add Location clients heuristics
Parse the activity service section and retrieve location usage clients Change-Id: I71fb6331be713b3b8653834feea05c88deab68b6
-rw-r--r--src/com/android/loganalysis/item/ActivityServiceItem.java53
-rw-r--r--src/com/android/loganalysis/item/BugreportItem.java17
-rw-r--r--src/com/android/loganalysis/item/LocationDumpsItem.java178
-rw-r--r--src/com/android/loganalysis/parser/ActivityServiceParser.java84
-rw-r--r--src/com/android/loganalysis/parser/BugreportParser.java6
-rw-r--r--src/com/android/loganalysis/parser/LocationServiceParser.java68
-rw-r--r--src/com/android/loganalysis/rule/LocationUsageRule.java83
-rw-r--r--src/com/android/loganalysis/rule/RuleEngine.java1
-rw-r--r--tests/src/com/android/loganalysis/item/LocationDumpsItemTest.java81
-rw-r--r--tests/src/com/android/loganalysis/parser/ActivityServiceParserTest.java60
-rw-r--r--tests/src/com/android/loganalysis/parser/BugreportParserTest.java27
-rw-r--r--tests/src/com/android/loganalysis/parser/LocationServiceParserTest.java89
12 files changed, 745 insertions, 2 deletions
diff --git a/src/com/android/loganalysis/item/ActivityServiceItem.java b/src/com/android/loganalysis/item/ActivityServiceItem.java
new file mode 100644
index 0000000..f149adf
--- /dev/null
+++ b/src/com/android/loganalysis/item/ActivityServiceItem.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.loganalysis.item;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An {@link IItem} used to store Activity Service Dumps
+ */
+public class ActivityServiceItem extends GenericItem {
+
+ /** Constant for JSON output */
+ public static final String LOCATION_DUMPS = "LOCATION";
+
+ private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
+ LOCATION_DUMPS));
+
+ /**
+ * The constructor for {@link ActivityServiceItem}.
+ */
+ public ActivityServiceItem() {
+ super(ATTRIBUTES);
+ }
+
+ /**
+ * Get the location dump
+ */
+ public LocationDumpsItem getLocationDumps() {
+ return (LocationDumpsItem) getAttribute(LOCATION_DUMPS);
+ }
+
+ /**
+ * Set the location dump
+ */
+ public void setLocationDumps(LocationDumpsItem location) {
+ setAttribute(LOCATION_DUMPS, location);
+ }
+}
diff --git a/src/com/android/loganalysis/item/BugreportItem.java b/src/com/android/loganalysis/item/BugreportItem.java
index 969c90a..e716728 100644
--- a/src/com/android/loganalysis/item/BugreportItem.java
+++ b/src/com/android/loganalysis/item/BugreportItem.java
@@ -45,10 +45,12 @@ public class BugreportItem extends GenericItem {
public static final String SYSTEM_PROPS = "SYSTEM_PROPS";
/** Constant for JSON output */
public static final String DUMPSYS = "DUMPSYS";
+ /** Constant for JSON output */
+ public static final String ACTIVITY_SERVICE = "ACTIVITY_SERVICE";
private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
TIME, COMMAND_LINE, MEM_INFO, PROCRANK, TOP, KERNEL_LOG, LAST_KMSG, SYSTEM_LOG,
- SYSTEM_PROPS, DUMPSYS));
+ SYSTEM_PROPS, DUMPSYS, ACTIVITY_SERVICE));
public static class CommandLineItem extends GenericMapItem<String> {
private static final long serialVersionUID = 0L;
@@ -200,4 +202,17 @@ public class BugreportItem extends GenericItem {
public void setDumpsys(DumpsysItem dumpsys) {
setAttribute(DUMPSYS, dumpsys);
}
+ /**
+ * Get the {@link ActivityServiceItem} of the bugreport.
+ */
+ public ActivityServiceItem getActivityService() {
+ return (ActivityServiceItem) getAttribute(ACTIVITY_SERVICE);
+ }
+
+ /**
+ * Set the {@link ActivityServiceItem} of the bugreport.
+ */
+ public void setActivityService(ActivityServiceItem activityService) {
+ setAttribute(ACTIVITY_SERVICE, activityService);
+ }
}
diff --git a/src/com/android/loganalysis/item/LocationDumpsItem.java b/src/com/android/loganalysis/item/LocationDumpsItem.java
new file mode 100644
index 0000000..580145f
--- /dev/null
+++ b/src/com/android/loganalysis/item/LocationDumpsItem.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.loganalysis.item;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+
+/**
+ * An {@link IItem} used to store location dumps.
+ */
+public class LocationDumpsItem implements IItem {
+
+ /** Constant for JSON output */
+ public static final String LOCATION_CLIENTS = "LOCATION_CLIENTS";
+
+ private Collection<LocationInfoItem> mLocationClients =
+ new LinkedList<LocationInfoItem>();
+
+ public static class LocationInfoItem extends GenericItem {
+ /** Constant for JSON output */
+ public static final String PACKAGE = "PACKAGE";
+ /** Constant for JSON output */
+ public static final String EFFECTIVE_INTERVAL = "EFFECTIVE_INTERVAL";
+ /** Constant for JSON output */
+ public static final String MIN_INTERVAL = "MIN_INTERVAL";
+ /** Constant for JSON output */
+ public static final String MAX_INTERVAL = "MAX_INTERVAL";
+ /** Constant for JSON output */
+ public static final String REQUEST_PRIORITY = "PRIORITY";
+ /** Constant for JSON output */
+ public static final String LOCATION_DURATION = "LOCATION_DURATION";
+
+ private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
+ PACKAGE, EFFECTIVE_INTERVAL, MIN_INTERVAL, MAX_INTERVAL, REQUEST_PRIORITY,
+ LOCATION_DURATION ));
+ /**
+ * The constructor for {@link LocationInfoItem}
+ *
+ * @param packageName The package that requests location
+ * @param effective Effective interval of location request
+ * @param min Min interval of location request
+ * @param max Max interval of location request
+ * @param priority The priority of the request
+ * @param duration Duration of the request
+ */
+ public LocationInfoItem(String packageName, int effective, int min, int max,
+ String priority, int duration) {
+ super(ATTRIBUTES);
+ setAttribute(PACKAGE, packageName);
+ setAttribute(EFFECTIVE_INTERVAL, effective);
+ setAttribute(MIN_INTERVAL, min);
+ setAttribute(MAX_INTERVAL, max);
+ setAttribute(REQUEST_PRIORITY, priority);
+ setAttribute(LOCATION_DURATION, duration);
+ }
+
+ /**
+ * Get the name of the package
+ */
+ public String getPackage() {
+ return (String) getAttribute(PACKAGE);
+ }
+
+ /**
+ * Get the effective location interval
+ */
+ public int getEffectiveInterval() {
+ return (int) getAttribute(EFFECTIVE_INTERVAL);
+ }
+
+ /**
+ * Get the min location interval
+ */
+ public int getMinInterval() {
+ return (int) getAttribute(MIN_INTERVAL);
+ }
+
+ /**
+ * Get the max location interval
+ */
+ public int getMaxInterval() {
+ return (int) getAttribute(MAX_INTERVAL);
+ }
+
+ /**
+ * Get the priority of location request
+ */
+ public String getPriority() {
+ return (String) getAttribute(REQUEST_PRIORITY);
+ }
+
+ /**
+ * Get the location duration
+ */
+ public int getDuration() {
+ return (int) getAttribute(LOCATION_DURATION);
+ }
+
+ }
+
+ /**
+ * Add a location client {@link LocationDumpsItem}.
+ *
+ * @param packageName The package that requests location
+ * @param effective Effective interval of location request
+ * @param min Min interval of location request
+ * @param max Max interval of location request
+ * @param priority The priority of the request
+ * @param duration Duration of the request
+ */
+ public void addLocationClient(String packageName, int effective, int min, int max,
+ String priority, int duration) {
+ mLocationClients.add(new LocationInfoItem(packageName, effective, min, max, priority,
+ duration));
+ }
+
+ public Collection<LocationInfoItem> getLocationClients() {
+ return mLocationClients;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IItem merge(IItem other) throws ConflictingItemException {
+ throw new ConflictingItemException("Location dumps items cannot be merged");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isConsistent(IItem other) {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public JSONObject toJson() {
+ JSONObject object = new JSONObject();
+ if (mLocationClients != null) {
+ try {
+ JSONArray locationClients = new JSONArray();
+ for (LocationInfoItem locationClient : mLocationClients) {
+ locationClients.put(locationClient.toJson());
+ }
+ object.put(LOCATION_CLIENTS, locationClients);
+ } catch (JSONException e) {
+ // Ignore
+ }
+ }
+
+ return object;
+ }
+}
diff --git a/src/com/android/loganalysis/parser/ActivityServiceParser.java b/src/com/android/loganalysis/parser/ActivityServiceParser.java
new file mode 100644
index 0000000..c79d6e5
--- /dev/null
+++ b/src/com/android/loganalysis/parser/ActivityServiceParser.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.LocationDumpsItem;
+import com.android.loganalysis.item.ActivityServiceItem;
+
+import java.util.List;
+
+/**
+ * A {@link IParser} to parse the activity service dump section of the bugreport
+ */
+public class ActivityServiceParser extends AbstractSectionParser {
+
+ private static final String LOCATION_SECTION_REGEX =
+ "^\\s*SERVICE com.google.android.gms/"
+ + "com.google.android.location.internal.GoogleLocationManagerService \\w+ pid=\\d+";
+
+ private static final String NOOP_SECTION_REGEX = "^\\s*SERVICE .*/.*";
+
+ private LocationServiceParser mLocationParser = new LocationServiceParser();
+
+ private ActivityServiceItem mActivityServiceItem= null;
+ private boolean mParsedInput = false;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return The {@link ActivityServiceItem}
+ */
+ @Override
+ public ActivityServiceItem parse(List<String> lines) {
+ setup();
+ for (String line : lines) {
+ if (!mParsedInput && !"".equals(line.trim())) {
+ mParsedInput = true;
+ }
+ parseLine(line);
+ }
+ commit();
+ return mActivityServiceItem;
+ }
+
+ /**
+ * Sets up the parser by adding the section parsers.
+ */
+ protected void setup() {
+ addSectionParser(mLocationParser, LOCATION_SECTION_REGEX);
+ addSectionParser(new NoopParser(), NOOP_SECTION_REGEX);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void commit() {
+ // signal EOF
+ super.commit();
+ if (mParsedInput) {
+ if (mActivityServiceItem == null) {
+ mActivityServiceItem = new ActivityServiceItem();
+ }
+ }
+
+ if (mActivityServiceItem != null) {
+ mActivityServiceItem.setLocationDumps(
+ (LocationDumpsItem) getSection(mLocationParser));
+ }
+ }
+}
diff --git a/src/com/android/loganalysis/parser/BugreportParser.java b/src/com/android/loganalysis/parser/BugreportParser.java
index ece6076..dac1f53 100644
--- a/src/com/android/loganalysis/parser/BugreportParser.java
+++ b/src/com/android/loganalysis/parser/BugreportParser.java
@@ -15,6 +15,7 @@
*/
package com.android.loganalysis.parser;
+import com.android.loganalysis.item.ActivityServiceItem;
import com.android.loganalysis.item.AnrItem;
import com.android.loganalysis.item.BugreportItem;
import com.android.loganalysis.item.BugreportItem.CommandLineItem;
@@ -55,6 +56,8 @@ public class BugreportParser extends AbstractSectionParser {
"------ (SYSTEM|MAIN|MAIN AND SYSTEM) LOG .*";
private static final String ANR_TRACES_SECTION_REGEX = "------ VM TRACES AT LAST ANR .*";
private static final String DUMPSYS_SECTION_REGEX = "------ DUMPSYS .*";
+ private static final String ACTIVITY_SERVICE_SECTION_REGEX =
+ "^------ APP SERVICES \\(dumpsys activity service all\\) ------$";
private static final String NOOP_SECTION_REGEX = "------ .* ------";
private static final String BOOTREASON_PROP = "ro.boot.bootreason";
@@ -112,6 +115,7 @@ public class BugreportParser extends AbstractSectionParser {
private KernelLogParser mLastKmsgParser = new KernelLogParser();
private LogcatParser mLogcatParser = new LogcatParser();
private DumpsysParser mDumpsysParser = new DumpsysParser();
+ private ActivityServiceParser mActivityServiceParser = new ActivityServiceParser();
private BugreportItem mBugreport = null;
private CommandLineItem mCommandLine = new CommandLineItem();
@@ -175,6 +179,7 @@ public class BugreportParser extends AbstractSectionParser {
addSectionParser(mKernelLogParser, KERNEL_LOG_SECTION_REGEX);
addSectionParser(mLastKmsgParser, LAST_KMSG_SECTION_REGEX);
addSectionParser(mDumpsysParser, DUMPSYS_SECTION_REGEX);
+ addSectionParser(mActivityServiceParser, ACTIVITY_SERVICE_SECTION_REGEX);
addSectionParser(new NoopParser(), NOOP_SECTION_REGEX);
mKernelLogParser.setAddUnknownBootreason(false);
mLastKmsgParser.setAddUnknownBootreason(false);
@@ -202,6 +207,7 @@ public class BugreportParser extends AbstractSectionParser {
mBugreport.setLastKmsg((KernelLogItem) getSection(mLastKmsgParser));
mBugreport.setSystemProps((SystemPropsItem) getSection(mSystemPropsParser));
mBugreport.setDumpsys((DumpsysItem) getSection(mDumpsysParser));
+ mBugreport.setActivityService((ActivityServiceItem) getSection(mActivityServiceParser));
if (mBugreport.getSystemLog() != null && mBugreport.getProcrank() != null) {
for (IItem item : mBugreport.getSystemLog().getEvents()) {
diff --git a/src/com/android/loganalysis/parser/LocationServiceParser.java b/src/com/android/loganalysis/parser/LocationServiceParser.java
new file mode 100644
index 0000000..1f0450f
--- /dev/null
+++ b/src/com/android/loganalysis/parser/LocationServiceParser.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.LocationDumpsItem;
+import com.android.loganalysis.util.NumberFormattingUtil;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A {@link IParser} to handle the parsing of location request information
+ */
+public class LocationServiceParser implements IParser {
+ /**
+ * Match a valid line such as:
+ * "Interval effective/min/max 1/0/0[s] Duration: 140[minutes] [com.google.android.gms,
+ * PRIORITY_NO_POWER, UserLocationProducer] Num requests: 2 Active: true"
+ */
+ private static final Pattern LOCATION_PAT = Pattern.compile(
+ "^\\s*Interval effective/min/max (\\d+)/(\\d+)/(\\d+)\\[s\\] Duration: (\\d+)"
+ + "\\[minutes\\]\\s*\\[([\\w.]+), (\\w+)(,.*)?\\] Num requests: \\d+ Active: \\w*");
+
+ private LocationDumpsItem mItem = new LocationDumpsItem();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public LocationDumpsItem parse(List<String> lines) {
+ Matcher m = null;
+ for (String line : lines) {
+ m = LOCATION_PAT.matcher(line);
+ if (m.matches()) {
+ mItem.addLocationClient(m.group(5), NumberFormattingUtil.parseIntOrZero(m.group(1)),
+ NumberFormattingUtil.parseIntOrZero(m.group(2)),
+ NumberFormattingUtil.parseIntOrZero(m.group(3)), m.group(6),
+ NumberFormattingUtil.parseIntOrZero(m.group(4)));
+ continue;
+ }
+ }
+ return mItem;
+ }
+
+ /**
+ * Get the {@link LocationDumpsItem}.
+ * <p>
+ * Exposed for unit testing.
+ * </p>
+ */
+ LocationDumpsItem getItem() {
+ return mItem;
+ }
+}
diff --git a/src/com/android/loganalysis/rule/LocationUsageRule.java b/src/com/android/loganalysis/rule/LocationUsageRule.java
new file mode 100644
index 0000000..71defa2
--- /dev/null
+++ b/src/com/android/loganalysis/rule/LocationUsageRule.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.loganalysis.rule;
+
+import com.android.loganalysis.item.BugreportItem;
+import com.android.loganalysis.item.LocationDumpsItem;
+import com.android.loganalysis.item.LocationDumpsItem.LocationInfoItem;
+
+import java.util.concurrent.TimeUnit;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+/**
+ * Rules definition for Process usage
+ */
+public class LocationUsageRule extends AbstractPowerRule {
+
+ private static final String LOCATION_USAGE_ANALYSIS = "LOCATION_USAGE_ANALYSIS";
+ private static final float LOCATION_REQUEST_DURATION_THRESHOLD = 0.1f; // 10%
+ // GSA requests for location every 285 seconds, anything more frequent is an issue
+ private static final int LOCATION_INTERVAL_THRESHOLD = 285;
+
+ private StringBuffer mAnalysisBuffer;
+
+ private BugreportItem mBugreportItem = null;
+
+ public LocationUsageRule (BugreportItem bugreportItem) {
+ super(bugreportItem);
+ mBugreportItem = bugreportItem;
+ }
+
+
+ @Override
+ public void applyRule() {
+ mAnalysisBuffer = new StringBuffer();
+ LocationDumpsItem locationDumpsItem = mBugreportItem.getActivityService()
+ .getLocationDumps();
+ final long locationRequestThresholdMs = (long) (getTimeOnBattery() *
+ LOCATION_REQUEST_DURATION_THRESHOLD);
+ if (locationDumpsItem != null) {
+ for (LocationInfoItem locationClient : locationDumpsItem.getLocationClients()) {
+ final String packageName = locationClient.getPackage();
+ final String priority = locationClient.getPriority();
+ final int effectiveIntervalSec = locationClient.getEffectiveInterval();
+ if (effectiveIntervalSec < LOCATION_INTERVAL_THRESHOLD &&
+ !priority.equals("PRIORITY_NO_POWER") &&
+ (TimeUnit.MINUTES.toMillis(locationClient.getDuration()) >
+ locationRequestThresholdMs)) {
+ mAnalysisBuffer.append(String.format("Package %s is requesting for location "
+ + "updates every %d secs with priority %s", packageName,
+ effectiveIntervalSec, priority));
+ }
+ }
+ }
+ }
+
+ @Override
+ public JSONObject getAnalysis() {
+ JSONObject usageAnalysis = new JSONObject();
+ try {
+ usageAnalysis.put(LOCATION_USAGE_ANALYSIS, mAnalysisBuffer.toString());
+ } catch (JSONException e) {
+ // do nothing
+ }
+ return usageAnalysis;
+ }
+}
diff --git a/src/com/android/loganalysis/rule/RuleEngine.java b/src/com/android/loganalysis/rule/RuleEngine.java
index add61e6..57daa19 100644
--- a/src/com/android/loganalysis/rule/RuleEngine.java
+++ b/src/com/android/loganalysis/rule/RuleEngine.java
@@ -66,5 +66,6 @@ public class RuleEngine {
private void addPowerRules() {
mRulesList.add(new WakelockRule(mBugreportItem));
mRulesList.add(new ProcessUsageRule(mBugreportItem));
+ mRulesList.add(new LocationUsageRule(mBugreportItem));
}
}
diff --git a/tests/src/com/android/loganalysis/item/LocationDumpsItemTest.java b/tests/src/com/android/loganalysis/item/LocationDumpsItemTest.java
new file mode 100644
index 0000000..c1af8a0
--- /dev/null
+++ b/tests/src/com/android/loganalysis/item/LocationDumpsItemTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.loganalysis.item;
+
+import com.android.loganalysis.item.LocationDumpsItem.LocationInfoItem;
+
+import junit.framework.TestCase;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Unit test for {@link LocationDumpsItem}.
+ */
+public class LocationDumpsItemTest extends TestCase {
+
+ /**
+ * Test that {@link LocationDumpsItem#toJson()} returns correctly.
+ */
+ public void testToJson() throws JSONException {
+ LocationDumpsItem item = new LocationDumpsItem();
+ item.addLocationClient("com.google.android.gms", 500, 60, 1000, "PRIORITY_ACCURACY", 45);
+ item.addLocationClient("com.google.android.maps", 0, 0, 0, "PRIORITY_ACCURACY", 55);
+
+ // Convert to JSON string and back again
+ JSONObject output = new JSONObject(item.toJson().toString());
+
+ assertTrue(output.has(LocationDumpsItem.LOCATION_CLIENTS));
+ assertTrue(output.get(LocationDumpsItem.LOCATION_CLIENTS) instanceof JSONArray);
+
+ JSONArray locationClients = output.getJSONArray(LocationDumpsItem.LOCATION_CLIENTS);
+
+ assertEquals(2, locationClients.length());
+ assertTrue(locationClients.getJSONObject(0).has(LocationInfoItem.PACKAGE));
+ assertTrue(locationClients.getJSONObject(0).has(LocationInfoItem.EFFECTIVE_INTERVAL));
+ assertTrue(locationClients.getJSONObject(0).has(LocationInfoItem.MIN_INTERVAL));
+ assertTrue(locationClients.getJSONObject(0).has(LocationInfoItem.MAX_INTERVAL));
+ assertTrue(locationClients.getJSONObject(0).has(LocationInfoItem.REQUEST_PRIORITY));
+ assertTrue(locationClients.getJSONObject(0).has(LocationInfoItem.LOCATION_DURATION));
+
+ assertTrue(locationClients.getJSONObject(1).has(LocationInfoItem.PACKAGE));
+ assertTrue(locationClients.getJSONObject(1).has(LocationInfoItem.EFFECTIVE_INTERVAL));
+ assertTrue(locationClients.getJSONObject(1).has(LocationInfoItem.MIN_INTERVAL));
+ assertTrue(locationClients.getJSONObject(1).has(LocationInfoItem.MAX_INTERVAL));
+ assertTrue(locationClients.getJSONObject(1).has(LocationInfoItem.REQUEST_PRIORITY));
+ assertTrue(locationClients.getJSONObject(1).has(LocationInfoItem.LOCATION_DURATION));
+ }
+
+ /**
+ * Test that {@link LocationDumpsItem#getLocationDumps()} returns correctly.
+ */
+ public void testGetLocationDumps() {
+ LocationDumpsItem item = new LocationDumpsItem();
+ item.addLocationClient("com.google.android.gms", 500, 60, 1000, "PRIORITY_ACCURACY", 45);
+
+ assertEquals(item.getLocationClients().size(), 1);
+ LocationInfoItem client = item.getLocationClients().iterator().next();
+ assertNotNull(client);
+ assertEquals(client.getPackage(), "com.google.android.gms");
+ assertEquals(client.getEffectiveInterval(), 500);
+ assertEquals(client.getMinInterval(), 60);
+ assertEquals(client.getMaxInterval(), 1000);
+ assertEquals(client.getPriority(), "PRIORITY_ACCURACY");
+ assertEquals(client.getDuration(), 45);
+ }
+
+}
diff --git a/tests/src/com/android/loganalysis/parser/ActivityServiceParserTest.java b/tests/src/com/android/loganalysis/parser/ActivityServiceParserTest.java
new file mode 100644
index 0000000..c074f14
--- /dev/null
+++ b/tests/src/com/android/loganalysis/parser/ActivityServiceParserTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.ActivityServiceItem;
+import com.android.loganalysis.item.DumpsysItem;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link ActivityServiceParser}
+ */
+public class ActivityServiceParserTest extends TestCase {
+
+ /**
+ * Test that normal input is parsed.
+ */
+ public void testActivityServiceParser() {
+ List<String> inputBlock = Arrays.asList(
+ "SERVICE com.google.android.gms/"
+ + "com.google.android.location.internal.GoogleLocationManagerService f4c9e9d "
+ + "pid=1494",
+ "Client:",
+ " nothing to dump",
+ "Location Request History By Package:",
+ "Interval effective/min/max 1/0/0[s] Duration: 140[minutes] "
+ + "[com.google.android.gms, PRIORITY_NO_POWER, UserLocationProducer] "
+ + "Num requests: 2 Active: true",
+ "Interval effective/min/max 284/285/3600[s] Duration: 140[minutes] "
+ + "[com.google.android.googlequicksearchbox, PRIORITY_BALANCED_POWER_ACCURACY] "
+ + "Num requests: 5 Active: true",
+ "FLP WakeLock Count:",
+ "SERVICE com.android.server.telecom/.components.BluetoothPhoneService 98ab pid=802",
+ "Interval effective/min/max 1/0/0[s] Duration: 140[minutes] "
+ + "[com.google.android.gms, PRIORITY_NO_POWER, UserLocationProducer] "
+ + "Num requests: 2 Active: true",
+ "");
+
+ ActivityServiceItem activityService = new ActivityServiceParser().parse(inputBlock);
+ assertNotNull(activityService.getLocationDumps());
+ assertEquals(activityService.getLocationDumps().getLocationClients().size(), 2);
+ }
+}
+
diff --git a/tests/src/com/android/loganalysis/parser/BugreportParserTest.java b/tests/src/com/android/loganalysis/parser/BugreportParserTest.java
index 6c8f7c2..b6e35b3 100644
--- a/tests/src/com/android/loganalysis/parser/BugreportParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/BugreportParserTest.java
@@ -18,10 +18,17 @@ package com.android.loganalysis.parser;
import com.android.loganalysis.item.BugreportItem;
import com.android.loganalysis.item.IItem;
import com.android.loganalysis.item.MiscKernelLogItem;
+import com.android.loganalysis.rule.RuleEngine;
+import com.android.loganalysis.rule.RuleEngine.RuleType;
import com.android.loganalysis.util.ArrayUtil;
import junit.framework.TestCase;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -138,7 +145,20 @@ public class BugreportParserTest extends TestCase {
" All wakeup reasons:",
" Wakeup reason 2:bcmsdh_sdmmc:2:qcom,smd:2:msmgio: 1m 5s 4ms (2 times) realtime",
" Wakeup reason 2:qcom,smd-rpm:2:fc4c.qcom,spmi: 7m 1s 914ms (7 times) realtime",
- "");
+ "",
+ "========================================================",
+ "== Running Application Services",
+ "========================================================",
+ "------ APP SERVICES (dumpsys activity service all) ------",
+ "SERVICE com.google.android.gms/"
+ + "com.google.android.location.internal.GoogleLocationManagerService f4c9d pid=14",
+ " Location Request History By Package:",
+ "Interval effective/min/max 1/0/0[s] Duration: 140[minutes] ["
+ + "com.google.android.gms, PRIORITY_NO_POWER, UserLocationProducer] "
+ + "Num requests: 2 Active: true",
+ "Interval effective/min/max 284/285/3600[s] Duration: 140[minutes] "
+ + "[com.google.android.googlequicksearchbox, PRIORITY_BALANCED_POWER_ACCURACY] "
+ + "Num requests: 5 Active: true");
BugreportItem bugreport = new BugreportParser().parse(lines);
assertNotNull(bugreport);
@@ -171,6 +191,11 @@ public class BugreportParserTest extends TestCase {
assertNotNull(bugreport.getDumpsys());
assertNotNull(bugreport.getDumpsys().getBatteryStats());
+
+ assertNotNull(bugreport.getActivityService());
+ assertNotNull(bugreport.getActivityService().getLocationDumps().getLocationClients());
+ assertEquals(bugreport.getActivityService().getLocationDumps().getLocationClients().size(),
+ 2);
}
/**
diff --git a/tests/src/com/android/loganalysis/parser/LocationServiceParserTest.java b/tests/src/com/android/loganalysis/parser/LocationServiceParserTest.java
new file mode 100644
index 0000000..fc58e45
--- /dev/null
+++ b/tests/src/com/android/loganalysis/parser/LocationServiceParserTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.LocationDumpsItem;
+import com.android.loganalysis.item.LocationDumpsItem.LocationInfoItem;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link LocationServiceParser}
+ */
+public class LocationServiceParserTest extends TestCase {
+
+ /**
+ * Test that normal input is parsed.
+ */
+ public void testLocationClientsSize() {
+ List<String> inputBlock = Arrays.asList(
+ " Location Request History By Package:",
+ " Interval effective/min/max 1/0/0[s] Duration: 140[minutes] "
+ + "[com.google.android.gms, PRIORITY_NO_POWER, UserLocationProducer] "
+ + "Num requests: 2 Active: true",
+ " Interval effective/min/max 284/285/3600[s] Duration: 140[minutes] "
+ + "[com.google.android.googlequicksearchbox, PRIORITY_BALANCED_POWER_ACCURACY] "
+ + "Num requests: 5 Active: true",
+ " Interval effective/min/max 0/0/0[s] Duration: 0[minutes] "
+ + "[com.google.android.apps.walletnfcrel, PRIORITY_BALANCED_POWER_ACCURACY] "
+ + "Num requests: 1 Active: false",
+ " ",
+ " FLP WakeLock Count");
+
+ LocationDumpsItem locationClients = new LocationServiceParser().parse(inputBlock);
+ assertNotNull(locationClients.getLocationClients());
+ assertEquals(locationClients.getLocationClients().size(), 3);
+ }
+
+ /**
+ * Test that normal input is parsed.
+ */
+ public void testLocationClientParser() {
+ List<String> inputBlock = Arrays.asList(
+ " Location Request History By Package:",
+ " Interval effective/min/max 1/0/0[s] Duration: 140[minutes] "
+ + "[com.google.android.gms, PRIORITY_NO_POWER, UserLocationProducer] "
+ + "Num requests: 2 Active: true");
+
+ LocationDumpsItem locationClients = new LocationServiceParser().parse(inputBlock);
+ assertNotNull(locationClients.getLocationClients());
+ LocationInfoItem client = locationClients.getLocationClients().iterator().next();
+ assertEquals(client.getPackage(), "com.google.android.gms");
+ assertEquals(client.getEffectiveInterval(), 1);
+ assertEquals(client.getMinInterval(), 0);
+ assertEquals(client.getMaxInterval(), 0);
+ assertEquals(client.getPriority(), "PRIORITY_NO_POWER");
+ assertEquals(client.getDuration(), 140);
+ }
+
+ /**
+ * Test that invalid input is parsed.
+ */
+ public void testLocationClientParserInvalidInput() {
+ List<String> inputBlock = Arrays.asList(
+ " Location Request History By Package:",
+ " Interval effective/min/max 1/0/0[s] Duration: 140[minutes] "
+ + "[com.google.android.gms PRIORITY_NO_POWER UserLocationProducer] "
+ + "Num requests: 2 Active: true");
+ LocationDumpsItem locationClients = new LocationServiceParser().parse(inputBlock);
+ assertEquals(locationClients.getLocationClients().size(), 0);
+ }
+
+}
+