package de.tum.in.i22.uc.pdp.android;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
import de.ecspride.events.EventInformation;
import de.ecspride.events.EventInformationParser;
import de.ecspride.events.Pair;
import de.tum.in.i22.uc.cm.datatypes.basic.XmlPolicy;
import de.tum.in.i22.uc.pdp.core.PolicyDecisionPoint;
import de.tum.in.i22.uc.pdp.core.shared.Constants;
import de.tum.in.i22.uc.pdp.core.shared.Decision;
import de.tum.in.i22.uc.pdp.core.shared.Event;
import de.tum.in.i22.uc.pdp.core.shared.IPolicyDecisionPoint;
import de.tum.in.i22.uc.pdp.core.shared.Param;
import de.tum.pip.IPIPCommunication;
import de.tum.pip.PolicyInformationPoint;
import de.util.FileUtil;
public class pdpService extends Service
{
private final static String eventInformationFileName ="eventInformation.xml";
private File eventInformationFile =null;
private static final String TAG ="pdpService";
private Messenger decisionMessenger;
private Messenger setPolicyMessenger;
private Messenger revokePolicyMessenger;
public static boolean pdpRunning =false;
public static IPolicyDecisionPoint lpdp =null;
public static IPIPCommunication lpip =null;
public final static String ACTION_PDP_DECISION ="de.tum.in.i22.uc.pdp.android.pdpService";
public final static String ACTION_PDP_SETPOLICY ="de.tum.in.i22.uc.pdp.android.setPolicy";
public final static String ACTION_PDP_REVPOLICY ="de.tum.in.i22.uc.pdp.android.revPolicy";
@Override
public void onCreate()
{
this.eventInformationFile=copyFileFromAssetsToInternalStorage(eventInformationFileName, true);
this.decisionMessenger=new Messenger(new PDPDecisionHandler(getApplicationContext(), eventInformationFile));
this.setPolicyMessenger=new Messenger(new SetPolicyHandler(getApplicationContext()));
this.revokePolicyMessenger=new Messenger(new RevokePolicyHandler(getApplicationContext()));
}
private File copyFileFromAssetsToInternalStorage(String fileName, boolean forceOverwrite)
{
String fileInternally=this.getFilesDir().toString() + File.separator + fileName;
File file=new File(fileInternally);
try
{
if(!file.exists() || forceOverwrite) FileUtil.copyPolicyFileFromAssetsToInternalStorage(getApplicationContext(), fileName, fileInternally);
}
catch(Exception ex)
{
Log.e("ERROR", ex.getMessage());
}
try
{
Runtime.getRuntime().exec("chmod 777 " + fileInternally);
}
catch(Exception ex)
{
ex.printStackTrace();
}
return file;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "Starting pdpService");
try
{
lpdp=PolicyDecisionPoint.getInstance();
// Log.i(TAG, "Starting PDP: " + lpdp.pdpStart());
lpip=PolicyInformationPoint.getInstance();
Log.i(TAG, "Starting PIP: " + lpip.initializePIP());
}
catch(Exception e)
{
Log.e(TAG, "exception while starting pdp");
Log.e(TAG, e.getMessage());
}
Log.d(TAG, "native pdp started");
Toast.makeText(this, "pdpService started", Toast.LENGTH_SHORT).show();
if(this.eventInformationFile == null) throw new RuntimeException("Oops, something went all wonky");
return START_STICKY;
}
@Override
public void onDestroy()
{
super.onDestroy();
Log.d(TAG, "Stopping pdpService");
Toast.makeText(this, "Stopping pdpService", Toast.LENGTH_SHORT).show();
}
@Override
public IBinder onBind(Intent intent)
{
Log.d(TAG, "pdpService - onBind");
if(intent.getAction().equals(ACTION_PDP_DECISION)) return this.decisionMessenger.getBinder();
else if(intent.getAction().equals(ACTION_PDP_SETPOLICY)) return this.setPolicyMessenger.getBinder();
else if(intent.getAction().equals(ACTION_PDP_REVPOLICY)) return this.revokePolicyMessenger.getBinder();
else throw new RuntimeException("Unknown action");
}
/**
* Abstract base class for all policy handlers
*
* @author Steven Arzt
*/
private static class AbstractPolicyHandler extends Handler
{
protected final Context context;
public AbstractPolicyHandler(Context context)
{
this.context=context;
}
}
/**
* Handler for setting a new PDP policy
*
* @author Steven Arzt
*/
private static class SetPolicyHandler extends AbstractPolicyHandler
{
public SetPolicyHandler(Context context)
{
super(context);
}
@Override
public void handleMessage(Message msg)
{
String policy=msg.getData().getString("policy");
Log.d("pdpService", "setPolicyHandler-handleMessage");
Log.d("pdpService", "policy: " + policy);
lpdp=PolicyDecisionPoint.getInstance();
//lpdp.pdpDeployPolicyString(policy);
// FIXME: policyName hardcoded
lpdp.deployPolicyXML(new XmlPolicy("name", policy));
}
}
/**
* Handler for revoking a PDP policy
*
* @author Steven Arzt
*/
private static class RevokePolicyHandler extends AbstractPolicyHandler
{
public RevokePolicyHandler(Context context)
{
super(context);
}
@Override
public void handleMessage(Message msg)
{
String mechName=msg.getData().getString("mechName");
lpdp=PolicyDecisionPoint.getInstance();
//lpdp.pdpRevokeMechanism(mechName);
// FIXME: policyName hardcoded
lpdp.revokeMechanism("name", mechName);
}
}
private static class PDPDecisionHandler extends AbstractPolicyHandler
{
private Map<String, EventInformation> eventNameToInfoMap =null;
int counter =0;
public PDPDecisionHandler(Context context, File eventInformationFile)
{
super(context);
// Initialize the event information
EventInformationParser eventInfoParser=new EventInformationParser(eventInformationFile.getAbsolutePath());
Map<String, EventInformation> eventInformation=eventInfoParser.parseEventInformation();
this.eventNameToInfoMap=setupEventNameToInformationMap(eventInformation);
}
@Override
public void handleMessage(Message msg)
{
/*
* lpdp = PolicyDecisionPoint.getInstance(); for (int i = 1; i < 20; i++)
* { Event event = new Event("sentTextMessage", true);
* event.addStringParameter("message", "xxx");
* event.addStringParameter("destination", "12345");
* event.addStringParameter("DATA_UNIQUE_IDENTIFIER", "true");
*
* Decision d = lpdp.pdpNotifyEventJNI(event); Log.d("PDP", "xxx " +
* d.getAuthorizationAction().getType()); }
*/
Log.d(TAG, "pdpService received message: " + counter);
lpdp = PolicyDecisionPoint.getInstance();
Event event=reconstructEvent(msg.getData().getString("eventname"), msg);
if (msg.getData().containsKey("APP_PACKAGE_NAME")) {
String app_package_name = (String) msg.getData().getString("APP_PACKAGE_NAME");
Log.d(TAG, "application package name: "+ app_package_name);
} else {
Log.e(TAG, "no package name information in event message!!!");
}
Decision d=lpdp.notifyEvent(event);
Toast.makeText(context, "Event " + event.getEventAction() + (d.getAuthorizationAction().getType() ? " allowed" : "inhibited"), Toast.LENGTH_LONG).show();
Message message=Message.obtain(null, 2, 0, 0);
Bundle b=new Bundle(); // or use more complex (key,value)-pairs.
b.putString("data", "" + d.getAuthorizationAction().getType());
message.setData(b);
Log.d(TAG, "answer sent to pep!!!!: ");
try
{
Messenger replyTo=msg.replyTo;
replyTo.send(message);
}
catch(RemoteException rme)
{
Log.e(TAG, "sending answer failed!");
}
}
private Event reconstructEvent(String eventname, Message msg)
{
Event event=new Event(eventname, true);
EventInformation eventInfo=eventNameToInfoMap.get(eventname);
if (eventInfo == null) {
Log.w(TAG, "warning: unknown event '"+ eventname +"'");
Log.w(TAG, "available events: ");
for (String k : eventNameToInfoMap.keySet()) {
Log.w(TAG, " -> "+ k);
}
}
for(Pair<Integer, String> parameterInformation : eventInfo.getParameterInformation())
{
String paramName=parameterInformation.getRight();
String paramValue=msg.getData().getString("param" + parameterInformation.getLeft() + "value");
event.addParam(new Param<String>(paramName, paramValue, Constants.PARAMETER_TYPE_STRING));
}
for(String key : msg.getData().keySet()) {
if(key.startsWith("DATA_")) {
String paramName=key;
String paramValue=msg.getData().getString(key);
event.addParam(new Param<String>(paramName, paramValue, Constants.PARAMETER_TYPE_STRING));
} else if (key.startsWith("APP_PACKAGE_NAME")) {
String paramName = key;
String paramValue = msg.getData().getString(key);
event.addParam(new Param<String>(paramName, paramValue, Constants.PARAMETER_TYPE_STRING));
}
}
return event;
}
private Map<String, EventInformation> setupEventNameToInformationMap(Map<String, EventInformation> eventInfo)
{
Map<String, EventInformation> eventNameToInfoMap=new HashMap<String, EventInformation>();
for(Map.Entry<String, EventInformation> entry : eventInfo.entrySet())
{
eventNameToInfoMap.put(entry.getValue().getEventName(), entry.getValue());
}
return eventNameToInfoMap;
}
}
}