package com.ibm.wala.mobile;
import static com.ibm.wala.mobile.Libraries.*;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.Iterator;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import com.ibm.wala.dalvik.test.callGraph.DalvikCallGraphTestBase;
import com.ibm.wala.ipa.callgraph.AnalysisOptions.ReflectionOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.NullProgressMonitor;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
public class CallGraphService extends Service {
public static final int APK_CALL_GRAPH = IBinder.FIRST_CALL_TRANSACTION;
public static final int MAIN_CALL_GRAPH = APK_CALL_GRAPH + 1;
private static String WALA_INTERFACE = "WALA";
private Pair<String,Integer> node(CGNode n) {
return Pair.make("" + n.getMethod().getName() + n.getMethod().getDescriptor(), n.getGraphNodeId());
}
private SlowSparseNumberedGraph<Pair<String,Integer>> writeable(CallGraph CG) {
SlowSparseNumberedGraph<Pair<String,Integer>> result = SlowSparseNumberedGraph.make();
for(CGNode n : CG) {
result.addNode(node(n));
}
for(CGNode n : CG) {
for(Iterator<CGNode> ss = CG.getSuccNodes(n); ss.hasNext(); ) {
result.addEdge(node(n), node(ss.next()));
}
}
return result;
}
@Override
public IBinder onBind(Intent intent) {
return new IBinder() {
@Override
public String getInterfaceDescriptor() throws RemoteException {
return WALA_INTERFACE;
}
@Override
public boolean pingBinder() {
return true;
}
@Override
public boolean isBinderAlive() {
return true;
}
@Override
public IInterface queryLocalInterface(String descriptor) {
final IBinder that = this;
return new IInterface() {
@Override
public IBinder asBinder() {
return that;
}
};
}
@Override
public void dump(FileDescriptor fd, String[] args)
throws RemoteException {
// TODO Auto-generated method stub
}
@Override
public void dumpAsync(FileDescriptor fd, String[] args)
throws RemoteException {
// TODO Auto-generated method stub
}
@Override
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
try {
data.setDataPosition(0);
String programFile = data.readString();
Pair<CallGraph,PointerAnalysis<InstanceKey>> x;
if (code == APK_CALL_GRAPH) {
x = DalvikCallGraphTestBase.makeAPKCallGraph(systemLibs(), null, programFile, new NullProgressMonitor(), ReflectionOptions.ONE_FLOW_TO_CASTS_APPLICATION_GET_METHOD);
} else {
String mainClassName = data.readString();
x = DalvikCallGraphTestBase.makeDalvikCallGraph(coreLibs(), null, mainClassName, programFile);
}
reply.writeSerializable(writeable(x.fst));
return true;
} catch (ClassHierarchyException |
IllegalArgumentException |
IOException |
CancelException e) {
reply.writeException(e);
return false;
}
}
@Override
public void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException {
// TODO Auto-generated method stub
}
@Override
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
// TODO Auto-generated method stub
return false;
}
};
}
}