package com.nolanlawson.apptracker.helper;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Intent;
import com.nolanlawson.apptracker.data.AnalyzedLogLine;
import com.nolanlawson.apptracker.util.FlagUtil;
import com.nolanlawson.apptracker.util.UtilLogger;
public class LogAnalyzer {
private static UtilLogger log = new UtilLogger(LogAnalyzer.class);
private static Pattern activityManagerPattern = Pattern.compile("Activity ?Manager");
private static Pattern startPattern = Pattern.compile("Starting activity|Starting: Intent|START");
private static Pattern launcherPattern = Pattern
.compile("\\bco?mp=\\{?([^/]++)/([^ \t}]+)");
// seems to be some kind of unconventional Samsung log pattern
private static Pattern tryingToLaunchPattern = Pattern
.compile("Trying to launch ([^/]++)/([^ \t}]+)");
private static Pattern flagPattern = Pattern.compile("\\bfl(?:g|ags)=0x(\\d+)\\b");
public static AnalyzedLogLine analyzeLogLine(String line) {
if (!lineIsActivityManagerStart(line)) {
return null;
}
if(startPattern.matcher(line).find()
&& line.contains("=android.intent.action.MAIN")
&& !line.contains("(has extras)")) {// if it has extras, we can't call it (e.g. com.android.phone)
if (line.contains("android.intent.category.HOME")) { // ignore home apps
return new AnalyzedLogLine(true, null, null);
}
// must contain the proper flags
if (!lineContainsIncompatibleFlags(line)) {
Matcher launcherMatcher = launcherPattern.matcher(line);
if (launcherMatcher.find()) {
return new AnalyzedLogLine(false, launcherMatcher.group(1), launcherMatcher.group(2));
}
}
}
Matcher tryingToLaunchMatcher = tryingToLaunchPattern.matcher(line);
if (tryingToLaunchMatcher.find()) {
// unconventional Samsung log line
return new AnalyzedLogLine(false, tryingToLaunchMatcher.group(1), tryingToLaunchMatcher.group(2));
}
return null;
}
private static boolean lineContainsIncompatibleFlags(String line) {
Matcher flagMatcher = flagPattern.matcher(line);
if (flagMatcher.find()) {
String flagsAsString = flagMatcher.group(1);
int flags = Integer.parseInt(flagsAsString, 16);
log.d("flags are: 0x%s",flagsAsString);
// intents have to be "new tasks" and they have to have been launched by the user
// (not like e.g. the incoming call screen)
return !FlagUtil.hasFlag(flags, Intent.FLAG_ACTIVITY_NEW_TASK)
|| FlagUtil.hasFlag(flags, Intent.FLAG_ACTIVITY_NO_USER_ACTION);
}
return false;
}
private static boolean lineIsActivityManagerStart(String line) {
return activityManagerPattern.matcher(line).find();
}
}