diff options
author | avellore <avellore@google.com> | 2015-12-08 19:12:29 -0800 |
---|---|---|
committer | avellore <avellore@google.com> | 2016-01-11 13:49:25 -0800 |
commit | 47682ace745705d3592a5681fa6400661991ca16 (patch) | |
tree | 2aeac825ac501292b7df5a44b374eb03d963e50f | |
parent | 902c545fe48ec077ca17fde629e9b5e655e83d15 (diff) | |
download | loganalysis-47682ace745705d3592a5681fa6400661991ca16.tar.gz |
Add Location clients heuristics
Parse the activity service section and retrieve location usage clients
Change-Id: I71fb6331be713b3b8653834feea05c88deab68b6
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); + } + +} + |