/**
* Incrementally collects the callback methods for all Android default
* handlers implemented in the source code. This just processes the contents
* of the worklist.
* Note that this operation runs inside Soot, so this method only registers
* a new phase that will be executed when Soot is next run
*/
public void collectCallbackMethodsIncremental() {
Transform transform = new Transform("wjtp.ajc", new SceneTransformer() {
protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes") Map options) {
// Process the worklist from last time
System.out.println("Running incremental callback analysis for " + callbackWorklist.size()
+ " components...");
MultiMap<String, SootMethodAndClass> workListCopy =
new HashMultiMap<String, SootMethodAndClass>(callbackWorklist);
for (String className : workListCopy.keySet()) {
List<MethodOrMethodContext> entryClasses = new LinkedList<MethodOrMethodContext>();
for (SootMethodAndClass am : workListCopy.get(className))
entryClasses.add(Scene.v().getMethod(am.getSignature()));
analyzeRechableMethods(Scene.v().getSootClass(className), entryClasses);
callbackWorklist.remove(className);
}
System.out.println("Incremental callback analysis done.");
}
});
PackManager.v().getPack("wjtp").add(transform);
}
@Override
public void onResultsAvailable(IInfoflowCFG cfg, InfoflowResults results) {
log.info("FlowDroid has finished. Duration: " + (System.currentTimeMillis() - Main.startTime) +" ms.");
Main.startTime = System.currentTimeMillis();
Settings.instance.setDummyMainToLibraryClass();
this.results = results;
if (log.isDebugEnabled()) {
log.debug("");
log.debug("InfoFlow Results");
MultiMap<ResultSinkInfo, ResultSourceInfo> r = results.getResults();
for (ResultSinkInfo k : r.keySet()) {
log.debug("ResultSinkInfo: "+ k);
for (ResultSourceInfo rsi: r.get(k)) {
log.debug(" source: "+ rsi);
}
}
log.debug("");
}
log.info("Starting bytecode instrumentation.");
log.info("Adding code to initialize PEPs.");
Util.initializePePInAllPossibleClasses(Settings.instance.getApkPath());
log.info("Build code for new 'WaitPDPActivity"); // building the code has to be done here (not in the Main class, otherwise Jimple validation will fail
String mainActivityClass = UpdateManifestAndCodeForWaitPDP.getMainActivityName(Settings.instance.getApkPath());
String packageName = UpdateManifestAndCodeForWaitPDP.getApplicationPackageName(Settings.instance.getApkPath());
UpdateManifestAndCodeForWaitPDP.updateWaitPDPActivity(packageName, mainActivityClass);
// update packagename in field of WaitPDP class
SootClass sc = Scene.v().getSootClass(Settings.INSTRUMENTATION_HELPER_JAVA);
SootField sf1 = sc.getFieldByName("applicationPackageName");
Util.changeConstantStringInField(sf1, packageName);
log.info("Adding Policy Enforcement Points (PEPs).");
doAccessControlChecks(cfg);
log.info("Instrumentation is done.");
if (Settings.mustOutputJimple()) {
log.info("-------- Dumping Jimple bodies.");
Main.dumpJimple();
log.info("--------");
}
}