From d2b84288687e2b6949cb93004b93b17d0ef70ff2 Mon Sep 17 00:00:00 2001
From: Adwait Nadkarni <anadkarni@ncsu.edu>
Date: Sat, 19 Oct 2013 00:21:02 -0400
Subject: [PATCH] Aquifer Security System, CCS 2013
---
 Android.mk                                         |    1 +
 api/current.txt                                    |  127 ++
 core/java/android/app/Activity.java                |  117 +-
 core/java/android/app/ActivityThread.java          |   21 +
 core/java/android/content/Intent.java              |   61 +-
 core/java/android/os/AquiferList.aidl              |    3 +
 core/java/android/os/AquiferList.java              |  196 ++
 core/java/android/os/ComponentScreen.aidl          |    3 +
 core/java/android/os/ComponentScreen.java          |   68 +
 core/java/android/os/Enforcement.aidl              |    3 +
 core/java/android/os/Enforcement.java              |   93 +
 core/java/android/os/Filter.aidl                   |    3 +
 core/java/android/os/Filter.java                   |  107 ++
 core/java/android/os/IAquiferService.aidl          |   50 +
 core/java/android/os/Participant.aidl              |    3 +
 core/java/android/os/Participant.java              |  128 ++
 core/java/android/os/Policy.aidl                   |    3 +
 core/java/android/os/Policy.java                   |  137 ++
 core/java/android/os/Process.java                  |   28 +
 services/audioflinger/Android.mk                   |    2 +-
 .../java/com/android/server/AquiferService.java    | 1979 ++++++++++++++++++++
 .../java/com/android/server/IntentResolver.java    |   94 +-
 services/java/com/android/server/SystemServer.java |   19 +-
 .../android/server/am/ActivityManagerService.java  |   98 +-
 .../java/com/android/server/am/ActivityStack.java  |  175 +-
 .../android/server/pm/PackageManagerService.java   |   81 +-
 services/jni/Android.mk                            |    3 +-
 services/jni/com_android_server_AquiferService.cpp |  271 +++
 services/jni/onload.cpp                            |    3 +-
 29 files changed, 3836 insertions(+), 41 deletions(-)
 create mode 100644 core/java/android/os/AquiferList.aidl
 create mode 100644 core/java/android/os/AquiferList.java
 create mode 100644 core/java/android/os/ComponentScreen.aidl
 create mode 100644 core/java/android/os/ComponentScreen.java
 create mode 100644 core/java/android/os/Enforcement.aidl
 create mode 100644 core/java/android/os/Enforcement.java
 create mode 100644 core/java/android/os/Filter.aidl
 create mode 100644 core/java/android/os/Filter.java
 create mode 100644 core/java/android/os/IAquiferService.aidl
 create mode 100644 core/java/android/os/Participant.aidl
 create mode 100644 core/java/android/os/Participant.java
 create mode 100644 core/java/android/os/Policy.aidl
 create mode 100644 core/java/android/os/Policy.java
 create mode 100644 services/java/com/android/server/AquiferService.java
 create mode 100644 services/jni/com_android_server_AquiferService.cpp

diff --git a/Android.mk b/Android.mk
index 371c370..89bf8e5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -120,6 +120,7 @@ LOCAL_SRC_FILES += \
 	core/java/android/nfc/INfcAdapter.aidl \
 	core/java/android/nfc/INfcAdapterExtras.aidl \
 	core/java/android/nfc/INfcTag.aidl \
+	core/java/android/os/IAquiferService.aidl \
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
diff --git a/api/current.txt b/api/current.txt
index ddf5baf..e44c264 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5333,6 +5333,8 @@ package android.content {
     method public android.os.Parcelable[] getParcelableArrayExtra(java.lang.String);
     method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
     method public T getParcelableExtra(java.lang.String);
+    method public int getPid();
+    method public java.lang.String getProcessName();
     method public java.lang.String getScheme();
     method public android.content.Intent getSelector();
     method public java.io.Serializable getSerializableExtra(java.lang.String);
@@ -5401,6 +5403,8 @@ package android.content {
     method public void setExtrasClassLoader(java.lang.ClassLoader);
     method public android.content.Intent setFlags(int);
     method public android.content.Intent setPackage(java.lang.String);
+    method public void setPid(int);
+    method public void setProcessName(java.lang.String);
     method public void setSelector(android.content.Intent);
     method public void setSourceBounds(android.graphics.Rect);
     method public android.content.Intent setType(java.lang.String);
@@ -14520,6 +14524,17 @@ package android.os {
     field public static final android.os.Bundle EMPTY;
   }
 
+  public class ComponentScreen implements android.os.Parcelable {
+    ctor public ComponentScreen(java.lang.String, int, long);
+    method public int describeContents();
+    method public java.lang.String getComponentName();
+    method public int getResultCode();
+    method public long getTimeStamp();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class ConditionVariable {
     ctor public ConditionVariable();
     ctor public ConditionVariable(boolean);
@@ -14676,6 +14691,21 @@ package android.os {
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
+  public class Enforcement implements android.os.Parcelable {
+    ctor public Enforcement();
+    ctor public Enforcement(android.os.Enforcement);
+    method public int describeContents();
+    method public void displayEnforcement();
+    method public static android.os.Enforcement enforcementJoin(android.os.Enforcement, android.os.Enforcement);
+    method public android.os.AquiferList getAllowedList();
+    method public android.os.AquiferList getRequiredList();
+    method public void readFromParcel(android.os.Parcel);
+    method public void setAllowedList(android.os.AquiferList);
+    method public void setRequiredList(android.os.AquiferList);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class Environment {
     ctor public Environment();
     method public static java.io.File getDataDirectory();
@@ -14727,6 +14757,46 @@ package android.os {
     field public static final int OPEN = 32; // 0x20
   }
 
+  public class Filter implements android.os.Parcelable {
+    ctor public Filter();
+    ctor public Filter(android.os.Filter);
+    method public boolean containsAction(java.lang.String);
+    method public int describeContents();
+    method public void displayFilter();
+    method public static android.os.Filter filterJoin(android.os.Filter, android.os.Filter);
+    method public java.util.HashMap<java.lang.String, android.os.AquiferList> getFilterMap();
+    method public android.os.AquiferList getPrincipals(java.lang.String);
+    method public void readFromParcel(android.os.Parcel);
+    method public void setFilterMap(java.util.HashMap<java.lang.String, android.os.AquiferList>);
+    method public void setPrincipals(java.lang.String, android.os.AquiferList);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class AquiferList implements android.os.Parcelable {
+    ctor public AquiferList();
+    ctor public AquiferList(java.util.ArrayList<java.lang.String>);
+    method public boolean add(java.lang.String);
+    method public boolean contains(java.lang.String);
+    method public int describeContents();
+    method public void displayAquiferList();
+    method public java.lang.String getAtIndex(int);
+    method public java.util.ArrayList<java.lang.String> getList();
+    method public void includeAll();
+    method public boolean isEMPTY();
+    method public boolean isEmpty();
+    method public static android.os.AquiferList listIntersection(android.os.AquiferList, android.os.AquiferList);
+    method public static android.os.AquiferList listUnion(android.os.AquiferList, android.os.AquiferList);
+    method public void readFromParcel(android.os.Parcel);
+    method public boolean remove(java.lang.String);
+    method public void setEmpty();
+    method public void setList(java.util.ArrayList<java.lang.String>);
+    method public int size();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static java.lang.String EMPTY;
+  }
+
   public class Handler {
     ctor public Handler();
     ctor public Handler(android.os.Handler.Callback);
@@ -14800,6 +14870,28 @@ package android.os {
     method public abstract void binderDied();
   }
 
+  public abstract interface IAquiferService implements android.os.IInterface {
+    method public abstract void addComponent(java.lang.String, int, java.lang.String, int, int, java.lang.String) throws android.os.RemoteException;
+    method public abstract void addParticipant(java.lang.String, int, java.lang.String, int, java.lang.String, int, int, java.lang.String) throws android.os.RemoteException;
+    method public abstract void addPolicy(android.os.Policy) throws android.os.RemoteException;
+    method public abstract void destroyActivity(java.lang.String) throws android.os.RemoteException;
+    method public abstract void destroyEntireProcess(java.lang.String, int) throws android.os.RemoteException;
+    method public abstract android.os.AquiferList getPrincipalList(java.lang.String, int, java.lang.String) throws android.os.RemoteException;
+    method public abstract java.lang.String getProcessName(int) throws android.os.RemoteException;
+    method public abstract java.lang.String hi(int) throws android.os.RemoteException;
+    method public abstract boolean isThisWorkflow(java.lang.String, int, java.lang.String, int) throws android.os.RemoteException;
+    method public abstract int removePackageName(java.lang.String) throws android.os.RemoteException;
+    method public abstract int storePackageName(java.lang.String, int) throws android.os.RemoteException;
+    method public abstract void workflowJoin(java.lang.String, int, java.lang.String, int, java.lang.String, int, int, java.lang.String) throws android.os.RemoteException;
+  }
+
+  public static abstract class IAquiferService.Stub extends android.os.Binder implements android.os.IAquiferService {
+    ctor public IAquiferService.Stub();
+    method public android.os.IBinder asBinder();
+    method public static android.os.IAquiferService asInterface(android.os.IBinder);
+    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+  }
+
   public abstract interface IInterface {
     method public abstract android.os.IBinder asBinder();
   }
@@ -15054,6 +15146,24 @@ package android.os {
     method public abstract T[] newArray(int);
   }
 
+  public class Participant implements android.os.Parcelable {
+    ctor public Participant(java.lang.String, java.lang.String, int, int, int, java.util.ArrayList<android.os.ComponentScreen>);
+    method public void addComponent(java.lang.String, int);
+    method public int describeContents();
+    method public void displayParticipant();
+    method public java.util.ArrayList<android.os.ComponentScreen> getComponentList();
+    method public java.lang.String getPackageName();
+    method public int getPid();
+    method public java.lang.String getProcessName();
+    method public int getResultCode();
+    method public int getUid();
+    method public boolean isComponentEmpty();
+    method public void readFromParcel(android.os.Parcel);
+    method public void removeComponent(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class PatternMatcher implements android.os.Parcelable {
     ctor public PatternMatcher(java.lang.String, int);
     ctor public PatternMatcher(android.os.Parcel);
@@ -15068,6 +15178,23 @@ package android.os {
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
   }
 
+  public class Policy implements android.os.Parcelable java.io.Serializable {
+    ctor public Policy();
+    ctor public Policy(android.os.Policy);
+    method public int describeContents();
+    method public void displayPolicy();
+    method public android.os.AquiferList getExportList();
+    method public android.os.Filter getFilter();
+    method public android.os.AquiferList getRequiredList();
+    method public static android.os.Policy policyJoin(android.os.Policy, android.os.Policy);
+    method public void readFromParcel(android.os.Parcel);
+    method public void setExportList(android.os.AquiferList);
+    method public void setFilter(android.os.Filter);
+    method public void setRequiredList(android.os.AquiferList);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class PowerManager {
     method public void goToSleep(long);
     method public boolean isScreenOn();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8e8d37d..2934bcb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -43,10 +43,13 @@ import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Binder;
 import android.os.Looper;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.os.IAquiferService;
+import android.os.ServiceManager;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -76,6 +79,7 @@ import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
+import java.util.ListIterator;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -631,7 +635,6 @@ public class Activity extends ContextThemeWrapper
         Window.Callback, KeyEvent.Callback,
         OnCreateContextMenuListener, ComponentCallbacks2 {
     private static final String TAG = "Activity";
-
     /** Standard activity result: operation canceled. */
     public static final int RESULT_CANCELED    = 0;
     /** Standard activity result: operation succeeded. */
@@ -645,7 +648,7 @@ public class Activity extends ContextThemeWrapper
     private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
     private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
     private static final String SAVED_DIALOG_ARGS_KEY_PREFIX = "android:dialog_args_";
-
+    
     private static class ManagedDialog {
         Dialog mDialog;
         Bundle mArgs;
@@ -3186,7 +3189,67 @@ public class Activity extends ContextThemeWrapper
      * @see #startActivity 
      */
     public void startActivityForResult(Intent intent, int requestCode) {
-        if (mParent == null) {
+	//Adwait's code
+	try{		
+		String processName="";
+		IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+		int pid=Binder.getCallingPid();
+		processName = aquifer.getProcessName(pid);	
+		String action=intent.getAction();
+		if(action==null)
+			action="";
+		//System.out.println("Inside StartActivityForResult:The processName is :"+processName+":"+pid);
+
+		if(action.equals(Intent.ACTION_CHOOSER))
+		{	
+			//the outer intent doesnt need these extras
+			intent.removeExtra("processName");
+			intent.removeExtra("pid");
+			intent.setProcessName(null);
+			intent.setPid(-1);
+			//System.out.println("Adwait:ACTION_CHOOSER detected.");
+			//setting the processName and pid on the inner intent, if the caller is not system or launcher
+			if(processName!=null && !processName.equals("system")&& !processName.startsWith("com.android.launcher"))
+			{
+				//System.out.println("Setting inner intent extras for ACTION_CHOOSER case.");
+				Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT);
+				Intent target = (Intent)targetParcelable;
+	//			target.putExtra("processName",processName);
+        //              	target.putExtra("pid",pid);
+
+				target.setProcessName(processName);
+				target.setPid(pid);
+				
+				intent.putExtra(Intent.EXTRA_INTENT, target);
+			}
+			else
+				System.out.println("System or launcher in chooser case. Should never happen!");
+			//Get the processName and pid of the caller.
+			//add it to the intent you got from intent.EXTRA_INTENT
+			//set the processName and pid of the outer intent to null and -1, just to be safe
+			//set the ignore flag in the inner intent: not
+			//necessary: if the second time around, the caller is
+			//the system, then the pid and processnames will not be
+			//set(i have already set them the first time nyways).
+			//If they are the same app that called, then it doesnt
+			//matter if they are set again, as its the same app.
+		}
+		
+		//do only if intent action is not ACTION_CHOOSER
+		if(processName!=null && !processName.equals("system")&& !processName.startsWith("com.android.launcher") && !action.equals(Intent.ACTION_CHOOSER) && !action.equals("android.intent.action.RINGTONE_PICKER"))
+		{	
+			//System.out.println("Adding extras for process "+processName);	
+//			intent.putExtra("processName",processName);
+//			intent.putExtra("pid",pid);
+			intent.setProcessName(processName);
+			intent.setPid(pid);
+
+		}
+	}
+	catch(Exception e)
+	{System.out.println("Exception while setting processName:pid as extras");}
+	//Adwait's code ends
+	 if (mParent == null) {
             Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivity(
                     this, mMainThread.getApplicationThread(), mToken, this,
@@ -3560,12 +3623,12 @@ public class Activity extends ContextThemeWrapper
      * @see #setResult(int)
      */
     public final void setResult(int resultCode, Intent data) {
-        synchronized (this) {
-            mResultCode = resultCode;
-            mResultData = data;
-        }
+	    synchronized (this) {
+	    	mResultCode = resultCode;
+            	mResultData = data;
+	     }
+        
     }
-
     /**
      * Return the name of the package that invoked this activity.  This is who
      * the data in {@link #setResult setResult()} will be sent to.  You can
@@ -4577,6 +4640,21 @@ public class Activity extends ContextThemeWrapper
     }
     
     final void performStop() {
+	//Adwait: Printing when an activity is stopped
+	/*
+	String processName="initial";
+	int pid=Binder.getCallingPid();
+        IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try{
+                processName=aquifer.getProcessName(pid);
+        }
+        catch(Exception e)
+        {
+                System.out.println("Exception at android.app.Activity:performStop");
+        }
+        System.out.println("Stopping activity "+processName+":"+pid);
+	*/
+	//Adwait's code ends
         if (mLoadersStarted) {
             mLoadersStarted = false;
             if (mLoaderManager != null) {
@@ -4624,6 +4702,29 @@ public class Activity extends ContextThemeWrapper
     }
 
     final void performDestroy() {
+	//Adwait: Printing when an activity is destroyed
+	String processName="initial";
+	int pid=Binder.getCallingPid();
+        IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try{
+                processName=aquifer.getProcessName(pid);
+		//System.out.println("DESTROYING ACTIVITY "+processName+":"+pid);
+		if(!processName.equals("system") && !processName.startsWith("com.android.launcher"))
+		{	
+			aquifer.destroyActivity(getComponentName().getClassName());
+		}
+        }
+        catch(Exception e)
+        {
+                System.out.println("Exception at performDestroy()");
+        }
+	/*
+	if(!processName.equals("system") && !processName.startsWith("com.android.launcher"))
+        	System.out.println("Destroying activity "+processName+":"+pid);
+	else
+		System.out.println("Aquifer cannot destroy"+processName+":"+pid);
+	*/
+	//Adwait's code ends
         mWindow.destroy();
         mFragments.dispatchDestroy();
         onDestroy();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0c761fc..d5c0398 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -100,6 +100,9 @@ import java.util.regex.Pattern;
 
 import dalvik.system.CloseGuard;
 
+import android.os.Binder;
+import android.os.IAquiferService;
+
 final class SuperNotCalledException extends AndroidRuntimeException {
     public SuperNotCalledException(String msg) {
         super(msg);
@@ -3035,6 +3038,24 @@ public final class ActivityThread {
     private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
             int configChanges, boolean getNonConfigInstance) {
         ActivityClientRecord r = mActivities.get(token);
+	
+	
+	//Adwait's hook for destroying activities
+	/*
+	IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try{   
+                int pid = Binder.getCallingPid();
+                String processName = aquifer.getProcessName(pid);
+                System.out.println("performDestroyActivity::"+processName+":"+pid);
+		System.out.println(r.state.toString());
+                aquifer.destroyActivity(pid,processName);
+        }
+        catch(Exception e)
+        {
+                System.out.println("Exception at ActivityManagerService:activityDestroyed:"+e);
+        }
+	*/
+	//Adwait's code ends
         Class activityClass = null;
         if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
         if (r != null) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4e5598b..db36600 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3010,6 +3010,9 @@ public class Intent implements Parcelable, Cloneable {
     private Bundle mExtras;
     private Rect mSourceBounds;
     private Intent mSelector;
+    //Adwait's fields
+    private String processName;
+    private int pid;
 
     // ---------------------------------------------------------------------
 
@@ -3041,6 +3044,8 @@ public class Intent implements Parcelable, Cloneable {
         if (o.mSelector != null) {
             this.mSelector = new Intent(o.mSelector);
         }
+        this.processName = o.processName;
+        this.pid = o.pid;
     }
 
     @Override
@@ -3056,6 +3061,9 @@ public class Intent implements Parcelable, Cloneable {
         this.mComponent = o.mComponent;
         if (o.mCategories != null) {
             this.mCategories = new HashSet<String>(o.mCategories);
+        this.processName = o.processName;
+        this.pid = o.pid;
+
         }
     }
 
@@ -3571,6 +3579,27 @@ public class Intent implements Parcelable, Cloneable {
     }
 
     /**
+     * Retrieve the processName of the caller
+     * @return The sender processName of this intent or null if none specified
+     *
+     * @see #setProcessName
+     */
+    public String getProcessName() {
+        return processName;
+    }
+
+    /**
+     * Retrieve the pid of the caller
+     * TODO: Set default to -1 everywhere
+     * @return The caller's pid of this intent or 0 if none specified
+     *
+     * @see #setPid
+     */
+    public int getPid() {
+        return pid;
+    }
+
+    /**
      * Retrieve data this intent is operating on.  This URI specifies the name
      * of the data; often it uses the content: scheme, specifying data in a
      * content provider.  Other schemes may be handled by specific activities,
@@ -4419,6 +4448,32 @@ public class Intent implements Parcelable, Cloneable {
     }
 
     /**
+     * Set the caller processName.
+     *
+     * @param processName Name of the calling process
+     *
+     * @return Returns nothing
+     *
+     * @see #getProcessName
+     */
+    public void setProcessName(String processName) {
+        this.processName = processName != null ? processName : null;
+    }
+
+    /**
+     * Set the caller pid.
+     *
+     * @param pid pid of the calling process
+     *
+     * @return Returns nothing
+     *
+     * @see #getPid
+     */
+    public void setPid(int pid) {
+        this.pid = pid;
+    }
+
+    /**
      * Set the data this intent is operating on.  This method automatically
      * clears any type that was previously set by {@link #setType}.
      *
@@ -6084,7 +6139,8 @@ public class Intent implements Parcelable, Cloneable {
         out.writeInt(mFlags);
         out.writeString(mPackage);
         ComponentName.writeToParcel(mComponent, out);
-
+	out.writeString(processName);
+	out.writeInt(pid);
         if (mSourceBounds != null) {
             out.writeInt(1);
             mSourceBounds.writeToParcel(out, flags);
@@ -6133,7 +6189,8 @@ public class Intent implements Parcelable, Cloneable {
         mFlags = in.readInt();
         mPackage = in.readString();
         mComponent = ComponentName.readFromParcel(in);
-
+	processName=in.readString();
+	pid=in.readInt();
         if (in.readInt() != 0) {
             mSourceBounds = Rect.CREATOR.createFromParcel(in);
         }
diff --git a/core/java/android/os/AquiferList.aidl b/core/java/android/os/AquiferList.aidl
new file mode 100644
index 0000000..5f5b2eb
--- /dev/null
+++ b/core/java/android/os/AquiferList.aidl
@@ -0,0 +1,3 @@
+package android.os;
+
+parcelable AquiferList;
diff --git a/core/java/android/os/AquiferList.java b/core/java/android/os/AquiferList.java
new file mode 100644
index 0000000..1ac1313
--- /dev/null
+++ b/core/java/android/os/AquiferList.java
@@ -0,0 +1,196 @@
+/* Abstraction for the ArrayList<String> Class.
+ * Defines set functions: union, intersection, difference for lists.
+ * Author: Adwait Nadkarni
+ */
+package android.os;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.io.Serializable;
+//to be used as both lists and pos and neg capabilities
+//since we have separated the pos and neg capabilities into 2 lists
+//this becomes easy.
+public class AquiferList implements Parcelable
+{	
+	private ArrayList<String> list;
+	public static String EMPTY = "EMPTY";
+	public static final Parcelable.Creator<AquiferList> CREATOR = new
+        Parcelable.Creator<AquiferList>() {
+                public AquiferList createFromParcel(Parcel in) {
+                         return new AquiferList(in);
+                }
+                 public AquiferList[] newArray(int size) {
+                        return new AquiferList[size];
+                }
+        };
+        //constructor to set the tagName in case we need to;
+        private AquiferList(Parcel in) {
+                readFromParcel(in);
+        }
+	public int describeContents()
+	{
+		return 0;
+	}
+        public void writeToParcel(Parcel out, int flags) {
+                out.writeStringList(list);
+        }
+
+        public void readFromParcel(Parcel in) {
+               	 list = new ArrayList<String>();
+		 in.readStringList((ArrayList<String>)list);
+        }
+	
+	public AquiferList()
+	{
+		//initialize a full list by default
+		list = new ArrayList<String>();
+	}
+	public AquiferList(ArrayList<String> list2)
+	{
+		this.list = list2;
+	}
+	public ArrayList<String> getList()
+	{
+		return this.list;
+	}
+	public void setList(ArrayList<String> list2)
+	{
+		this.list = list2;
+	}
+	public boolean add(String t)
+	{	
+		if(t.equals(EMPTY))
+			return false;
+		boolean empty=this.isEMPTY();
+		boolean b = list.add(t);
+		//check if the list was EMPTY before this successful addition,
+		//and remove the empty flag if it is
+		if(b && empty)
+			list.remove(EMPTY);
+		return b;
+	} 
+	public boolean remove(String t)
+	{
+		boolean b =list.remove(t);
+		//if this was the last element, then set the list as EMPTY
+		if(list.isEmpty())
+			list.add(EMPTY);
+		return b;
+		
+	}
+	public boolean contains(String t)
+	{
+		return list.contains(t);
+	}
+	public void includeAll()
+	{
+		list.clear();
+	}
+	public void setEmpty()
+	{
+		list.clear();
+		list.add(EMPTY);
+	}
+	public String getAtIndex(int index)
+	{
+		return (String)(list.get(index));	
+	}
+	public boolean isEmpty()
+	{
+		return list.isEmpty();
+	}
+	public boolean isEMPTY()
+	{
+  		if((list.size()==1) &&  (list.contains(EMPTY)))
+			return true;
+		return false;	
+	}
+	public int size()
+	{
+		//Minimum list size is 1. Numerical intarray contains -1 if list is EMPTY
+		return list.size();
+	}
+	public void displayAquiferList()
+	{	
+		ListIterator<String> li1 = list.listIterator();
+                while(li1.hasNext())
+                {       String t1 = li1.next();
+			System.out.println("|"+t1+"|");
+                }	
+	}	
+
+	//Set functions:
+	//For list1 union list2
+        public static AquiferList listUnion(AquiferList list1, AquiferList list2)
+        {	
+		//checking for conditions when the list is either FULL(isEmpty) or EMPTY(isEMPTY) 
+		if(list1.isEmpty())
+			return list1;
+		else if(list2.isEmpty())
+			return list2;
+		else if(list1.isEMPTY())
+			return list2;
+		else if(list2.isEMPTY())
+			return list1;
+		else{}
+
+                AquiferList list3 = new AquiferList();
+                //Adding all of list1's elements to list3
+                ListIterator<String> li1 = list1.getList().listIterator();
+                while(li1.hasNext())
+                {
+                        list3.add(li1.next());
+                }
+
+                //iterating through list 2, and adding all the elements in 
+                //list 2 to list 3, except for all the elements that are already
+                //present in list3
+                ListIterator<String> li2 = list2.getList().listIterator();
+                while(li2.hasNext())
+                {
+                        String t =li2.next();
+                        boolean add = true;
+                        if(list3.contains(t))
+                        {
+                        	add = false;
+                        }
+                        if(add)
+                        {
+                                list3.add(t);
+                        }
+                }
+
+                return list3;
+        }
+
+        //for list1 INTERSECTION list2
+        public static AquiferList listIntersection(AquiferList list1, AquiferList list2)
+        {
+		//checking for conditions when the list is either FULL(isEmpty) or EMPTY(isEMPTY) 
+                if(list1.isEmpty())
+                        return list2;
+                else if(list2.isEmpty())
+                        return list1;
+                else if(list1.isEMPTY())
+                        return list1;
+		else if(list2.isEMPTY())
+			return list2;
+                else{}
+                
+                AquiferList list3 = new AquiferList();
+		//traversing list 1
+                //for each element in list 1, traversing list 2
+                //if a match is found in list2, adding it to list 3
+                //otherwise continue traversing list 1
+                ListIterator<String> li1 = list1.getList().listIterator();
+                while(li1.hasNext())
+                {       String t1 = li1.next();
+                        if(list2.contains(t1))
+                        {
+                        	list3.add(t1);
+                        }
+                }
+                return list3;
+        }
+}	
diff --git a/core/java/android/os/ComponentScreen.aidl b/core/java/android/os/ComponentScreen.aidl
new file mode 100644
index 0000000..ff8228f
--- /dev/null
+++ b/core/java/android/os/ComponentScreen.aidl
@@ -0,0 +1,3 @@
+package android.os;
+
+parcelable ComponentScreen;
diff --git a/core/java/android/os/ComponentScreen.java b/core/java/android/os/ComponentScreen.java
new file mode 100644
index 0000000..59a6d85
--- /dev/null
+++ b/core/java/android/os/ComponentScreen.java
@@ -0,0 +1,68 @@
+/* Abstraction for the ArrayList<String> Class.
+ * Defines set functions: union, intersection, difference for lists.
+ * Author: Adwait Nadkarni
+ */
+package android.os;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.io.Serializable;
+//to be used as both lists and pos and neg capabilities
+//since we have separated the pos and neg capabilities into 2 lists
+//this becomes easy.
+public class ComponentScreen implements Parcelable
+{	
+	String componentName;
+	int resultcode;
+	long timestamp;
+	public static final Parcelable.Creator<ComponentScreen> CREATOR = new
+        Parcelable.Creator<ComponentScreen>() {
+                public ComponentScreen createFromParcel(Parcel in) {
+                         return new ComponentScreen(in);
+                }
+                 public ComponentScreen[] newArray(int size) {
+                        return new ComponentScreen[size];
+                }
+        };
+        //constructor to set the tagName in case we need to;
+        private ComponentScreen(Parcel in) {
+                readFromParcel(in);
+        }
+	public int describeContents()
+	{
+		return 0;
+	}
+        public void writeToParcel(Parcel out, int flags) {
+                out.writeString(componentName);
+		out.writeInt(resultcode);
+		out.writeLong(timestamp);
+        }
+
+        public void readFromParcel(Parcel in) {
+		 
+		 this.componentName = in.readString();
+		 this.resultcode = in.readInt();
+		 this.timestamp = in.readLong();
+        }
+	
+	public ComponentScreen(String cname, int rcode, long tstamp)
+	{
+		componentName = cname;
+		resultcode = rcode;
+		timestamp = tstamp;
+	}
+	
+	public String getComponentName()
+	{
+		return this.componentName;	
+	}
+	public int getResultCode()
+	{
+		return this.resultcode;
+	}
+	public long getTimeStamp()
+	{
+		return this.timestamp;
+	}
+}	
diff --git a/core/java/android/os/Enforcement.aidl b/core/java/android/os/Enforcement.aidl
new file mode 100644
index 0000000..85951b2
--- /dev/null
+++ b/core/java/android/os/Enforcement.aidl
@@ -0,0 +1,3 @@
+package android.os;
+
+parcelable Enforcement;
diff --git a/core/java/android/os/Enforcement.java b/core/java/android/os/Enforcement.java
new file mode 100644
index 0000000..404e118
--- /dev/null
+++ b/core/java/android/os/Enforcement.java
@@ -0,0 +1,93 @@
+/* Enforcement Class.
+ * Defines Enforcement{AllowedList, RequiredList}
+ * Author: Adwait Nadkarni
+ */
+package android.os;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.AquiferList;
+import java.util.ListIterator;
+public class Enforcement implements Parcelable
+{	
+	private AquiferList AllowedList;
+	private AquiferList RequiredList;
+	public static final Parcelable.Creator<Enforcement> CREATOR = new
+        Parcelable.Creator<Enforcement>() {
+                public Enforcement createFromParcel(Parcel in) {
+                         return new Enforcement(in);
+                }
+                 public Enforcement[] newArray(int size) {
+                        return new Enforcement[size];
+                }
+        };
+        //constructor to set the tagName in case we need to;
+        private Enforcement(Parcel in) {
+                readFromParcel(in);
+        }
+	public int describeContents()
+	{
+		return 0;
+	}
+        public void writeToParcel(Parcel out, int flags) {
+                out.writeParcelable(AllowedList,flags);
+                out.writeParcelable(RequiredList,flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+               	 AllowedList = in.readParcelable(AquiferList.class.getClassLoader());
+               	 RequiredList = in.readParcelable(AquiferList.class.getClassLoader());
+        }
+	
+	//Constructors
+	public Enforcement()
+	{
+		//The allowedList is full by default
+		AllowedList = new AquiferList();
+		//The requiredList is empty by default
+		RequiredList = new AquiferList();
+		RequiredList.setEmpty();
+	}
+	public Enforcement(Enforcement e)
+	{
+		this.AllowedList = e.AllowedList;
+		this.RequiredList = e.RequiredList;
+	}
+
+	//Getters and Setters
+	public AquiferList getAllowedList()
+	{
+		return this.AllowedList;
+	}
+	public void setAllowedList(AquiferList allowed)
+	{
+		this.AllowedList = allowed;
+	}
+	public AquiferList getRequiredList()
+	{
+		return this.RequiredList;
+	}
+	public void setRequiredList(AquiferList required)
+	{
+		this.RequiredList = required;
+	}
+
+	//Enforcement Display method
+	public void displayEnforcement()
+	{	
+		System.out.println("Enforcement Lists:");
+		System.out.println("Allowed List:");
+		AllowedList.displayAquiferList();
+		System.out.println("Required List:");
+		RequiredList.displayAquiferList();
+	}	
+	
+	//Enforcement Join function
+	public static Enforcement enforcementJoin(Enforcement enforce1, Enforcement enforce2)
+	{
+		Enforcement enforce3 = new Enforcement();
+		enforce3.AllowedList = AquiferList.listIntersection(enforce1.getAllowedList(), enforce2.getAllowedList());
+		enforce3.RequiredList = AquiferList.listUnion(enforce1.getRequiredList(), enforce2.getRequiredList());
+		return enforce3;
+	}
+
+}	
diff --git a/core/java/android/os/Filter.aidl b/core/java/android/os/Filter.aidl
new file mode 100644
index 0000000..7b76ab5
--- /dev/null
+++ b/core/java/android/os/Filter.aidl
@@ -0,0 +1,3 @@
+package android.os;
+
+parcelable Filter;
diff --git a/core/java/android/os/Filter.java b/core/java/android/os/Filter.java
new file mode 100644
index 0000000..1d82961
--- /dev/null
+++ b/core/java/android/os/Filter.java
@@ -0,0 +1,107 @@
+/* Filter Class.
+ * Defines Filter{<Action, PrincialList>}
+ * Author: Adwait Nadkarni
+ */
+package android.os;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.AquiferList;
+import java.util.ListIterator;
+import java.util.HashMap;
+import java.io.Serializable;
+public class Filter implements Parcelable
+{	
+	private HashMap<String, AquiferList> FilterMap;
+	public static final Parcelable.Creator<Filter> CREATOR = new
+        Parcelable.Creator<Filter>() {
+                public Filter createFromParcel(Parcel in) {
+                         return new Filter(in);
+                }
+                 public Filter[] newArray(int size) {
+                        return new Filter[size];
+                }
+        };
+        //constructor to set the tagName in case we need to;
+        private Filter(Parcel in) {
+                readFromParcel(in);
+        }
+	public int describeContents()
+	{
+		return 0;
+	}
+        public void writeToParcel(Parcel out, int flags) {
+                out.writeMap(FilterMap);
+        }
+
+        public void readFromParcel(Parcel in) {
+		FilterMap = new HashMap<String, AquiferList>();
+               	in.readMap(FilterMap,AquiferList.class.getClassLoader());
+        }
+
+	//Constructors	
+	public Filter()
+	{
+		FilterMap = new HashMap<String, AquiferList>();
+	}
+	public Filter(Filter filter)
+	{
+		this.FilterMap = filter.FilterMap;
+	}
+
+	//Getters and Setters
+	public AquiferList getPrincipals(String action)
+	{
+		return this.FilterMap.get(action);
+	}
+	public void setPrincipals(String action, AquiferList Principals)
+	{
+		this.FilterMap.put(action, Principals);
+		//Principals.displayAquiferList();
+	}
+
+	public HashMap<String, AquiferList> getFilterMap()
+	{
+		return this.FilterMap;
+	}
+	public void setFilterMap(HashMap<String, AquiferList> FilterMap)
+	{
+		this.FilterMap = FilterMap;
+	}
+	public boolean containsAction(String action)
+	{
+		return this.FilterMap.containsKey(action);
+	}
+	//Display Method
+	public void displayFilter()
+	{	
+		System.out.println("Printing Filter:");
+		for ( String action : this.FilterMap.keySet())
+		{	
+			System.out.println("For Action:"+action);
+			(FilterMap.get(action)).displayAquiferList();	
+		}
+	}	
+
+	//Filter Join function
+	public static Filter filterJoin(Filter filter1, Filter filter2)
+	{
+		Filter filter3 = new Filter();
+
+		//copying filter1 to filter3
+		for ( String action : filter1.FilterMap.keySet())
+		{	
+			filter3.setPrincipals(action, filter1.FilterMap.get(action));
+		}
+		
+		//For common actions, take the intersection of the Principals
+		for ( String action : filter2.FilterMap.keySet())
+		{
+			if(filter3.containsAction(action))
+				filter3.setPrincipals(action, AquiferList.listIntersection(filter1.getPrincipals(action), filter2.getPrincipals(action)));		
+			else
+				filter3.setPrincipals(action, filter2.FilterMap.get(action));
+		}
+		return filter3;
+	}
+
+}	
diff --git a/core/java/android/os/IAquiferService.aidl b/core/java/android/os/IAquiferService.aidl
new file mode 100644
index 0000000..d7433e9
--- /dev/null
+++ b/core/java/android/os/IAquiferService.aidl
@@ -0,0 +1,50 @@
+package android.os;
+import android.os.AquiferList;
+import android.os.Policy;
+/**The AquiferService aidl.
+ * Author: Adwait Nadkarni
+ */
+interface IAquiferService
+{	
+	//Test Functions
+	String hi(int val);	
+//	String message(String val);
+
+	//Management Functions:
+	void addParticipant(String sprocessName, int spid, String rprocessName, int rpid, String rpackageName, int ruid, int resultcode, String componentName);
+	
+	//Utility Functions
+	String getProcessName(int pid);
+	
+	//Getting the principals list for a certain action         
+	AquiferList getPrincipalList(String sprocessName, int spid, String action);
+
+	//Adding Policy
+	void addPolicy(in Policy p);
+
+	//intercepting a databaseupdate
+	//void interceptDatabase();
+
+	//Managing the workflow when an activity is destroyed
+	void destroyActivity(String componentName);
+
+	//Adding a component to an existing participant
+	void addComponent( String sprocessName, int spid, String spackageName, int suid, int resultcode ,String rcomponentName);
+
+	//Join two workflows, and assign the join to the receiving workflow.
+	void workflowJoin(String sprocessName, int spid, String rprocessName, int rpid, String rpackageName, int ruid, int resultcode, String rcomponentName);
+	
+	//Verify if the process rprocessname is in the workflow of sprocessName
+	boolean isThisWorkflow(String sprocessName, int spid, String rprocessName, int rpid);
+
+	//Destroy a process to start a new one
+	void destroyEntireProcess(String processName, int pid);
+
+	//Storing packageName:uid mappings with the AquiferService on install
+	int storePackageName(String packageName, int uid);
+
+	//Removing packageName from the AquiferService on uninstall
+	int removePackageName(String packageName);
+
+}
+
diff --git a/core/java/android/os/Participant.aidl b/core/java/android/os/Participant.aidl
new file mode 100644
index 0000000..7b35e65
--- /dev/null
+++ b/core/java/android/os/Participant.aidl
@@ -0,0 +1,3 @@
+package android.os;
+
+parcelable Participant;
diff --git a/core/java/android/os/Participant.java b/core/java/android/os/Participant.java
new file mode 100644
index 0000000..51ef715
--- /dev/null
+++ b/core/java/android/os/Participant.java
@@ -0,0 +1,128 @@
+/* Participant Class.
+ * Defines a workflow Participant(processName, packageName, pid, uid, resultcode)
+ * Author: Adwait Nadkarni
+ */
+package android.os;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+import android.os.ComponentScreen;
+//to be used as both lists and pos and neg capabilities
+//since we have separated the pos and neg capabilities into 2 lists
+//this becomes easy.
+public class Participant implements Parcelable
+{	
+        String processName;
+        String packageName;
+        int pid;
+        int uid;
+        int resultcode;
+	ArrayList<ComponentScreen> componentList;
+	public static final Parcelable.Creator<Participant> CREATOR = new
+        Parcelable.Creator<Participant>() {
+                public Participant createFromParcel(Parcel in) {
+                         return new Participant(in);
+                }
+                 public Participant[] newArray(int size) {
+                        return new Participant[size];
+                }
+        };
+        //constructor to set the tagName in case we need to;
+        private Participant(Parcel in) {
+                readFromParcel(in);
+        }
+	public int describeContents()
+	{
+		return 0;
+	}
+        public void writeToParcel(Parcel out, int flags) {
+                out.writeString(processName);
+                out.writeString(packageName);
+		out.writeInt(pid);
+		out.writeInt(uid);
+		out.writeInt(resultcode);
+		out.writeList(componentList);
+        }
+
+        public void readFromParcel(Parcel in) {
+		processName=in.readString();
+		packageName=in.readString();
+		pid=in.readInt();
+		uid=in.readInt();
+		resultcode=in.readInt();
+		in.readList(componentList, ComponentScreen.class.getClassLoader());
+        }
+
+	//Constructor
+	public Participant(String processName, String packageName, int pid, int uid, int resultcode, ArrayList<ComponentScreen> componentList)
+        {
+                this.processName=processName;
+                this.packageName=packageName;
+                this.pid=pid;
+                this.uid=uid;
+                this.resultcode=resultcode;
+		this.componentList=componentList;
+        }
+                
+	//Getters
+        public String getProcessName()
+        {
+                return this.processName;
+        }
+        public String getPackageName()
+        {
+                return this.packageName;
+        }
+        public int getPid()
+        {
+                return this.pid;
+        }
+        public int getUid()
+        {
+                return this.uid;
+        }
+        public int getResultCode()
+        {
+                return this.resultcode;
+        }
+	public boolean isComponentEmpty()
+	{
+		return componentList.isEmpty();
+	}
+	public void removeComponent(String componentName)
+	{
+		//Removing the matching component with the latest timestamp
+		Iterator<ComponentScreen> iterator = componentList.iterator();
+		long timestamp=0;
+		int index=0;
+		while(iterator.hasNext())
+		{
+			ComponentScreen current = iterator.next();
+			if(current.getComponentName().equals(componentName))
+			{
+				if(current.getTimeStamp() >= timestamp)
+				{
+					timestamp = current.getTimeStamp();
+					index = componentList.indexOf(current);
+				}	
+			}
+		}
+		componentList.remove(index);
+	}
+	public void addComponent(String componentName, int resultcode)
+	{
+		componentList.add(new ComponentScreen(componentName, resultcode, System.currentTimeMillis()));
+	}
+	public ArrayList<ComponentScreen> getComponentList()
+	{
+		return componentList;
+	}
+	// Participant Display Method
+	public void displayParticipant()
+	{	
+		System.out.println("Participant:");
+		System.out.println("process:"+processName+":"+pid+"|package"+packageName+":"+uid+"|resultcode="+resultcode);
+	}
+}	
diff --git a/core/java/android/os/Policy.aidl b/core/java/android/os/Policy.aidl
new file mode 100644
index 0000000..d5fdb48
--- /dev/null
+++ b/core/java/android/os/Policy.aidl
@@ -0,0 +1,3 @@
+package android.os;
+
+parcelable Policy;
diff --git a/core/java/android/os/Policy.java b/core/java/android/os/Policy.java
new file mode 100644
index 0000000..c5f5cd5
--- /dev/null
+++ b/core/java/android/os/Policy.java
@@ -0,0 +1,137 @@
+/* Aquifer Policy Class.
+ * Defines Policy{Enforcement, Filter}
+ * Author: Adwait Nadkarni
+*/
+
+package android.os;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.AquiferList;
+//import android.os.Enforcement;
+import android.os.Filter;
+import java.util.ListIterator;
+import java.io.Serializable;
+
+public class Policy implements Parcelable, Serializable
+{	
+	private AquiferList ExportList;
+	private AquiferList RequiredList;
+//	private Enforcement enforcement;
+	private Filter filter;
+	public static final Parcelable.Creator<Policy> CREATOR = new
+        Parcelable.Creator<Policy>() {
+                public Policy createFromParcel(Parcel in) {
+                         return new Policy(in);
+                }
+                 public Policy[] newArray(int size) {
+                        return new Policy[size];
+                }
+        };
+        //constructor to set the tagName in case we need to;
+        private Policy(Parcel in) {
+                readFromParcel(in);
+        }
+	public int describeContents()
+	{
+		return 0;
+	}
+        public void writeToParcel(Parcel out, int flags) {
+  //              out.writeParcelable(enforcement,flags);
+                out.writeParcelable(ExportList,flags);
+                out.writeParcelable(RequiredList,flags);
+                out.writeParcelable(filter,flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+//               	 enforcement = in.readParcelable(Enforcement.class.getClassLoader());
+               	 ExportList = in.readParcelable(AquiferList.class.getClassLoader());
+               	 RequiredList = in.readParcelable(AquiferList.class.getClassLoader());
+               	 filter = in.readParcelable(Filter.class.getClassLoader());
+        }
+
+	//Constructors	
+	public Policy()
+	{
+//		enforcement = new Enforcement();
+	        ExportList = new AquiferList();
+		RequiredList = new AquiferList();
+		RequiredList.setEmpty();	
+		filter = new Filter();
+	}
+	public Policy(Policy policy)
+	{
+//		this.enforcement = policy.enforcement;
+		this.filter = policy.filter;
+		this.ExportList = policy.ExportList;
+		this.RequiredList = policy.RequiredList;
+	}
+
+	//Getters and Setters
+/*	public Enforcement getEnforcement()
+	{
+		return this.enforcement;
+	}
+	public void setEnforcement(Enforcement enforcement)
+	{
+		this.enforcement = enforcement;
+	}
+*/	//
+	public Filter getFilter()
+	{
+		return this.filter;
+	}
+	public void setFilter(Filter filter)
+	{
+		this.filter = filter;
+	}
+	//
+	public AquiferList getExportList()
+	{
+		return this.ExportList;
+	}
+	public void setExportList(AquiferList export)
+	{
+		this.ExportList = export;
+	}
+	//
+	public AquiferList getRequiredList()
+	{
+		return this.RequiredList;
+	}
+	public void setRequiredList( AquiferList required)
+	{
+		this.RequiredList = required;
+	}
+
+	//Policy Display Method
+	public void displayPolicy()
+	{	
+		System.out.println("Policy:");
+//		enforcement.displayEnforcement();
+		System.out.println("Export List:");
+		ExportList.displayAquiferList();
+		System.out.println("Required List:");
+		RequiredList.displayAquiferList();
+		filter.displayFilter();
+	}	
+
+	//Policy Join
+	public static Policy policyJoin(Policy policy1, Policy policy2)
+	{
+		if(policy1 == null)
+			return policy2;
+		else if(policy2==null)
+			return policy1;
+		else{
+			Policy policy3 = new Policy();
+//			policy3.setEnforcement(Enforcement.enforcementJoin(policy1.getEnforcement(), policy2.getEnforcement()));
+			policy3.setFilter(Filter.filterJoin(policy1.getFilter(), policy2.getFilter()));			
+			policy3.ExportList = AquiferList.listIntersection(policy1.getExportList(), policy2.getExportList());
+                	policy3.RequiredList = AquiferList.listUnion(policy1.getRequiredList(), policy2.getRequiredList());
+		
+			return policy3;
+		}
+	
+	}
+
+}	
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index e1bc275..9514d1a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.os.IAquiferService;
 import android.net.LocalSocketAddress;
 import android.net.LocalSocket;
 import android.util.Log;
@@ -722,7 +723,23 @@ public class Process {
      * other's processes.
      */
     public static final void killProcess(int pid) {
+	//Adwait's patch	
+	String processName="initial";
+	IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try{
+       		processName=aquifer.getProcessName(pid);
+        }
+        catch(Exception e)
+        {
+		System.out.println("Exception at android.os.Proceess:killProcess");
+	}
+	System.out.println("Killing process "+processName+":"+pid);
+	//Adwait's patch ends
+	//get procname:pid here
         sendSignal(pid, SIGNAL_KILL);
+	//get procname:pid here. If same obtained, then
+	//the process has been killed; so now remove it from the
+	//workflow
     }
 
     /** @hide */
@@ -746,6 +763,17 @@ public class Process {
      * beat you up.
      */
     public static final void killProcessQuiet(int pid) {
+	//Adwait's patch        
+        String processName="initial";
+        IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try{   
+                processName=aquifer.getProcessName(pid);
+        }
+        catch(Exception e)
+        {
+                System.out.println("Exception at android.os.Proceess:killProcess");
+        }
+        System.out.println("Killing process "+processName+":"+pid);
         sendSignalQuiet(pid, SIGNAL_KILL);
     }
 
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index fa49592..122ca32 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -22,7 +22,7 @@ LOCAL_SHARED_LIBRARIES := \
     libhardware_legacy \
     libeffects \
     libdl \
-    libpowermanager
+    libpowermanager \
 
 LOCAL_STATIC_LIBRARIES := \
     libcpustats \
diff --git a/services/java/com/android/server/AquiferService.java b/services/java/com/android/server/AquiferService.java
new file mode 100644
index 0000000..0c515cd
--- /dev/null
+++ b/services/java/com/android/server/AquiferService.java
@@ -0,0 +1,1979 @@
+package com.android.server;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManager.RunningServiceInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ServiceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IAquiferService;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.util.Log;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import android.os.Binder;
+import android.os.ServiceManager;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ListIterator;
+import android.util.SparseArray;
+//Aquifer API
+import android.os.ComponentScreen;
+import android.os.Enforcement;
+import android.os.Filter;
+import android.os.Policy;
+import android.os.AquiferList;
+import android.os.Participant;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ByteArrayInputStream;
+//SECURITY 
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.lang.StackTraceElement;
+import java.lang.Thread;
+import android.app.Activity;
+import java.util.Random;
+public class AquiferService extends IAquiferService.Stub 
+    {
+   	private static final String TAG = "AquiferService";
+	private Context mContext;
+	//private static final int POLICY_SIZE = 1024;
+	private static final int POLICY_SIZE = 224;
+	private static final int POLICY_VALID = 2;
+	private static final int POLICY_INVALID = 3;
+	private static final HashMap<String, WLabel> WorkflowMap = new HashMap<String, WLabel>();  	
+	private static final HashMap<String, String> WorkflowKey = new HashMap<String, String>();  	
+	private static final HashMap<String,HashMap<String, Policy>> file_label = new HashMap<String,HashMap<String, Policy>>();  	
+	private static HashMap<String, Integer> PackageMap = new HashMap<String, Integer>();
+	//Constructor
+	public AquiferService(Context context) 
+    	{
+		super();
+		mContext = context;
+		Log.i(TAG, "AquiferService Constructed");
+		int n=5;
+
+		//Commenting socket creation for now
+               int x=democallThread(n);
+               System.out.println("RESULT OF DEMOCALL ="+x);
+
+		//Creating the file to hold filePolicyMaps
+		File file = new File("/data/system/aquifermap");
+		try{
+			if(!file.exists()){
+		        	file.createNewFile();
+		       		System.out.print("PackageMap file /data/system/aquifermap created");
+				FileOutputStream f = new FileOutputStream(file);
+		        	ObjectOutputStream s = new ObjectOutputStream(f);
+		        	s.writeObject(PackageMap);
+		        	s.close();
+			}
+		}
+		catch(Exception e)
+		{
+			System.out.println("File Creation Error:AquiferService:"+e);
+			
+		}
+
+		
+    	}
+	public String hi(int val)
+	{
+		return "hello"+val;
+	}
+
+	private int message(final int pid, final int inode, final int mask, byte[] policy)
+    	{   	
+		//System.out.println("Enters message");
+		new Thread(new Runnable() {
+                        public void run() {
+				//System.out.println("Data from JNI:"+pid+"::"+inode+".");
+				synchronized(this)
+				{
+					//fileAccess(pid,inode);
+				}
+				//do something
+                        }
+                }).start();
+        	return 0;
+    	}
+
+	private int readFile( final int pid, int inode, int mask, final int[] policy)
+	{
+		//System.out.println("readFile called from the jni:"+policy[0]+"pid="+pid+"inode="+inode);
+		/*
+		new Thread(new Runnable() {
+                        public void run() {
+				*/
+                                synchronized(this)
+                                {
+                                        readFileInternal(pid,policy);
+                                }
+				/*
+                        }
+                }).start();
+		*/
+		return 0;
+	}
+		
+	private int[] writeFile( final int pid, int inode, int mask, final int[] policy)
+        {
+                //System.out.println("writeFile called from the jni:"+policy[0]+"pid="+pid+"inode="+inode);
+               // new Thread(new Runnable() {
+                 //       public void run() {
+                                synchronized(this)
+                                {
+                                        return writeFileInternal(pid,policy);
+                                }
+                       // }
+               // }).start();
+        }
+/**************************************************************************************************************/
+	//Specific AquiferService Management Functions
+
+	//Checks if the process is a part of this workflow
+	public boolean isThisWorkflow(String sprocessName, int spid, String rprocessName, int rpid)
+	{
+		//TODO: Validate caller here.
+		String sindex = sprocessName+":"+spid;
+		String rindex = rprocessName+":"+rpid;
+		if(sindex.equals(rindex))
+		{
+			//System.out.println("Started by self");
+			return true;
+		}
+	
+		WLabel slabel=null;
+		String skey=null;
+		if(sprocessName!=null)
+                        skey = WorkflowKey.get(sindex);
+		if(skey==null)
+		{	//System.out.println("Null key for sender "+sindex);
+			return false;
+		}
+		else
+		{
+			slabel = WorkflowMap.get(skey);
+                	if(slabel==null)
+                	{
+				//System.out.println("Null label for sender "+sindex);
+				return false;
+			}	
+		}
+
+		WLabel rlabel=null;
+		String rkey=null;
+		if(rprocessName!=null)
+                        rkey = WorkflowKey.get(rindex);
+		if(rkey==null)
+		{	//System.out.println("Null key for receiver "+rindex);
+			return false;
+		}
+		else
+		{
+			rlabel = WorkflowMap.get(rkey);
+                	if(rlabel==null)
+                	{
+				//System.out.println("Null label for receiver "+rindex);
+				return false;
+			}	
+		}
+		if(rkey.equals(skey))
+		{	
+			//System.out.println("Process "+rindex+ "created in the same workflow pointed by "+skey);
+			return true;
+		}
+		return false;
+	}
+	//Adding a component to an existing participant
+	public void addComponent( String sprocessName, int spid, String spackageName, int suid, int resultcode ,String rcomponentName) {
+		validateCaller();
+		WLabel label=null;
+                String index=sprocessName+":"+spid;
+		System.out.println("Adding component "+rcomponentName+" started by "+index);
+                String key=null;
+                if(sprocessName!=null)
+                        key = WorkflowKey.get(index);
+		if(key==null)
+		{
+			//System.out.println("AquiferService:No workflowKey for "+index+" in addComponent");
+			//Get all the fields and addParticipant(sprocessName, spid, );
+			addParticipant( sprocessName, spid, sprocessName, spid, spackageName, suid, resultcode, rcomponentName);
+			return;
+		}
+		
+		label=WorkflowMap.get(key);
+                if(label==null)
+                {
+                        //System.out.println("AquiferService:addComponent: Error!!No workflow for key:"+key);
+                                //TODO: Handle by removing the index's entry from WorkflowKey
+                }
+                else
+                {       synchronized(this)
+                 	{    
+				Iterator<Participant> iterator = label.ParticipantList.iterator();
+                        	while(iterator.hasNext())
+                       		{
+                               		Participant part = iterator.next();
+                               		int part_pid = part.getPid();
+					String part_processName = part.getProcessName();
+					String part_index=part_processName + ":" + part_pid;
+					if(part_index.equals(index))
+					{
+						part.addComponent(rcomponentName, resultcode);
+						//System.out.println("Successfully added component "+rcomponentName);
+						break;
+					}
+                       		}					
+				//Adding the component to the HistoryList
+				Iterator<Participant> iterator2 = label.HistoryList.iterator();
+                                while(iterator.hasNext())
+                                {
+                                        Participant part = iterator.next();
+                                        int part_pid = part.getPid();
+                                        String part_processName = part.getProcessName();
+                                        String part_index=part_processName + ":" + part_pid;
+                                        if(part_index.equals(index))
+                                        {
+                                                part.addComponent(rcomponentName, resultcode);
+                                                //System.out.println("Successfully added component "+rcomponentName);
+                                                break;
+                                        }
+                                }
+                        }
+		System.out.println("Printing label on adding component");
+		//label.displayLabel();
+                }
+		
+	}
+
+	
+	//Adding a participant to a workflow
+	public void addParticipant( String sprocessName, int spid, String rprocessName, int rpid, String rpackageName, int ruid, int resultcode, String rcomponentName) {
+
+		//TODO: get the componentName from the method call
+		
+		//TODO: ValidateCaller
+		//Sanity Check
+		//System.out.println("MY PID!!!!!!!!!!!!!!!!!!!!!!!!>>>>"+android.os.Process.myPid());
+		validateCaller();
+		//System.out.println("Adding participant "+rprocessName+":"+rpid+" from sender "+sprocessName+":"+spid);
+		if(rprocessName==null || rpid==0)
+		{	
+			//System.out.println("Undefined input to AquiferService:addParticipant:");
+			//System.out.println("Sender:"+sprocessName+":"+spid);
+			//System.out.println("Receiver:"+rprocessName+":"+rpid);
+			return;
+		}
+
+		WLabel label=null;
+		String index=sprocessName+":"+spid;
+		String key=null;
+		if(sprocessName!=null)
+			key = WorkflowKey.get(index);
+		ArrayList<ComponentScreen> componentList = new ArrayList<ComponentScreen>();
+		componentList.add(new ComponentScreen(rcomponentName, resultcode, System.currentTimeMillis()));
+		Participant part = new Participant(rprocessName,rpackageName,rpid, ruid,resultcode,componentList);
+		//if there is no key for the sender's index, then the receiver
+		//is being started by the launcher Thus, create a new workflow
+		//starting with the receiver.
+		if(key == null)
+		{	synchronized(this)
+			{	
+				label=createWorkflow(rprocessName, rpid);
+				if(label==null)
+					System.out.println("Workflow Creation Failure!");
+				else 
+				{	//adding the first participant to the newly created workflow
+					label.ParticipantList.add(part);
+					label.HistoryList.add(part);
+				}	
+			}
+		}
+		else // If a workflow already exists for the caller
+		{
+			//System.out.println("Adding "+rprocessName+":"+rpid+" to existing workflow of "+key);	
+			label=WorkflowMap.get(key);
+			if(label==null)
+			{	
+				System.out.println("ERROR!!No workflow for key:"+key);
+				//TODO: Handle by removing the index's entry from WorkflowKey
+			}
+			else//Everything's normal.
+			{	synchronized(this)
+				{
+					label.ParticipantList.add(part);
+                                	label.HistoryList.add(part);
+					WorkflowKey.put(rprocessName+":"+rpid,key);
+				}
+			}
+		}
+		//label.displayLabel();
+	
+		//Configsuring Internet Access Policy for the process being added to the workflow.
+		Policy effective = label.effectivePolicy();
+		//System.out.println("Checking the policy in addParticipant");
+		//System.out.println("Effective Policy, rpackagename=:"+rpackageName);
+		//effective.displayPolicy();
+
+		AquiferList ExportList=effective.getExportList();
+		if(ExportList.isEmpty())
+                {
+                        setInternet(rpid, 0);
+                        //System.out.println("Granting Internet privilege for pid "+rpid);
+		}
+   		else if(ExportList.isEMPTY())
+                {
+                        //System.out.println("Revoking Internet privilege for pid "+rpid);
+                        setInternet(rpid, 1);
+                }
+                else
+                {
+                        if(ExportList.contains(rpackageName))
+                        {       //allow
+                                setInternet(rpid, 0);
+                                //System.out.println("Granting Internet privilege for pid "+rpid);
+                        }
+                        else
+                        {       //deny
+                                //System.out.println("Revoking Internet privilege for pid "+rpid);
+                                setInternet(rpid, 1);
+                        }
+                }
+
+		//Since we added a participant, we check the RequiredList
+		requiredCheck(label, effective.getRequiredList());
+
+		//TEST: Printing all the currently running processes every time a participant is added
+		/*ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
+		System.out.println("pid          processname");
+                for(RunningAppProcessInfo pInfo : am.getRunningAppProcesses())
+                {
+                	try{   
+				int pid=pInfo.pid;
+				String processName=pInfo.processName;	
+				System.out.println(pid+"          "+processName);
+                        }
+                        catch(Exception e)
+                        {
+				System.out.println("Exception at AquiferService:addParticipant,printing active processes:"+e);
+			}
+                }*/
+	}
+	
+	private int democallThread(final int n)
+	{
+		//System.out.println("Inside DEMOCALL THREAD");
+		 new Thread(new Runnable() {
+      			public void run() {
+				//System.out.println("DEMOCALL STARTS");
+        			int x=	democall(n);
+				//System.out.println("DEMOCALL FROM KERNEL RETURNS:"+x);	
+			}
+    		}).start();
+		return 0;
+	}
+	
+	//Creating a new workflow
+    	private WLabel createWorkflow(String processName, int pid)
+	{
+		WLabel label= new WLabel();
+		String index=processName+":"+pid;
+		System.out.println("Creating new workflow for "+index);
+		WorkflowMap.put(index, label);
+		WorkflowKey.put(index,index);
+		return label;
+	}
+	
+	//Adding a data "Owner's" policy, through one of its components.
+	public void addPolicy(Policy policy)
+	{
+		int current_pid = Binder.getCallingPid();
+		String processName = getProcessName(current_pid);
+		if(policy==null)
+			return;
+		//Displaying policy
+		//System.out.println("Policy to add:");
+		//policy.displayPolicy();
+
+		//ProcessName for the current pid does not exist!!
+		//Return immediately
+                if(processName == null || processName.equals(""))
+                {
+		//	System.out.println("Unknown Exception at AquiferService:addPolicy, processName="+processName);
+			return;
+		}
+		synchronized(this)
+		{//Getting the workflow for this component
+			WLabel label=null;
+                	String index=processName+":"+current_pid;
+			//System.out.println("Adding policy for "+index);
+        	        String key=null;
+		
+			//Getting the workflowKey
+			key = WorkflowKey.get(index);
+			if(key==null)
+			{
+				//System.out.println("Creating new workflow for "+index);
+				//TODO: Create workflow and add this process to it
+				//then get key again and continue	
+			}
+			
+			//Getting the workflow label from the key
+			label=WorkflowMap.get(key);
+                	if(label==null)
+                	{
+                		System.out.println("ERROR!!No workflow for key:"+key+" at AquiferService:addPolicy");
+                        	//TODO: Handle by removing the index's entry from WorkflowKey and returning??
+				//On the next attempt, a new workflow will be created due to the check above.
+				return;
+                	}
+
+			//getting the packagename, i.e. the owner for the calling process
+			String packageName = getPackageName(index, label.ParticipantList);
+	 		if(packageName == null)
+			{
+				System.out.println("Null packageName for "+index+" in the workflow");
+				return;
+			}
+			else
+			{	//Finally adding the policy for the calling Application
+				label.PolicyMap.put(packageName, policy);
+				//rechecking add reassigning the internet privilege throughout the workflow.
+				//System.out.println("Successfully added policy for package "+ packageName);
+				checkInternet(label);
+				//Printing the label
+				//label.displayLabel();
+			}
+		
+		}
+
+	}
+
+	//Returns the principalslist for the particular action
+	public AquiferList getPrincipalList(String sprocessName, int spid, String action)
+	{
+		 //validateCaller();
+		 synchronized(this)
+                 {//Getting the workflow for this component
+			try{
+                        	WLabel label=null;
+                	        String index=sprocessName+":"+spid;
+        	                String key=null;
+	
+                	        //Getting the workflowKey
+        	                key = WorkflowKey.get(index);
+	                        if(key==null)
+                        	{
+                	                System.out.println("No workflow for "+index+": Filtering Policy at AquiferPolicy: getPrincipalList");
+					return null;
+	                        }
+				//System.out.println("Key found: getPrincipalList");
+                	        //Getting the workflow label from the key
+        	                label=WorkflowMap.get(key);
+	                        if(label==null)
+                        	{
+                	                System.out.println("ERROR!!No workflow for key:"+key+" at AquiferService:getPrincipalList");
+        	                        return null;
+	                        }
+				//System.out.println("Label found: getPrincipalList");
+				Policy effective = label.effectivePolicy();
+				if(effective == null)		
+				{		
+					System.out.println("Null Effective Policy: getPrincipalList");
+					return null;
+				}
+				return effective.getFilter().getPrincipals(action);
+			}
+			catch(Exception e)
+			{
+				System.out.println("Exception at AquiferService:getPrincipalList:"+e);
+				return null;
+			}
+		}
+
+	}
+
+	//To manage the workflow in case an activity has been destroyed
+	public void destroyActivity( String componentName)
+	{
+		//get the pid and the processName of the activity being destroyed
+		int pid=Binder.getCallingPid();
+		String processName=getProcessName(pid);
+		
+		//Manage state for the activity
+		activityDestroyed(pid, processName, componentName);
+		/*
+		//Then kill its process; if it is not system or launcher or pid 0
+		if((pid!=0 && !processName.equals("system") && !processName.equals("com.launcher")))
+		{	
+			System.out.println("Killing process "+processName+":"+pid);
+			android.os.Process.killProcess(pid);	
+			
+		}
+		*/
+	}
+	private void activityDestroyed(int pid, String processName, String componentName)
+	{
+		try{
+			 WLabel label=null;
+                         String index=processName+":"+pid;
+                         String key=null;
+
+                         //Getting the workflowKey
+                         key = WorkflowKey.get(index);
+                         if(key==null)
+                         { 
+                          //      System.out.println("No workflow for "+index+": Filtering Policy at AquiferPolicy: activityDestroyed");
+                                return;
+                         }
+                        //System.out.println("Key found: activityDestroyed");
+                        //Getting the workflow label from the key
+                        label=WorkflowMap.get(key);
+                        if(label==null)
+                        { 
+                                System.out.println("ERROR!!No workflow for key:"+key+" at AquiferService:activityDestroyed");
+                                return;
+                        }
+			
+      			//Getting the participantlist, and this participant
+			ArrayList<Participant> ParticipantList = label.ParticipantList;
+                        if(ParticipantList == null)
+                        {
+                                 System.out.println("Error!:Null participant list at AquiferService:activityDestroyed");
+                                 return;
+                        }
+
+                        //Getting this participant from the Participants list
+                        Iterator<Participant> iterator = ParticipantList.iterator();
+			Participant part_this=null;
+                        while(iterator.hasNext())
+                        {
+                                Participant part = iterator.next();
+				String tempindex=part.getProcessName()+":"+part.getPid();
+				if(tempindex.equals(index))
+				{
+					part_this=part;
+					break;
+				}
+                        }
+			if(part_this==null)
+			{
+				System.out.println("No participant found for "+index+" at AquiferService:activityDestroyed");
+				return;
+			}
+			else
+			{	
+				//System.out.println("Participant "+index+" obtained.");
+			}
+
+			boolean policyRemove=true;
+			int resultcode = part_this.getResultCode();			
+			//If it returns a result, do not remove its policy
+			if(resultcode>=0)
+				policyRemove=false;
+
+			//If it does not return a result, but some of its application's components are still
+			//present in the workflow, do not remove its policy
+			if(policyRemove)
+			{
+				String packageName=part_this.getPackageName();
+				iterator = ParticipantList.iterator();
+				while(iterator.hasNext())
+	                        {
+        	                        Participant part = iterator.next();
+					String tempindex=part.getProcessName()+":"+part.getPid();
+                	                if(!tempindex.equals(index) && part.getPackageName().equals(packageName))
+                        	        {
+                                	       	policyRemove=false;
+                                        	break;
+                                	}	
+                        	}
+
+				//Check the HistoryList for a component with returncode=1,
+				//If there is one, then policyRemove=false
+				iterator = label.HistoryList.iterator();
+				while(iterator.hasNext())
+                                {
+                                        Participant part = iterator.next();
+                                        String tempindex=part.getProcessName()+":"+part.getPid();
+                                        if(!tempindex.equals(index) && part.getPackageName().equals(packageName))
+                                        {
+						//check for component with resultcode=1 		
+						ArrayList<ComponentScreen> componentList = part.getComponentList();
+						Iterator<ComponentScreen> compiterator = componentList.iterator();
+						while(compiterator.hasNext())
+						{
+							if(compiterator.next().getResultCode()==1)
+                                                	{	policyRemove=false;
+                                                		break;
+							}
+						}
+						break;
+                                        }
+                                }
+
+				if(policyRemove)
+				{	
+					label.PolicyMap.remove(packageName);
+				}
+			}
+
+			//remove from the Participants list
+			part_this.removeComponent(componentName);
+			if(part_this.isComponentEmpty())
+			{	
+				if((part_this.getPid()!=0 && !part_this.getProcessName().equals("system") && !part_this.getProcessName().equals("com.launcher")))
+                                {
+                                       // System.out.println("Killing process "+part_this.getProcessName()+":"+part_this.getPid());
+                                        //android.os.Process.killProcess(part_this.getPid());
+                        
+                                }
+				ParticipantList.remove(part_this);
+				//Removing from WorkflowKey
+				//TODO:Remove only if there is no other participant with the same processName:pid combination
+				WorkflowKey.remove(index);
+
+				//if this was the start of the workflow
+				//Make the next participant the start of the workflow
+				if(key.equals(index)){//And there is no other Participant with the same index
+					if(!ParticipantList.isEmpty())
+					{
+						iterator = ParticipantList.iterator();
+						Participant newHead = iterator.next();
+						String newHeadIndex = newHead.getProcessName() + ":" + newHead.getPid();					
+						WLabel wflowlabel =  WorkflowMap.remove(index);
+						WorkflowMap.put(newHeadIndex, wflowlabel);
+						synchronized(this)
+						{	
+							if(newHead.getProcessName() == null || newHead.getProcessName().equals(""))
+							{	
+								System.out.println("WTF::Participant process null:process="+newHead.getProcessName()+" pid="+newHead.getPid());
+								return;
+							}
+							while(iterator.hasNext())
+		                                	{
+                		                        	Participant part = iterator.next();
+                                		        	String tempindex=part.getProcessName()+":"+part.getPid();
+								WorkflowKey.put(tempindex, newHeadIndex);
+                                			}
+						}	
+					}
+					else
+					{
+						WorkflowMap.remove(index);
+					}
+				}
+			}
+			
+		}	
+		catch(Exception e)
+		{System.out.println("Exception at activityDestroy");}
+		//To maintain consistency in the workflow:
+		//policyRemove=true
+		//Check if the result code is >=0
+		//if it is, policyRemove = false	
+		//if policyRemove == true,
+		// check if there is even 1 participant with the same packagename and resultcode >=0
+		//if found even one, policyRemove=false
+
+		//remove the participant from the ParticipantList
+		//if policyRemove = true
+		// remove the package's policy frm the policy map
+	}
+	
+	public void destroyEntireProcess(String processName, int pid){
+	try{
+        	WLabel label=null;
+                String index=processName+":"+pid;
+              	String key=null;
+                //Getting the workflowKey
+                key = WorkflowKey.get(index);
+                if(key==null)
+                {
+                	//System.out.println("No workflow for "+index+": at destroyEntireProcess");
+                        android.os.Process.killProcess(pid);
+			return;
+                }
+                //Getting the workflow label from the key
+                label=WorkflowMap.get(key);
+                if(label==null)
+                {
+                        //System.out.println("ERROR!!No workflow for key:"+key+" at AquiferService:activityDestroyed");
+			android.os.Process.killProcess(pid);
+                        return;
+                }
+		
+	        //Getting the participantlist, and this participant
+                ArrayList<Participant> ParticipantList = label.ParticipantList;
+                if(ParticipantList == null)
+                {
+                        //System.out.println("Error!:Null participant list at AquiferService:activityDestroyed");
+			android.os.Process.killProcess(pid);
+                        return;
+                }
+                Iterator<Participant> iterator = ParticipantList.iterator();
+                Participant part_this=null;
+                while(iterator.hasNext())
+                {
+                	 Participant part = iterator.next();
+                         String tempindex=part.getProcessName()+":"+part.getPid();
+                         if(tempindex.equals(index))
+                         {
+                                part_this=part;
+                         	break;
+               	         }
+               	}
+               	if(part_this==null)
+               	{
+                        //System.out.println("No participant found for "+index+" at AquiferService:activityDestroyed");
+			android.os.Process.killProcess(pid);
+                        return;
+		}
+			
+		//Cleaning up the workflow
+		boolean policyRemove=true;
+                int resultcode = part_this.getResultCode();
+                //If it returns a result, do not remove its policy
+                if(resultcode>=0)
+                	policyRemove=false;
+                //If it does not return a result, but some of its application's components are still
+                //present in the workflow, do not remove its policy
+                if(policyRemove)
+                {
+                	String packageName=part_this.getPackageName();
+                        iterator = ParticipantList.iterator();
+                        while(iterator.hasNext())
+                        {
+                        	Participant part = iterator.next();
+                                String tempindex=part.getProcessName()+":"+part.getPid();
+                                if(!tempindex.equals(index) && part.getPackageName().equals(packageName))
+                                {
+                                        policyRemove=false;
+                                        break;
+                                }
+                        }
+                        if(policyRemove)
+                                label.PolicyMap.remove(packageName);
+                }
+		ParticipantList.remove(part_this);
+                WorkflowKey.remove(index);
+		//If the head is being killed, replace it with the next node
+		//If not possible, then remove the workflow.
+		if(key.equals(index)){
+                	if(!ParticipantList.isEmpty())
+                        {
+                        	iterator = ParticipantList.iterator();
+                                Participant newHead = iterator.next();
+                                String newHeadIndex = newHead.getProcessName() + ":" + newHead.getPid();
+                                WLabel wflowlabel =  WorkflowMap.remove(index);
+                                WorkflowMap.put(newHeadIndex, wflowlabel);
+                                synchronized(this)
+                                {
+                                	if(newHead.getProcessName() == null || newHead.getProcessName().equals(""))
+                                        {
+                                        	System.out.println("WTF::Participant process null:process="+newHead.getProcessName()+" pid="+newHead.getPid());
+						android.os.Process.killProcess(pid);
+                                                return;
+                                        }
+                                      	while(iterator.hasNext())
+                                        {
+                                        	Participant part = iterator.next();
+                                                String tempindex=part.getProcessName()+":"+part.getPid();
+                                                WorkflowKey.put(tempindex, newHeadIndex);
+                                        }
+                                }
+                        }
+                        else
+                        {
+                        	WorkflowMap.remove(index);
+                        }
+		}
+	}
+	catch(Exception e){
+		System.out.println("Exception while removing entire process:"+e);
+	}
+	android.os.Process.killProcess(pid);
+	return;
+	}
+	
+	//Serialize a AquiferList to an integer ArrayList
+	private void translateListToInt(AquiferList aquiferlist, ArrayList<Integer> finalPolicy)
+	{
+		finalPolicy.add(aquiferlist.size());
+		int size = aquiferlist.size();
+		int notNull = size;
+	
+		ArrayList<String> stringlist= aquiferlist.getList();
+		Iterator<String> iterator = stringlist.iterator();
+                while(iterator.hasNext())
+                {
+                        String packageName = iterator.next();
+                    	if(packageName.equals("EMPTY")){
+				finalPolicy.add(new Integer(-1));
+				continue;
+			}
+			Integer uid = getUid(packageName);
+			if(uid==null)
+			{
+				//TODO: What if more than one packages are not found. We will have more than 1 -2s, still the list won't have a -1 if necessary.
+				//Should we have such filtering at addPolicy itself?
+				//add dummy, so that you don't have to go back a few steps and update the size of the list.
+				if(size >1)
+                                	finalPolicy.add(-2);
+				else 
+					finalPolicy.add(-1);//if the list had 1 element, which is also not found, it is empty.
+				continue;
+			}
+			else finalPolicy.add(uid);
+                }
+	}
+	
+	//Serialize a policy to an ArrayList<Integer>
+	private void translateToInt(Policy policy, ArrayList<Integer> finalPolicy)
+	{
+		translateListToInt(policy.getExportList(), finalPolicy);
+		translateListToInt(policy.getRequiredList(), finalPolicy);
+	
+		//Propagating the Filter
+		//Putting the ascii representation of the Filter String	
+		//Adding the length of the filter, just to know when the filter ends
+		finalPolicy.add(policy.getFilter().getFilterMap().size());
+		for ( String action : policy.getFilter().getFilterMap().keySet())
+                {
+			//Add the ascii representation of the action string to the list.
+			addActionToList(action, finalPolicy);
+			//Add the list associated with the action string. 
+              		translateListToInt(policy.getFilter().getPrincipals(action), finalPolicy);
+                }
+	}
+
+	//Convert a PolicyMap to an intPolicyMap
+	private void policyMapToInt(HashMap<String, Policy> PolicyMap, ArrayList<Integer> finalPolicy)
+	{	
+		//For each package, we first add the packagename, followed by the policy
+		for ( String packageName : PolicyMap.keySet())
+		{
+			Integer uid = getUid(packageName);
+			if(uid == null)
+			{
+				//Since we don't add its policy, remove it from the count of policies too
+				//Thus, decrement the policycount at index 1 by 1
+				finalPolicy.set(1,(finalPolicy.get(1)-1)); 
+				continue;
+			}
+			//Add the uid, and then the corresponding policy
+			finalPolicy.add(uid);
+			translateToInt(PolicyMap.get(packageName), finalPolicy);
+		} 
+	}
+		
+	//Convert an arraylist  intPolicyMap back to a PolicyMap
+	private HashMap<String, Policy> policyIntToMap(ArrayList<Integer> intPolicyMap)
+	{	
+		HashMap<String, Policy> PolicyMap = new HashMap<String, Policy>();
+		
+		Iterator<Integer> iterator = intPolicyMap.iterator();
+		int totalOwners=0;
+		if(iterator.hasNext())
+			totalOwners = iterator.next();	
+		//Loop for owners; i.e. for every owners, decode
+                for(int i=0;i<totalOwners; i++)
+                {
+			//First get the packagename of the owner.
+			Integer uidOwner = iterator.next();
+			String ownerPackageName = getPackageName(uidOwner);
+			if(ownerPackageName == null)
+			{
+				//Skip the policy entirely, or stop here? I suggest stop here.
+				//Skipping the policy
+				//Get the export list size
+				int esize = iterator.next();
+				//skip the export list
+				while(esize!=0)
+				{
+					iterator.next();
+					esize--;
+				}
+
+				//Get the required list size
+                                int rsize = iterator.next();
+				//skip the required list
+                                while(rsize!=0)
+                                {
+                                        iterator.next();
+                                        rsize--;
+                                }
+				
+				//Skipping the filter is a bit tricky
+				//Getting the total filter count
+				int fsize = iterator.next();
+				
+				//For each filter to be skipped
+				for(int j=0;j<fsize; j++)
+				{
+					//Skipping the action name
+					//First get the action string length, and skip the action string
+					int acsize =  iterator.next();
+					while(acsize!=0);
+					{
+						iterator.next();
+						acsize--;
+					}
+				
+					//Getting the principal list size
+					int psize = iterator.next();
+					while(psize!=0)
+					{	
+						iterator.next();
+						psize--;
+					}	
+				}
+				
+				continue;//Move to the next policy to be decoded
+			}//Skipping Policy done
+
+			//Traversing the policy, and then adding it to the policyMap
+                        //Get the export list size
+			Policy policy = new Policy();
+        	        //First, the export list
+	        	int esize = iterator.next();
+			AquiferList exportlist = new AquiferList();
+			//Clear it, since we also include the empty tag as -1 while encoding.
+			exportlist.getList().clear();
+			while(iterator.hasNext() && esize!=0)
+	                {
+				esize--;
+                        	Integer uid = iterator.next();
+                        	if(uid== -1){
+                                	exportlist.add("EMPTY");
+                                	continue;
+                        	}
+				else if(uid == -2)//a package that was not found while storing this policy initially
+                                        continue;
+                        	String packageName = getPackageName(uid);
+                        	if(packageName == null)
+                        	        continue;
+                	        else exportlist.add(packageName);
+        	        }
+			//Add the exportlist to the policy.
+			policy.setExportList(exportlist);
+
+			//The requiredlist
+                        int rsize = iterator.next();
+			AquiferList requiredlist = new AquiferList();
+			//Clear it, since we also include the empty tag as -1 while encoding.
+			requiredlist.getList().clear();
+			while(iterator.hasNext() && rsize!=0)
+	                {
+				rsize--;
+                        	Integer uid = iterator.next();
+                        	if(uid== -1){
+                                	requiredlist.add("EMPTY");
+                                	continue;
+                        	}
+				else if(uid == -2)//a package that was not found while storing this policy initially
+					continue;
+                        	String packageName = getPackageName(uid);
+                        	if(packageName == null)
+                        	        continue;
+                	        else requiredlist.add(packageName);
+        	        }
+			//Add the requiredlist to the policy.
+			policy.setRequiredList(requiredlist);
+
+			//The Filter
+			Filter filter = new Filter();
+			int filtersize = iterator.next();
+			while(filtersize!=0)
+			{
+				String action = "";
+				int aclength = iterator.next();
+				while(aclength!=0)
+				{
+					int nextASCII=iterator.next();
+					action+=(char)(nextASCII);
+					aclength--;
+				}
+				AquiferList principalList = new AquiferList();
+				principalList.getList().clear();
+				int plength = iterator.next();
+				while(plength!=0)
+				{
+					Integer uid = iterator.next();
+					
+					if(uid== -1){
+                                        	principalList.add("EMPTY");
+                                        	continue;
+                                	}
+					else if(uid == -2)//a package that was not found while storing this policy initially
+                                        	continue;
+					String packageName = getPackageName(uid);
+                                	if(packageName == null)
+                                        	continue;
+                                	else principalList.add(packageName);
+						plength--;
+				}
+				
+				filter.setPrincipals(action, principalList);
+				filtersize--;
+			}
+			policy.setFilter(filter);
+			//Add the policy to the PolicyMap
+			PolicyMap.put(ownerPackageName, policy);
+                }
+		return PolicyMap;
+	}
+
+	
+	private int[] getIntFromPolicyMap(HashMap<String, Policy> PolicyMap)
+	{	
+		ArrayList<Integer> finalPolicy = new ArrayList<Integer>();
+
+		//Clear the Integer list, just as a precaution
+		finalPolicy.clear();
+
+		//Set the policy to valid in the Integer list
+		finalPolicy.add(POLICY_VALID);
+
+		//TODO:
+		//Keep a spot empty for the policy total length; initially enter 0
+		finalPolicy.add(0);
+
+		//Add the total number of policies in the map to the Integer list.
+		finalPolicy.add(PolicyMap.size());
+
+		//Serialize the policymap to the Integer list
+		policyMapToInt(PolicyMap, finalPolicy);
+
+		//Create an int[] and copy the Integer list into it. 
+		//We cannot directly convert the list into an array as we need an array of fixed size.
+		int finalPolicyInt[]= new int[POLICY_SIZE];
+		//System.out.println("SECURITY_LABEL SIZE = "+finalPolicy.size());
+		Iterator<Integer> iterator = finalPolicy.iterator();
+		int i=0;
+                while(iterator.hasNext())
+                {
+                        finalPolicyInt[i] = iterator.next();
+			i++;
+                }
+		
+		//TODO: Add the policy size, i, which includes the first 2 bits, to finalPolicyInt[1], i.e. the second position
+		finalPolicyInt[1]=finalPolicy.size();
+		return finalPolicyInt;
+	}
+	
+	//Get a PolicyMap from int[]
+	private HashMap<String, Policy> getPolicyMapFromInt(int[] source)
+	{
+		if(source[0]==POLICY_INVALID)
+		{
+			//In case of a write operation, this will be a case for the first write to the file
+			//System.out.println("No policymap for file in getPolicyMapFromInt");
+			return new HashMap<String, Policy>();
+		}	
+		HashMap<String, Policy> PolicyMap=new HashMap<String, Policy>(); 
+		try{
+			ArrayList<Integer> listPolicyMap = new ArrayList<Integer>();
+                	//Clear the Integer list, just as a precaution
+                	listPolicyMap.clear();
+			//TODO: Instead, get the length from the second bit of the source, i.e. source[1]
+			//int len = source.length;
+			int len = source[1];
+			
+			//Copy the int[] into the ArrayList; strip off the first integer as it is just a valid-invalid flag.
+			//strip off the total policy length too.
+                	for(int i=2;i<len;i++)
+                	{
+                        	listPolicyMap.add(source[i]);
+                        }
+                        PolicyMap =policyIntToMap(listPolicyMap);
+		}			
+                catch(Exception e)
+                {
+                        System.out.println("Exception at getPolicyMapFromInt wrapper:"+e);
+                }
+		return PolicyMap;
+	}
+
+	//Internal function for handling file read
+	private void readFileInternal(int pid, int[] policy)
+	{
+		try{
+
+                //Printing the integer file policy input
+		/*
+		System.out.println("Printing the source int array policy:");
+                String array="";
+                for(int i=0;i<policy.length; i++){
+                        array+=policy[i]+",";
+                }
+                System.out.println(array);
+		*/
+		//
+
+		HashMap<String, Policy> FilePolicyMap = getPolicyMapFromInt(policy);
+		//Printing the initially acquired FilePolicyMap
+		/*
+		System.out.println("Printing the initially converted FilePolicyMap:readFileInternal");
+                for(String packageName: FilePolicyMap.keySet())
+                        FilePolicyMap.get(packageName).displayPolicy();
+		*/
+		//end of printing the policy		
+
+		String processName="";
+		processName = getProcessName(pid);
+                if(processName.equals(""))
+                {
+               		//System.out.println("File Access by non-visual Component:"+pid);
+                        return;
+                }
+
+		String index=processName+":"+pid;
+                String key=null;
+		WLabel label=null;
+                //Getting the workflowKey
+                key = WorkflowKey.get(index);
+                if(key==null)
+                {
+                        //System.out.println("Key not found: Read access by system ui component, or by non-ui component:"+index);
+                        return;
+                }
+                //Getting the workflow label from the key
+                label=WorkflowMap.get(key);
+                if(label==null)
+                {
+                        //System.out.println("ERROR!!No workflow for key:"+key+" at AquiferService:fileAccess");
+                        return;
+                }
+		
+		HashMap<String, Policy> wFlowPolicyMap = null;
+                //getting the PolicyMap for the workflow
+                wFlowPolicyMap = label.PolicyMap;
+	
+		if(FilePolicyMap.isEmpty())
+                {
+			//System.out.println("Not Possible, if we avoid propagation when the workflow map is empty");
+                        return;
+                }
+		if(wFlowPolicyMap.isEmpty())
+		{
+			//Adwait: Temp changes
+			//label.PolicyMap.putAll(FilePolicyMap);	
+			label.PolicyMap=FilePolicyMap;	
+		}
+		else if(FilePolicyMap==wFlowPolicyMap)
+		{
+			//System.out.println("Identical Workflow and File Labels");
+			return;
+		}
+		else
+		{
+			//System.out.println("Intersecting PolicyMaps for "+index+" accessing file "+file_id);
+                	//getting the intersection
+			
+			//Adwait: Temp changes
+			/*
+                	HashMap<String,Policy> newMap = new HashMap<String,Policy>();
+                	//copying wFlowPolicyMap to newMap
+                   	for ( String packageName : wFlowPolicyMap.keySet())
+                        {
+                                newMap.put(packageName, wFlowPolicyMap.get(packageName));
+                        }
+
+                        //For common actions, take the intersection of the Principals
+                        for ( String packageName : FilePolicyMap.keySet())
+                        {
+
+                                if(newMap.containsKey(packageName))
+                                        newMap.put(packageName, Policy.policyJoin(wFlowPolicyMap.get(packageName), FilePolicyMap.get(packageName)));
+                                else
+                                        newMap.put(packageName, FilePolicyMap.get(packageName));
+                        }
+                        wFlowPolicyMap = newMap;
+			label.PolicyMap.putAll(wFlowPolicyMap);
+			*/
+			//
+			//For common owners, take the effective of the owner policies
+                        for ( String packageName : FilePolicyMap.keySet())
+                        {
+
+                                if(wFlowPolicyMap.containsKey(packageName))
+                                        wFlowPolicyMap.put(packageName, Policy.policyJoin(wFlowPolicyMap.get(packageName), FilePolicyMap.get(packageName)));
+                                else
+                                        wFlowPolicyMap.put(packageName, FilePolicyMap.get(packageName));
+                        }
+			label.PolicyMap=wFlowPolicyMap;
+			//
+		}
+                //Check the internet policy of the affected workflow
+                checkInternet(label);
+
+		//Printing Final Policy
+		/*
+		System.out.println("Printing the policyMap returned:readFileInternal");
+                for(String packageName: wFlowPolicyMap.keySet())
+                        wFlowPolicyMap.get(packageName).displayPolicy();
+		*/		
+		//
+		}
+		catch(Exception e)
+		{	
+			System.out.println("Exception at readFileInternal"+e);
+		}
+	}
+
+	private int[] writeFileInternal(int pid, int[] policy)
+	{
+		
+		//System.out.println("Inside writeFileInternal");
+		int returnPolicy[] = new int[POLICY_SIZE];
+		try{
+		HashMap<String, Policy> FilePolicyMap = getPolicyMapFromInt(policy);
+		String processName="";
+                processName = getProcessName(pid);
+		if(processName.equals(""))
+                {
+                        //System.out.println("File Access by non-visual Component:"+pid);
+                        returnPolicy[0]=POLICY_INVALID;
+                        return returnPolicy;
+                }
+
+		String index=processName+":"+pid;
+                String key=null;
+		WLabel label=null;
+                //Getting the workflowKey
+                key = WorkflowKey.get(index);
+                if(key==null)
+                {
+                        //System.out.println("Key not found: Write access by system ui component, or by non-ui component:"+index);
+                        returnPolicy[0]=POLICY_INVALID;
+                        return returnPolicy;
+                }
+                //Getting the workflow label from the key
+                label=WorkflowMap.get(key);
+                if(label==null)
+                {
+                        System.out.println("ERROR!!No workflow for key:"+key+" at AquiferService:fileAccess");
+                        returnPolicy[0]=POLICY_INVALID;
+                        return returnPolicy;
+                }
+
+                HashMap<String, Policy> wFlowPolicyMap = null;
+                //getting the PolicyMap for the workflow
+                wFlowPolicyMap = label.PolicyMap;
+		if(wFlowPolicyMap.isEmpty())
+                {	
+			//System.out.println("WorkflowMap for "+pid+" empty Inside writeFileInternal");
+			//return the policy on the file itself
+			//System.out.println("returning as it is");
+			returnPolicy[0]=POLICY_INVALID;
+                     	return returnPolicy;
+                }
+
+		if(FilePolicyMap.isEmpty())
+                {
+			//System.out.println("FilePolicy empty");	
+			//Adwait: Temp changes
+                	//FilePolicyMap.putAll(label.PolicyMap);  
+			FilePolicyMap=wFlowPolicyMap;
+                }
+		else if(FilePolicyMap==wFlowPolicyMap)
+                {
+                        System.out.println("Identical Workflow and File Labels");
+                        returnPolicy[0]=POLICY_INVALID;
+			return returnPolicy;
+                }
+		else
+		{	
+			//TODO: First check if they are equal.
+			//Joining the PolicyMaps
+			//Adwait: Temp changes
+			/*
+			HashMap<String,Policy> newMap = new HashMap<String,Policy>();
+                        //copying wFlowPolicyMap to newMap
+                        for ( String packageName : wFlowPolicyMap.keySet())
+                        {
+                               	newMap.put(packageName, wFlowPolicyMap.get(packageName));
+                       	}
+                       	//For common actions, take the intersection of the Principals
+                       	for ( String packageName : FilePolicyMap.keySet())
+                       	{	
+                               	if(newMap.containsKey(packageName))
+                                       	newMap.put(packageName, Policy.policyJoin(wFlowPolicyMap.get(packageName), FilePolicyMap.get(packageName)));
+                               	else   
+                               	        newMap.put(packageName, FilePolicyMap.get(packageName));
+                        }	
+
+			FilePolicyMap = newMap;
+			*/
+			//
+			//For common owners, take the effective policy
+			for ( String packageName : wFlowPolicyMap.keySet())
+                        {       
+                                if(FilePolicyMap.containsKey(packageName))
+                                        FilePolicyMap.put(packageName, Policy.policyJoin(wFlowPolicyMap.get(packageName), FilePolicyMap.get(packageName)));
+                                else   
+                                        FilePolicyMap.put(packageName, FilePolicyMap.get(packageName));
+                        }
+			//
+		}
+
+		returnPolicy = getIntFromPolicyMap(FilePolicyMap);
+		
+		//Printing the policymap returned
+		/*
+		System.out.println("WRITE:Printing the policyMap returned:");
+		for(String packageName: FilePolicyMap.keySet())
+			FilePolicyMap.get(packageName).displayPolicy();
+		*/
+		//
+		
+		//Printing the array Policy
+		/*
+		System.out.println("Printing the int array policy:");
+		String array="";
+		for(int i=0;i<returnPolicy.length; i++){
+			array+=returnPolicy[i]+",";
+		}
+		System.out.println(array);
+		System.out.println("WRITE PRINT END");
+		*/
+		//
+		
+		//Comparing the input with the returnpolicy. If the same, then we do not write the return policy
+		//
+		/*
+		int i2;
+		int polLen = returnPolicy[2];
+		for(i2=0;i2<polLen; i2++){
+                        if(returnPolicy[i2]!=policy[i2])
+			{
+				break;
+			}
+                }
+		//if the same
+		if(i2==polLen)
+			returnPolicy[0]=POLICY_INVALID;
+		*/
+		//
+
+		}
+		catch(Exception e)
+		{	
+			System.out.println("Exception at writeFileInternal"+e);
+		}
+		return returnPolicy;
+
+	}	
+
+	
+/*****************************************************************************************************************************/
+//Internet Access Privilege Management
+
+	private void checkInternet(WLabel label)
+	{	
+		//internet=0 is allow, i.e. by default a variable is defined
+		//Get the effective policy
+		Policy effective = label.effectivePolicy();
+		//System.out.println("Effective Policy at checkInternet()");
+		//effective.displayPolicy();
+		//Then get the RequiredList from the enforcement field of the policy
+		AquiferList RequiredList= effective.getRequiredList();
+		
+		//First check if the RequiredList is a subset of packages that are currently a part of the workflow
+		// i.e. the list of packages from the ParticipantList
+		boolean required=requiredCheck(label, RequiredList);
+		//System.out.println("The required check returns "+required);
+		if(!required)
+		{
+			//set the internet of all the processes to 0 and return
+			ArrayList<Participant> ParticipantList = label.ParticipantList;
+	                if(ParticipantList == null)
+	                {
+       		                 System.out.println("Error!:Null participant list at AquiferService:checkInternet(WLabel)");
+       		                 return;
+                	}
+			
+                	//Setting internet policy to deny, i.e. 1 for all participants
+                	Iterator<Participant> iterator = ParticipantList.iterator();
+                	while(iterator.hasNext())
+                	{
+                        	Participant part = iterator.next();
+                        	int part_pid = part.getPid();
+				//System.out.println("Revoking Internet privilege for pid "+part_pid);
+				setInternet(part_pid, 1);
+                	}
+			return;
+		}
+
+		//Now setting internet for each participant if it is in the allowedlist
+		AquiferList ExportList= effective.getExportList();
+		ArrayList<Participant> ParticipantList = label.ParticipantList;
+		if(ParticipantList == null)
+                {
+                        System.out.println("Error!:Null participant list at AquiferService:checkInternet(WLabel)");
+                	return;
+                }
+		allowedCheck(ExportList, ParticipantList);
+	}
+	
+	//Checking if the ExportList is satisfied in the current workflow
+	//and setting internet for each participant if it is in the allowedlist
+	private void allowedCheck(AquiferList ExportList, ArrayList<Participant> ParticipantList)
+	{
+		//First checking for conditions where the list is Full or Empty
+		//if list is full
+		if(ExportList.isEmpty())
+		{	
+			//System.out.println("Everybody is allowed");
+			//set internet for all participants and return
+			Iterator<Participant> iterator = ParticipantList.iterator();
+			while(iterator.hasNext())
+                	{	
+                        	Participant part = iterator.next();
+				int part_pid = part.getPid();
+				//System.out.println("Assigning Internet privilege for pid "+part_pid);
+				setInternet(part_pid, 0);
+			}
+			return;
+		}	
+		//if list is empty
+		else if(ExportList.isEMPTY())
+		{	
+			//System.out.println("Nobody is allowed!");
+			//set internet deny for all participants and return
+			Iterator<Participant> iterator = ParticipantList.iterator();
+                        while(iterator.hasNext())
+                        {
+                                Participant part = iterator.next();
+                                int part_pid = part.getPid();
+				//System.out.println("Revoking Internet privilege for pid "+part_pid);
+                                setInternet(part_pid, 1);
+                        }
+                        return;
+		}
+		else
+		{
+			Iterator<Participant> iterator = ParticipantList.iterator();
+                	while(iterator.hasNext())
+               		{
+                        	Participant part = iterator.next();
+				String packageName = part.getPackageName();
+                        	int part_pid = part.getPid();
+				if(ExportList.contains(packageName))
+				{	//allow
+                        	
+					setInternet(part_pid, 0);
+					//System.out.println("Granting Internet privilege for pid "+part_pid);
+				}
+				else	
+				{	//deny
+					//System.out.println("Revoking Internet privilege for pid "+part_pid);
+                        		setInternet(part_pid, 1);
+				}
+			}	
+                }
+	}
+	//Checking if the requiredList is satisfied in the current workflow
+	private static boolean requiredCheck(WLabel label, AquiferList RequiredList)
+	{
+		//First checking for conditions where the list is Full or Empty
+		//If the list is full
+                if(RequiredList.isEmpty())
+                {
+                        //All apps on a device required? Break and false
+			//System.out.println("All apps required in requiredCheck!");
+                        return false;
+                }
+                //If the list is empty
+                if(RequiredList.isEMPTY())
+                {
+			//System.out.println("No apps required in requiredCheck");
+                        return true;
+                }
+		
+		// Take the HistoryList in the ParticipantList
+                ArrayList<Participant> ParticipantList = label.HistoryList;
+                if(ParticipantList == null)
+                {
+                        //System.out.println("Error!:Null participant list at AquiferService:requiredCheck(WLabel)");
+                        return false;
+                }
+		
+		//Getting all the packageNames in a separate list
+                AquiferList packageList = new AquiferList();
+                Iterator<Participant> iterator = ParticipantList.iterator();
+                while(iterator.hasNext())
+                {
+                        Participant part = iterator.next();
+                        packageList.add(part.getPackageName());
+                }
+
+		//Checking if the RequiredList is a subset of the PackageList
+                ListIterator<String> li = RequiredList.getList().listIterator();
+                boolean required=true;
+                while(li.hasNext())
+                {	
+                        String packageName = li.next();
+                        if(!packageList.contains(packageName))
+                        {	//System.out.println("Required Package "+packageName+"not present in the workflow: requiredCheck(Wlabel)");
+                                required=false;
+                                break;
+                        }
+                }
+		return required;
+	}		
+
+	
+
+	//Setting the network policy in the kernel for a pid
+	private static void setInternet(int pid, int inetflag)
+        {
+		//System.out.println("Setting internet to "+inetflag+" for pid="+pid);
+                int val=addInetFlag(pid, inetflag);               
+                //System.out.println("returned value="+val);
+        }	
+	
+	//Returning a data "Owner's" policy to a component belonging to that owner.
+/**************************************************************************************************************/
+	//General use functions:
+		
+	private Integer getUid(String packageName)
+	{	
+		Integer uid = PackageMap.get(packageName);
+		try{
+		if(uid==null)
+		{
+			//Get the PackageMap from the file
+                        File file = new File("/data/system/aquifermap");
+                        FileInputStream f = new FileInputStream(file);
+                        ObjectInputStream s = new ObjectInputStream(f);
+                        PackageMap = (HashMap<String,Integer>)s.readObject();
+                        if(PackageMap==null)
+                        {
+                                System.out.println("Error Reading aquifermap for PackageMap:");
+                                return null;
+                        }
+                        f.close();
+                        s.close();
+			uid = PackageMap.get(packageName);
+			if(uid == null)
+			{
+				System.out.println("ERROR. No uid for packageName: "+packageName);
+			}
+		}
+		}
+		catch(Exception e)
+                {
+                        System.out.println("File Creation Error:AquiferService:"+e);
+
+                }
+		return uid;
+	}
+	private String getPackageName(Integer uid)
+	{	
+		String packageName=null;
+		//System.out.println("Looking for packagename for uid: "+uid);
+		try{
+		for ( HashMap.Entry<String, Integer> entry : PackageMap.entrySet())
+                {
+			//System.out.println("Inside HashMap");
+			int uidi = uid;
+                       	if(entry.getValue()==uidi){
+				//System.out.println("Got packagename for "+uid+ " from map");
+				packageName=entry.getKey();	
+				break;
+			}
+			else
+			{
+				//System.out.println("Entry.getValue failed="+entry.getValue()+" entry key ="+entry.getKey());
+			}
+                }	
+		if(packageName==null)
+		{
+			//System.out.println("Not found in Map");
+			//Get the PackageMap from the file
+                        File file = new File("/data/system/aquifermap");
+                        FileInputStream f = new FileInputStream(file);
+                        ObjectInputStream s = new ObjectInputStream(f);
+                        PackageMap = (HashMap<String,Integer>)s.readObject();
+                        if(PackageMap==null)
+                        {
+                                System.out.println("Error Reading aquifermap for PackageMap:");
+                                return null;
+                        }
+                        f.close();
+                        s.close();
+			
+			for ( HashMap.Entry<String, Integer> entry : PackageMap.entrySet())
+                	{
+                        	if(entry.getValue()==uid)
+                                	packageName=entry.getKey();
+               		}
+			if(packageName ==null)
+			{
+				//System.out.println("ERROR. No packageName for uid: "+uid);
+			}
+		}
+		}
+		catch(Exception e)
+                {
+                        System.out.println("File Creation Error:AquiferService:"+e);
+
+                }
+		return packageName;
+	}
+	public int storePackageName(String packageName, int uid)
+	{
+		//TODO: validate caller
+		try{
+			//Get the PackageMap from the file
+                        File file = new File("/data/system/aquifermap");
+                        FileInputStream f = new FileInputStream(file);
+                        ObjectInputStream s = new ObjectInputStream(f);
+                        PackageMap = (HashMap<String,Integer>)s.readObject();
+                        if(PackageMap==null)
+                        {
+                                System.out.println("Error Reading aquifermap for PackageMap:");
+                                return -1;
+                        }
+			f.close();
+			s.close();
+			
+			//Then add this to the PackageMap
+			PackageMap.put(packageName, new Integer(uid));
+			//Store it back to the file
+                        FileOutputStream fo = new FileOutputStream(file);
+                        ObjectOutputStream so = new ObjectOutputStream(fo);
+                        so.writeObject(PackageMap);
+			fo.close();
+                        so.close();
+			
+			//System.out.println("Package "+packageName+":"+uid+" successfully added.");
+			//Print the PackageMap; for DEBUG. TODO: Remove Later
+			int i=0; 
+			//System.out.println("Printing first 5 elements of PackageMap");
+			//for ( String packageName2 : PackageMap.keySet())
+                        //{
+			//	System.out.println(packageName2+":"+PackageMap.get(packageName2));
+                        //}
+                }
+                catch(Exception e)
+                {
+                        System.out.println("Exception at AquiferService:storePackageName while reading from file:"+e);
+                        return-1;
+                }
+		return 0;
+		//Store it back to the file
+	}	
+	public int removePackageName(String packageName)
+	{
+		//TODO: validate caller
+		try{
+			//Get the PackageMap from the file
+                        File file = new File("/data/system/aquifermap");
+                        FileInputStream f = new FileInputStream(file);
+                        ObjectInputStream s = new ObjectInputStream(f);
+                        PackageMap = (HashMap<String,Integer>)s.readObject();
+                        if(PackageMap==null)
+                        {
+                                System.out.println("Error Reading aquifermap for PackageMap:");
+                                return -1;
+                        }
+			f.close();
+			s.close();
+			
+			//Then add this to the PackageMap
+			PackageMap.remove(packageName);
+			//Store it back to the file
+                        FileOutputStream fo = new FileOutputStream(file);
+                        ObjectOutputStream so = new ObjectOutputStream(fo);
+                        so.writeObject(PackageMap);
+			fo.close();
+                        so.close();
+			
+			//System.out.println("Package "+packageName+"successfully removed.");
+			//Print the PackageMap; for DEBUG. TODO: Remove Later
+			int i=0; 
+			//System.out.println("Printing first 5 elements of PackageMap");
+			//for ( String packageName2 : PackageMap.keySet())
+                        //{
+			//	System.out.println(packageName2+":"+PackageMap.get(packageName2));
+                        //}
+                }
+                catch(Exception e)
+                {
+                        System.out.println("Exception at AquiferService:removePackageName while reading from file:"+e);
+                        return-1;
+                }
+		return 0;
+		//Store it back to the file
+	}
+        
+	//Getting the Participant's packageName
+	private static String getPackageName(String index, ArrayList<Participant> ParticipantList)
+	{
+		if(ParticipantList == null)
+		{
+			System.out.println("Null participant list at AquiferService:getPackageName(index, participantlist)");
+			return null;
+		}
+		Iterator<Participant> iterator = ParticipantList.iterator();
+		while(iterator.hasNext())
+		{
+			Participant part = iterator.next();
+			String tocompare=part.getProcessName()+":"+part.getPid();
+			if(tocompare.equals(index))
+				return part.getPackageName();
+		}
+		return null;
+	}
+
+	//Getting the processName given the pid
+	public String getProcessName(int pid)
+	{
+		ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
+		try{
+			for(RunningAppProcessInfo pInfo : am.getRunningAppProcesses())
+			{
+				if(pInfo.pid == pid)
+					return pInfo.processName;
+			}
+		}
+		catch(Exception e)
+		{}
+		return "";
+	}
+
+	//Getting the processName given the pid
+	public String getComponentName(String processName)
+	{
+		ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
+		for(RunningAppProcessInfo pInfo : am.getRunningAppProcesses())
+		{
+			try{
+				if(pInfo.processName.equals(processName))
+					return pInfo.importanceReasonComponent.getClassName();
+			}
+			catch(Exception e)
+			{}
+		}
+		return "";
+	}
+
+	private boolean isService(int pid)
+	{
+		
+		ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
+                for(RunningServiceInfo pInfo : am.getRunningServices(100))
+                {
+                        try{   
+                                if(pInfo.pid == pid)
+                                        return true;
+                        }  
+                        catch(Exception e)
+                        {
+				System.out.println("Exception at AquiferService:isService(int pid):"+e);
+			}
+                }
+                return false;
+	}
+	//Get pid for processName
+	private int getPid(String processName)
+        {
+                ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
+                for(RunningAppProcessInfo pInfo : am.getRunningAppProcesses())
+                {
+                        if(pInfo.processName.equals(processName))
+                                return pInfo.pid;
+                }
+                return -1;
+        }
+
+	//Get processName for Activity componentName
+	private String getProcessName2(ComponentName componentName)
+	{	
+		PackageManager pm = mContext.getPackageManager();
+                String ret=null;
+                try{
+			ActivityInfo ai;
+                        ai = pm.getActivityInfo(componentName,0);
+			ret = ai.processName;
+                }
+                catch(Exception e)
+                {       Log.w(TAG, "Component Not found:getProcessName2(Component)");                        
+                }
+                return ret;
+        }
+
+	//Get processName for service ComponentName
+	private String getProcessName3(ComponentName componentName)
+	{	
+		PackageManager pm = mContext.getPackageManager();
+                String ret=null;
+                try{
+			ServiceInfo si;
+                        si = pm.getServiceInfo(componentName,0);
+			ret = si.processName;
+                }
+                catch(Exception e)
+                {       Log.w(TAG, "Component Not found:getProcessName3(Component)");                        
+                }
+                return ret;
+        }
+	
+	//Getting the packageName given the uid
+/*        private String[] getPackageName(int uid)
+        {
+                PackageManager pm = mContext.getPackageManager();
+                String[] ret=null;
+                try{   
+                        ret = pm.getPackagesForUid(uid);
+                }
+                catch(Exception e)
+                {       Log.w(TAG, "Package Not found");
+			ret=null;                        
+                }
+                return ret;
+        }
+*/
+	//Checking if the given processName is alive
+        private boolean isAlive(String processName)
+        {
+                ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
+                for(RunningAppProcessInfo pInfo : am.getRunningAppProcesses())
+                {
+                        if(pInfo.processName.equals(processName))
+                                return true;
+                }
+                return false;
+        }
+
+	//Check caller permissions
+	private static boolean validateCaller()
+	{
+		int pid = Binder.getCallingPid();
+		String processName="";
+		IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+		try{
+			processName = aquifer.getProcessName(pid);
+		}
+		catch(Exception e)
+		{}
+		if(!processName.equals("system") && pid!=0)
+		{
+			System.out.println("AquiferService::Dropping call from "+processName);
+			return false;
+		}
+		else 
+			return true;
+	}
+
+	void printMsg(int pid)
+	{
+		System.out.println("Printing pid:"+pid);
+	}
+	
+	public void workflowJoin(String a,int b,String c,int d, String e,int f,int g, String h)
+	{}
+
+	void addActionToList(String action, ArrayList<Integer> finalPolicy)
+	{
+		finalPolicy.add(action.length());
+		for(int i=0;i<action.length();i++)
+			 finalPolicy.add((int)(action.charAt(i)));
+	}
+	String getActionFromList(ArrayList<Integer> policy)
+	{
+		Iterator<Integer> iterator = policy.iterator();
+		int length = iterator.next();
+		String action = "";
+		while(iterator.hasNext())
+		{
+			int nextASCII = iterator.next();
+			action+=(char)(nextASCII);
+		}
+		return action;
+	}
+/************************************************************************************************************/
+
+
+/**********************************************************************************************************************/
+	/*
+	 *NATIVE METHODS
+	 *
+	 */
+	//For checking AquiferPolicy in the kernel. Not important in the current implementation.
+	private static native int checkAquiferNative(int pid1, int pid2, int flow);	
+  
+	//Adds the internet flag to the task_struct of a process
+	private static native int addInetFlag(int pid, int flag);	
+	
+	//temp method to test jni
+	private native int democall(int n);
+	
+/**********************************************************************************************************************/
+	//Supporting Sub-classes
+	//The Label Class
+	private class WLabel
+	{
+		private ArrayList<Participant> ParticipantList;
+		private ArrayList<Participant> HistoryList;
+		private HashMap<String, Policy> PolicyMap;
+		//Constructor	
+		WLabel()
+		{
+			ParticipantList = new ArrayList<Participant>(); 
+			HistoryList = new ArrayList<Participant>(); 
+			PolicyMap = new HashMap<String, Policy>();
+		}
+		
+		//Getters & Setters not necessary since we can directly access
+		//members of WLabel from the FLoidService. Still, do these later.
+		
+		//Getting the Effective Policy
+		private Policy effectivePolicy()
+		{
+			Policy policy = new Policy();
+			for ( String packageName : PolicyMap.keySet())
+			{
+				policy = Policy.policyJoin(policy, PolicyMap.get(packageName));
+			}
+			return policy;
+		}
+		private void displayLabel()
+		{	//System.out.println("Policies:");
+			for ( String packageName : PolicyMap.keySet())
+                        {
+				 //System.out.println("Policy For "+packageName);
+                                 PolicyMap.get(packageName).displayPolicy();
+                        }
+		}
+	}
+  }
+
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index b3d7220..a9bcaff 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -37,7 +37,12 @@ import android.util.Printer;
 
 import android.content.Intent;
 import android.content.IntentFilter;
-
+import android.content.pm.ResolveInfo;
+import java.util.ListIterator;
+import android.os.IAquiferService;
+import android.os.AquiferList;
+import android.os.Binder;
+import android.os.ServiceManager;
 /**
  * {@hide}
  */
@@ -306,12 +311,97 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
         }
         sortResults(finalList);
 
-        if (debug) {
+	//Adwait's patch begins
+	if(this.toString().contains("ActivityIntentResolver"))
+	{
+		//Supply the calling process's procname, pid and packagename and the action with the intent
+		//then in th aquiferservice get the label, then the effective policy, and check if the action has any Principals.
+		//return the filter:PrincipalList from the AquiferService. The finalList contains only those apps that are also in 
+		//the PrincipalList.
+		//Getting the sender's processname, pid, packagename
+//		String sprocessName=intent.getStringExtra("processName");
+//		int spid=intent.getIntExtra("pid",0);
+		String sprocessName=intent.getProcessName();
+		int spid=intent.getPid();
+		//Getting the Intent Action
+		String action = intent.getAction();
+		//System.out.println("Filtering results for "+sprocessName+":"+spid+":"+action);
+		
+		IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        	try{   
+			if(finalList==null){
+				//System.out.println("null finalList");
+			}
+			else
+			{	/*
+				ListIterator li2 = finalList.listIterator();
+				System.out.println("Initial List Contents:");
+				if(li2!=null)
+				{
+					while(li2.hasNext())
+					{
+						ResolveInfo rinfo =(ResolveInfo) li2.next();
+						if(rinfo!=null && rinfo.activityInfo!=null && rinfo.activityInfo.name!=null)
+							System.out.println(rinfo.activityInfo.name);
+						else	
+							System.out.println("Something is null, probably rinfo.activityInfo:"+rinfo.activityInfo);
+					}	
+				}*/
+				if(sprocessName!=null && !sprocessName.startsWith("com.android") && !sprocessName.equals("system"))	
+				{
+					AquiferList PrincipalList = aquifer.getPrincipalList(sprocessName, spid, action);
+					if(PrincipalList!=null)
+					{	
+						if(PrincipalList.isEmpty())
+						{
+							//System.out.println("null principallist returned for action "+action);		
+							return finalList;
+						}
+						//System.out.println("Non null principallist returned for action "+action);
+						ListIterator li = finalList.listIterator();
+						int i=0;
+						while(li.hasNext())
+                				{
+                        				//Filtering the final list displayed to the user
+                        				ResolveInfo rinfo =(ResolveInfo) li.next();
+	                        			String rpackageName = rinfo.activityInfo.packageName;
+							if(PrincipalList.contains(rpackageName))
+							{
+								//System.out.println("The component "+rinfo.activityInfo.name+" passes all the checks");
+							}
+							else
+							{
+        	                                        	//start from the beginning
+								//System.out.println("Removing component "+rinfo.activityInfo.name);
+								finalList.remove(rinfo);
+                	                	                li = finalList.listIterator();
+                        	                       		// i=0; 
+							}
+							i++;
+						}
+					}
+					else
+					{
+						//System.out.println("No principals for the current action "+action);
+					}
+				}
+			}
+        	}
+        	catch(Exception e)
+        	{	
+			System.out.println("Exception at activity intent resolver:"+e);	
+		}
+	}
+
+	//Adwait's check ends
+       
+	 if (debug) {
             Slog.v(TAG, "Final result list:");
             for (R r : finalList) {
                 Slog.v(TAG, "  " + r);
             }
         }
+	//System.out.println("Generated the final list");
         return finalList;
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ae62ad..af10091 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -62,6 +62,7 @@ import java.io.File;
 import java.util.Timer;
 import java.util.TimerTask;
 
+
 class ServerThread extends Thread {
     private static final String TAG = "SystemServer";
     private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
@@ -132,16 +133,26 @@ class ServerThread extends Thread {
         NetworkTimeUpdateService networkTimeUpdater = null;
 
         // Critical services...
-        try {
+        
+	try {
+
             Slog.i(TAG, "Entropy Service");
             ServiceManager.addService("entropy", new EntropyService());
-
+	
             Slog.i(TAG, "Power Manager");
             power = new PowerManagerService();
             ServiceManager.addService(Context.POWER_SERVICE, power);
 
             Slog.i(TAG, "Activity Manager");
             context = ActivityManagerService.main(factoryTest);
+	
+	    //Adwait : Registering the AquiferService
+            try {
+                Slog.i(TAG, "Aquifer Service");
+                ServiceManager.addService("Aquifer",new AquiferService(context));
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting AquiferService", e);
+            }		
 
             Slog.i(TAG, "Telephony Registry");
             ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
@@ -170,9 +181,9 @@ class ServerThread extends Thread {
             }
 
             ActivityManagerService.setSystemProcess();
-
+	
             mContentResolver = context.getContentResolver();
-
+		
             // The AccountManager must come before the ContentService
             try {
                 Slog.i(TAG, "Account Manager");
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index df58e83..915a13a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -15,7 +15,7 @@
  */
 
 package com.android.server.am;
-
+import android.os.IAquiferService;
 import com.android.internal.R;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessStats;
@@ -1891,6 +1891,18 @@ public final class ActivityManagerService extends ActivityManagerNative
         }
 
         startProcessLocked(app, hostingType, hostingNameStr);
+	//Adwait's hook - startProcessLocked
+        /*if(info.packageName.equals("com.demoapps.adwait"))
+        {
+                IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+                try{
+			aquifer.hi(5);
+                    	System.out.println("Aquifer Says Hi!: "+processName);
+        	}
+                catch(Exception e)
+                {}
+        }*/
+
         return (app.pid != 0) ? app : null;
     }
 
@@ -1959,13 +1971,24 @@ public final class ActivityManagerService extends ActivityManagerNative
             if ("1".equals(SystemProperties.get("debug.assert"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
             }
-
+		
+	    //Adwait's process creation hook
             // Start the process.  It will either succeed and return a result containing
             // the PID of the new process, or else throw a RuntimeException.
             Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                     app.processName, uid, uid, gids, debugFlags,
                     app.info.targetSdkVersion, null);
-
+	    /*if( app.processName!=null && !app.processName.equals("system") && !app.processName.startsWith("com.android."))
+	    {	
+		System.out.println("Setting internet for the process "+app.processName);
+	    	//Call AquiferService Here
+	   	IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+	    	try{
+	    		aquifer.setInternetPolicy(startResult.pid, uid, app.processName);
+	    	}
+	    	catch(Exception e)
+	    	{}
+	    }*/
             BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
             synchronized (bs) {
                 if (bs.isOnBattery()) {
@@ -2229,6 +2252,17 @@ public final class ActivityManagerService extends ActivityManagerNative
             int grantedMode, IBinder resultTo,
             String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
             String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+		//Adwait's code - Intent path	
+		/*
+		String processName=intent.getStringExtra("processName");
+		System.out.println("Inside act manager service");
+	        if(processName!=null && processName.contains(".AppAactivity"))
+         	{
+			if(intent.getPolicy()==null)
+				System.out.println("Null policy at ActivityManagerService");   
+			else System.out.println("Policy Exists at ActivityManagerService");
+		}*/
+		//ends
         return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 grantedUriPermissions, grantedMode, resultTo, resultWho,
                 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
@@ -4089,6 +4123,26 @@ public final class ActivityManagerService extends ActivityManagerNative
     }
 
     public final void activityDestroyed(IBinder token) {
+	//Adwait's coded for destroying an activity
+	/*
+        IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+	int pid=-50;
+	String processName="boo";
+        try{    ActivityRecord r = ActivityRecord.forToken(token);
+		if(r==null)
+			System.out.println("Null Activity Record");
+                if(r.app==null)
+			System.out.println("Null app");
+		pid = r.app.pid;
+                processName = r.processName;
+                aquifer.destroyActivity(pid,processName);
+        }
+        catch(Exception e)
+        {
+                System.out.println("Exception at ActivityManagerService:activityDestroyed:"+e);
+        }*/
+        //Adwait's code ends
+
         if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
         mMainStack.activityDestroyed(token);
     }
@@ -10480,6 +10534,44 @@ public final class ActivityManagerService extends ActivityManagerNative
 
                 ComponentName name = new ComponentName(
                         sInfo.applicationInfo.packageName, sInfo.name);
+		//Adwait's hook for attaching policy to services
+		//First getting the aggregate policy
+		/*
+		try
+		{IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+		AquiferPolicy aggPolicy=null;
+		String sprocessName = service.getStringExtra("processName");
+		String rprocessName = sInfo.processName;
+		System.out.println("Sender for the intent="+sprocessName);
+                System.out.println("Service selected = "+sInfo.name);        
+		if(rprocessName!=null && !sprocessName.contains("com.android") && !sprocessName.equals("system"))
+                {	
+			//System.out.println("Policy on the intent :");
+                        //System.out.println("IntentResolver::The processName is "+sprocessName);
+                        //Getting the aggregate policy (sending process+intent)
+                        aggPolicy = aquifer.aggregatePolicy(sprocessName,service);
+                        System.out.println("Aggregate Policy:");
+                        if(aggPolicy==null)
+                               	System.out.println("Aggregate Policy is null");
+                        else
+                                aggPolicy.displayAquiferPolicy();
+			if(aquifer.isAlive(rprocessName))
+			{	System.out.println("Process "+rprocessName+" is alive.");
+                                AquiferPolicy finalPolicy=aquifer.policyConvergence(rprocessName, aggPolicy);
+				aquifer.addComponentPolicy(rprocessName, finalPolicy);
+                                System.out.println("Policy:");
+                                finalPolicy.displayAquiferPolicy();
+			}
+			else
+			{
+				aquifer.addComponentPolicy(rprocessName, aggPolicy);
+			}
+		}}
+		catch(Exception e)
+		{
+			System.out.println("Exception at retrieveServiceLocked: adding policy to a service process:"+e);
+		}*/
+           	//ends 
                 r = mServices.get(name);
                 if (r == null) {
                     filter = new Intent.FilterComparison(service.cloneFilter());
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 6c11953..5221a69 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -70,7 +70,9 @@ import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-
+import java.util.ListIterator;
+import android.os.IAquiferService;
+import android.os.ServiceManager;
 /**
  * State and management of a single stack of activities.
  */
@@ -694,23 +696,147 @@ final class ActivityStack {
         } else if (mInitialStartTime == 0) {
             mInitialStartTime = SystemClock.uptimeMillis();
         }
-        
+       	boolean x=false;
+		
+	//Adwait's code
+	String rcomponentName = "";
+	rcomponentName = r.realActivity.getClassName();
+	String action="";
+	if(r.intent.getAction()!=null)
+		action=r.intent.getAction();
+
+        //Getting Sender Information
+	String sprocessName="";
+	int spid=0;
+	try{
+//		sprocessName=r.intent.getStringExtra("processName");
+//        	spid=r.intent.getIntExtra("pid",0);
+		sprocessName=r.intent.getProcessName();
+        	spid=r.intent.getPid();
+	}
+        catch(Exception e)
+	{
+		System.out.println("Exception at startSpecificActivityLocked while getting the processName. pid="+spid+"::"+e);
+	}	
+	int resultcode=r.requestCode;
+	//System.out.println("startSpecificActivityLocked:The caller is "+sprocessName+":"+spid);
+	boolean callItself=false;
+	if(app!=null)
+	{
+		//System.out.println("startSpecificActivityLocked:The receiver has processrecord :"+app.pid);
+		if(app.pid==spid)
+		{
+			//System.out.println(sprocessName + ":" + spid + " calls itself");
+			callItself=true;
+		}		
+	}
+	//start the ringtone activity in a new process, i.e. remove the RINGTONE_PICKER case somehow. 
+	//Then before this condition, check if the activity being currently called is already in the workflow of the receiver. If so,
+	//Then simply restart it.
+        //if (app != null && app.thread != null && (app.processName.equals("system") || app.processName.equals("com.android.launcher") || app.processName.contains("chooser") || (r.intent.getAction()!=null && r.intent.getAction().equals(Intent.ACTION_CHOOSER)) || (r.intent.getAction()!=null && r.intent.getAction().equals("android.intent.action.RINGTONE_PICKER")) || callItself)) {
+	IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
         if (app != null && app.thread != null) {
-            try {
-                app.addPackage(r.info.packageName);
-                realStartActivityLocked(r, app, andResume, checkConfig);
-                return;
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Exception when starting activity "
-                        + r.intent.getComponent().flattenToShortString(), e);
-            }
-
+	//	System.out.println("Process "+app.processName+" already exists:");
+		//Adwait's code for checking if the processname is the same process starting it
+		if(app.processName.equals("system") || app.processName.equals("com.android.launcher") || app.processName.contains("chooser") || (r.intent.getAction()!=null && r.intent.getAction().equals(Intent.ACTION_CHOOSER)) || (r.intent.getAction()!=null && r.intent.getAction().equals("android.intent.action.RINGTONE_PICKER")))
+		{}
+		else
+		{	
+			//In case sprocessName is null, i.e. the original process firing this intent is system or launcher
+			if(sprocessName==null)
+				sprocessName="";
+			//For a process holding multiple activities
+			boolean current=false;
+                        try{
+				//System.out.println("Checking if the process belongs to the same workflow");
+				//Check if the process of the activity is a part of the current workflow
+                                if(aquifer.isThisWorkflow(sprocessName, spid, app.processName, app.pid))
+					current=true;
+                        }
+                        catch(Exception e)
+                        {
+                                System.out.println("Exception while checking if process is in the current workflow:"+e);
+                        }
+			if(current)
+			{		
+				//System.out.println("Adding component to existing workflow");
+				String rpackageName = app.info.packageName;
+				int ruid = app.info.uid;
+                		try{
+                        		aquifer.addComponent(app.processName, app.pid, rpackageName, ruid, resultcode,rcomponentName);
+                		}
+                		catch(Exception e)
+                		{
+                        		System.out.println("Exception while adding component to the current workflow process "+app.processName+" :"+e);
+                		}
+			}
+			else
+			{	//current = false, i.e., 
+				//The app.processName is either a part of no workflow(HOW?) or a part of some other workflow.
+				//In either case, first try to destroy this particular participating component from its process.
+				//System.out.println("Killing and adding process to the workflow of "+sprocessName+":"+spid);
+				try{
+					aquifer.destroyEntireProcess(app.processName, app.pid);
+					//creating a new process
+					ProcessRecord rec = mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false);
+        				//Getting Receiver information
+        				String rpackageName=rec.info.packageName;
+        				String rprocessName=rec.processName;
+        				int rpid=rec.pid;
+        				int ruid=rec.info.uid;
+					//System.out.println("New process "+rprocessName+":"+rpid+" created after killing it.");
+					if(rprocessName.equals("system") || rprocessName.equals("com.android.launcher") || rprocessName.contains("chooser") || (r.intent.getAction()!=null && r.intent.getAction().equals(Intent.ACTION_CHOOSER)) || (r.intent.getAction()!=null && r.intent.getAction().equals("android.intent.action.RINGTONE_PICKER")))
+					{}
+					else
+					{
+						aquifer.addParticipant( sprocessName, spid, rprocessName, rpid, rpackageName, ruid, resultcode, rcomponentName);
+					}
+				}
+				catch(Exception e)
+				{	System.out.println("Exception: call to destroyEntireProcess and addParticipant:"+e);
+				}	
+				return;//since the app.addPackage and realStartActivityLocked  part is useless for when we create a new process.
+			}
+			//System.out.println("Resuming process for activity");
+		}
+       		try {
+              		app.addPackage(r.info.packageName);
+                	realStartActivityLocked(r, app, andResume, checkConfig);
+                	return;
+            	} 
+		catch (RemoteException e) {
+                	Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);
+        	}    	
             // If a dead object exception was thrown -- fall through to
             // restart the application.
-        }
-
-        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
+        	
+	}
+	//System.out.println("Starting a new process for the activity");
+	//Adwait's code: Adding a new participant
+	ProcessRecord rec = mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                 "activity", r.intent.getComponent(), false);
+	//Getting Receiver information
+	
+	String rpackageName=rec.info.packageName;
+        String rprocessName=rec.processName;
+        int rpid=rec.pid;
+	int ruid=rec.info.uid;
+	
+	if(rprocessName.equals("system") || rprocessName.equals("com.android.launcher") || rprocessName.contains("chooser") || (r.intent.getAction()!=null && r.intent.getAction().equals(Intent.ACTION_CHOOSER)) || (r.intent.getAction()!=null && r.intent.getAction().equals("android.intent.action.RINGTONE_PICKER")))
+        {}
+	else{
+		//the actual call to addParticipant(..)
+		//System.out.println("Process "+rprocessName+":"+rpid+":"+rpackageName+" started by "+ sprocessName+":"+spid+"with resultcode"+resultcode);
+		try
+		{	
+			aquifer.addParticipant( sprocessName, spid, rprocessName, rpid, rpackageName, ruid, resultcode, rcomponentName); 
+		}
+		catch(Exception e)
+		{	
+			System.out.println("Exception while adding participant: ActivityStack:startSpecificActivityLocked");
+		}	
+		//Adwait's code ends
+	}
     }
     
     void stopIfSleepingLocked() {
@@ -2228,7 +2354,6 @@ final class ActivityStack {
             boolean componentSpecified, ActivityRecord[] outActivity) {
 
         int err = START_SUCCESS;
-
         ProcessRecord callerApp = null;
         if (caller != null) {
             callerApp = mService.getRecordForAppLocked(caller);
@@ -2244,6 +2369,7 @@ final class ActivityStack {
         }
 
         if (err == START_SUCCESS) {
+	    
             Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid "
                     + (callerApp != null ? callerApp.pid : callingPid));
         }
@@ -2831,7 +2957,19 @@ final class ActivityStack {
 
         // Don't modify the client's object!
         intent = new Intent(intent);
-
+	/*
+	//Adwait's code
+	try{
+		String sprocessName=intent.getStringExtra("processName");
+        	int spid=intent.getIntExtra("pid",0);
+        	System.out.println("The caller at ActivityStack is "+sprocessName+":"+spid);
+	}
+	catch(Exception e)
+	{
+		System.out.println("Exception at ActivityStack:startActivityMayWait while getting extras:"+e);
+	}
+	//Adwait's code ends
+	*/
         // Collect information about the target of the Intent.
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
                 profileFile, profileFd, autoStopProfiler);
@@ -2859,6 +2997,7 @@ final class ActivityStack {
                 // This may be a heavy-weight process!  Check to see if we already
                 // have another, different heavy-weight process running.
                 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
+		    
                     if (mService.mHeavyWeightProcess != null &&
                             (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
                             !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
@@ -2921,7 +3060,8 @@ final class ActivityStack {
                     }
                 }
             }
-            
+	  //Adwait: Adding policy to the sender process  
+	    
             int res = startActivityLocked(caller, intent, resolvedType,
                     grantedUriPermissions, grantedMode, aInfo,
                     resultTo, resultWho, requestCode, callingPid, callingUid,
@@ -3543,7 +3683,6 @@ final class ActivityStack {
         if (mService.mFocusedActivity == r) {
             mService.mFocusedActivity = null;
         }
-
         r.configDestroy = false;
         r.frozenBeforeDestroy = false;
 
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6b61c47..a66a6a0 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -83,6 +83,7 @@ import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.IAquiferService;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
@@ -3674,6 +3675,21 @@ public class PackageManagerService extends IPackageManager.Stub {
             int i;
             for (i=0; i<N; i++) {
                 PackageParser.Provider p = pkg.providers.get(i);
+		
+		 //Adwait's patch for providers begins
+                //initialize a new string to hold the s.info.name or "process"
+                //if s.info.processName is null, then put this string as s.info.processName, else let it be
+                /*
+		if(pkg.applicationInfo.processName!=null && !pkg.applicationInfo.processName.startsWith("com.android."))
+                {int len = pkg.applicationInfo.packageName.length();
+                String name =p.info.name.substring(len+1);
+   		// System.out.println("::Installing provider"+pname);
+                     if(p.info.processName==null)
+                      {p.info.processName=""+pkg.applicationInfo.packageName+":"+name;}
+                }
+		*/
+                //Adwait's patch ends
+
                 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         p.info.processName, pkg.applicationInfo.uid);
                 mProvidersByComponent.put(new ComponentName(p.info.packageName,
@@ -3734,7 +3750,19 @@ public class PackageManagerService extends IPackageManager.Stub {
             r = null;
             for (i=0; i<N; i++) {
                 PackageParser.Service s = pkg.services.get(i);
-                s.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                //Adwait's patch for services begins
+                //initialize a new string to hold the s.info.name or "process"
+                //if s.info.processName is null, then put this string as s.info.processName, else let it be
+		/*
+                if(pkg.applicationInfo.processName!=null && !pkg.applicationInfo.processName.startsWith("com.android."))
+                {int len = pkg.applicationInfo.packageName.length();
+                String name =s.info.name.substring(len+1);
+ 		//   System.out.println("::Installing service "+sname);
+                     if(s.info.processName==null)
+                         s.info.processName=""+pkg.applicationInfo.packageName+":"+name;
+                }*/
+                //Adwait's patch ends
+		s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         s.info.processName, pkg.applicationInfo.uid);
                 mServices.addService(s);
                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
@@ -3754,6 +3782,18 @@ public class PackageManagerService extends IPackageManager.Stub {
             r = null;
             for (i=0; i<N; i++) {
                 PackageParser.Activity a = pkg.receivers.get(i);
+		//Adwait's patch for receivers begins
+                //initialize a new string to hold the s.info.name or "process"
+                //if s.info.processName is null, then put this string as s.info.processName, else let it be
+		/*
+                if(pkg.applicationInfo.processName!=null && !pkg.applicationInfo.processName.startsWith("com.android"))
+                {int len = pkg.applicationInfo.packageName.length();
+                String name =a.info.name.substring(len+1);
+   		// System.out.println("::Installing Reciever "+aname);
+                     if(a.info.processName==null)
+                     {	a.info.processName=""+pkg.applicationInfo.packageName+":"+name;}
+                }*/
+                //Adwait's patch ends
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         a.info.processName, pkg.applicationInfo.uid);
                 mReceivers.addActivity(a, "receiver");
@@ -3774,6 +3814,23 @@ public class PackageManagerService extends IPackageManager.Stub {
             r = null;
             for (i=0; i<N; i++) {
                 PackageParser.Activity a = pkg.activities.get(i);
+		 //Adwait's patch for activities begins
+                //initialize a new string to hold the s.info.name or "process"
+                //if s.info.processName is null, then put this string as s.info.processName, else let it be
+		/*
+                if(pkg.applicationInfo.processName!=null)// && !pkg.applicationInfo.processName.startsWith("com.android")
+                {
+			int len = pkg.applicationInfo.packageName.length();		
+                	String name ="";
+			if(a.info.name.length()>(len+1))
+				name=a.info.name.substring(len+1);
+			else 
+				name=a.info.name;
+   			// System.out.println("::Installing activity "+aname);
+               		//if(a.info.processName==null)
+                        a.info.processName=""+pkg.applicationInfo.packageName+":"+name;
+                }*/
+                //Adwait's patch ends
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         a.info.processName, pkg.applicationInfo.uid);
                 mActivities.addActivity(a, "activity");
@@ -6334,6 +6391,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                                 res.removedInfo, true);
             }
         }
+	
     }
 
     private void replacePackageLI(PackageParser.Package pkg,
@@ -6703,6 +6761,16 @@ public class PackageManagerService extends IPackageManager.Stub {
             installNewPackageLI(pkg, parseFlags, scanMode,
                     installerPackageName,res);
         }
+	//Adwait: update the packageName in the AquiferService
+	IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try {
+             	aquifer.storePackageName(pkg.packageName, pkg.applicationInfo.uid);
+           	System.out.println("Adding Package: PackageManagerService");
+        } catch (RemoteException e) {
+        // TODO Auto-generated catch block
+        	e.printStackTrace();
+        }
+	    //Adwait's code ends
     }
 
     private int setPermissionsLI(PackageParser.Package newPackage) {
@@ -7178,6 +7246,17 @@ public class PackageManagerService extends IPackageManager.Stub {
             ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
                     writeSettings);
         }
+	//Adwait: remove the packageName from the AquiferService
+        IAquiferService aquifer = IAquiferService.Stub.asInterface(ServiceManager.getService("Aquifer"));
+        try {
+                aquifer.removePackageName(packageName);
+                System.out.println("Removing Package:"+packageName);
+        } catch (RemoteException e) {
+        // TODO Auto-generated catch block
+                e.printStackTrace();
+        }  
+            //Adwait's code ends
+
         return ret;
     }
 
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index 6fa5dfa..884e2bf 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \
     com_android_server_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
+    com_android_server_AquiferService.cpp \
     com_android_server_SystemServer.cpp \
     com_android_server_UsbDeviceManager.cpp \
     com_android_server_UsbHostManager.cpp \
@@ -42,5 +43,5 @@ ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
 endif
 
 LOCAL_MODULE:= libandroid_servers
-
+LOCAL_LDLIBS := -llog
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/jni/com_android_server_AquiferService.cpp b/services/jni/com_android_server_AquiferService.cpp
new file mode 100644
index 0000000..4b6dff1
--- /dev/null
+++ b/services/jni/com_android_server_AquiferService.cpp
@@ -0,0 +1,271 @@
+//the .cpp file which will be an interface between the java and the c file
+/* DO NOT EDIT THIS FILE - it is machine generated */
+//#include "android_os_Aquifer.h"
+#include <jni.h>
+#include <JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include<stdlib.h>
+#include <fcntl.h>
+#include<sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <android/log.h>
+#include <sys/types.h>
+#include<linux/fs.h>
+//#include <attr/xattr.h>
+
+#define  AQUIFER_INET _IOWR('f',18,struct aquifer_inet)
+#define  AQUIFER_SETXATTR _IOWR('f',19,struct file_hook_data)
+#define	 AQUIFER_READ_MODE 1
+#define	 AQUIFER_WRITE_MODE 2
+#define  POLICY_VALID 2
+#define  POLICY_INVALID 3
+
+#define NETLINK_FILE 17
+
+//#define POLICY_SIZE 1024
+#define POLICY_SIZE 224
+#define MAX_PAYLOAD 2048  // maximum payload size
+//#define MAX_PAYLOAD 6144  // maximum payload size
+struct sockaddr_nl src_addr, dest_addr;
+struct nlmsghdr *nlh = NULL;
+struct iovec iov;
+int sock_fd;
+struct msghdr msg;
+bool status = true;
+
+/*
+ * Class:     android_os_Aquifer
+ * Method:    checkAquiferNative
+ * Signature: ()I
+ */
+//using namespace android;
+ 
+namespace android {
+
+struct aquifer_inet
+{
+        pid_t pid;
+        int inetflag;
+};
+struct file_hook_data {
+        pid_t pid;
+        unsigned int inode;
+        unsigned int fmask;
+        struct dentry* dentry;
+        jint policy[POLICY_SIZE];
+};
+
+static jint JNICALL Java_android_server_AquiferService_addInetFlag(JNIEnv *, jclass, jint pid, jint flag)
+{
+	
+	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","ADDING INET FLAG\n");
+	struct aquifer_inet inet;
+	inet.pid=pid;
+	inet.inetflag=flag;
+	int fd;
+	fd = open("/dev/aquifer",O_RDWR);
+	if(fd == -1)
+		return 100;
+	int ret = ioctl(fd, AQUIFER_INET, &inet);
+	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","ADDED INET FLAG\n");
+	if(ret == -1)
+		return 50;
+	close(fd);
+
+	return ret;
+}	
+
+jint JNICALL Java_android_server_AquiferService_democall(JNIEnv* env, jobject obj,jint num){
+	//Calling a function in AquiferService, just to check
+
+	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","ENTERED SOCKET FUNCTION\n");
+//	jstring jstr = env->NewStringUTF("From jni initially");
+    	jclass cls = env->GetObjectClass(obj);
+    	jmethodID method = env->GetMethodID(cls, "message", "(III[B)I");
+	jint in1=0;
+	jint in2=1;
+    	//jobject result = env->CallObjectMethod(obj, method, in1, in2);
+	//Calling java ends
+
+	// Using netlink to talk to the kernel
+	
+	sock_fd = socket(AF_NETLINK, SOCK_RAW,NETLINK_FILE);
+	
+	memset(&src_addr, 0, sizeof(src_addr));
+	src_addr.nl_family = AF_NETLINK;
+	src_addr.nl_pid = getpid();  // self pid 
+	src_addr.nl_groups = 0;  //not in mcast groups 
+	src_addr.nl_pad=0;
+	bind(sock_fd, (struct sockaddr*)&src_addr,sizeof(src_addr));
+
+	memset(&dest_addr, 0, sizeof(dest_addr));
+ 	dest_addr.nl_family = AF_NETLINK;
+ 	dest_addr.nl_pid = 0;   // For Linux Kernel 
+ 	dest_addr.nl_groups = 0;  //unicast 
+	dest_addr.nl_pad=0;
+	nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
+
+	// Fill the netlink message header 
+ 	nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
+	memset(nlh,0,MAX_PAYLOAD);
+ 	nlh->nlmsg_pid = getpid();  // self pid 
+ 	nlh->nlmsg_flags = 1;
+	nlh->nlmsg_type = 0;
+	nlh->nlmsg_len=MAX_PAYLOAD;
+ 	// Fill in the netlink message payload 
+ 	strcpy((char*)NLMSG_DATA(nlh), "Hello you!");
+	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","Sending message payload: %s\n",(char*)(NLMSG_DATA(nlh)));
+	iov.iov_base = (void *)nlh;
+ 	iov.iov_len = nlh->nlmsg_len;
+
+	//msg
+	memset(&msg,0,sizeof(msg));
+ 	msg.msg_name = (void *)&dest_addr;
+ 	msg.msg_namelen = sizeof(dest_addr);
+ 	msg.msg_iov = &iov;
+ 	msg.msg_iovlen = 1;	
+	int error=sendmsg(sock_fd, &msg, 0);
+	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","Error while Sending message payload: %d\n",error);
+
+
+	 // Read message from kernel 
+	//Clear msg buffer first, before reading into it.
+	char* returnstring =NULL;
+	while(1)
+ 	{	
+		struct file_hook_data *file_hook;
+		file_hook = (struct file_hook_data*)malloc(sizeof(struct file_hook_data));
+		if(!file_hook)
+		{
+			//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","Couldnot allocate memory for file_hook_data");
+			continue;
+		}
+		//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","Waiting for Kernel Message.");	
+		memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
+ 		int retval=recvmsg(sock_fd, &msg, 0);
+		memcpy(file_hook, NLMSG_DATA(nlh), sizeof(struct file_hook_data));
+		//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","Received message pid: %d, inode: %d, mask=%d, sizeOfPolicy=%d,Error=%d\n",file_hook->pid, file_hook->inode,file_hook->fmask, sizeof(file_hook->policy) ,retval);
+
+		if(file_hook->fmask == AQUIFER_READ_MODE)
+		{	jmethodID newreadmethod = env->GetMethodID(cls, "readFile", "(III[I)I");
+			//READ
+		
+			// __android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","policy READ:%c",file_hook->policy[0]);
+			//Call a function that returns void. The current method will do.
+			if(file_hook->policy!=NULL)
+    		 	{	
+				jintArray bArray = env->NewIntArray(POLICY_SIZE);
+				env->SetIntArrayRegion(bArray, 0, POLICY_SIZE , file_hook->policy);
+				//env->CallObjectMethod(obj, readmethod, file_hook->pid, file_hook->inode, file_hook->fmask, file_hook->policy);	
+				env->CallObjectMethod(obj, newreadmethod, file_hook->pid, file_hook->inode, file_hook->fmask, bArray);				 
+				env->DeleteLocalRef(bArray);
+				//env->DeleteLocalRef(newreadmethod);
+			}
+			
+		}
+		else if (file_hook->fmask == AQUIFER_WRITE_MODE)
+		{
+			jmethodID newwritemethod = env->GetMethodID(cls, "writeFile", "(III[I)[I");
+			//WRITE
+			// __android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","AQUIFER_WRITE_MODE:");
+			if(file_hook->policy ==NULL)
+			{	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","policy NULL at write");
+				continue;
+			}
+			struct file_hook_data file_hook_reply;
+			file_hook_reply.pid=file_hook->pid;
+			file_hook_reply.inode=file_hook->inode;
+			file_hook_reply.fmask=file_hook->fmask;
+			file_hook_reply.dentry=file_hook->dentry;
+	
+			jintArray bArray = env->NewIntArray(POLICY_SIZE);
+                        env->SetIntArrayRegion(bArray, 0, POLICY_SIZE , file_hook->policy);
+
+			//jintArray receivedArray = env->NewIntArray(POLICY_SIZE); 					
+			jintArray receivedArray; 					
+			receivedArray = (jintArray)(env->CallObjectMethod(obj, newwritemethod, file_hook->pid, file_hook->inode, file_hook->fmask, bArray));	
+			jboolean x;
+			jint *temp = env->GetIntArrayElements(receivedArray, &x);
+
+			//TODO: Go only upo the entire policy size, written in the second integer.
+			//for(int i=0; i<POLICY_SIZE;i++)
+			if(temp[0]==POLICY_INVALID)
+			{
+				file_hook_reply.policy[0] =POLICY_INVALID;
+			}
+			else{	
+				//Adwait: Temp Change
+				/*
+				for(int i=0; i<temp[1];i++)
+					file_hook_reply.policy[i]=temp[i];
+				*/
+				int size=temp[1];
+				memcpy((void*)(file_hook_reply.policy),(const void *)temp, sizeof(int)*size);
+			}
+			//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","12:");
+			
+			//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","policy[0]:%d",file_hook_reply.policy[0] );
+			
+			if(file_hook_reply.policy[0] == POLICY_INVALID)
+                        {        
+				//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","Invalid Policy; abort label transfer on write.");
+			}
+			else
+			{	//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","13:");
+				int fd;
+        			fd = open("/dev/aquifer",O_RDWR);
+				//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE","14:");
+				ioctl(fd, AQUIFER_SETXATTR, &file_hook_reply);
+				//__android_log_print(ANDROID_LOG_DEBUG, "AQUIFERSERVICE WRITING BACK","15:");
+				//env->ReleaseByteArrayElements(receivedArray, temp, JNI_ABORT);
+			}
+			//Freeing bArray 
+			env->DeleteLocalRef(bArray);
+			//Clearing receivedArray and temp after use
+			env->ReleaseIntArrayElements(receivedArray, temp, JNI_ABORT);
+			env->DeleteLocalRef(receivedArray);
+			//free(temp);
+		}
+		else{}
+		free(file_hook);
+    		 //env->CallObjectMethod(obj, method, file_hook->pid, file_hook->inode_no, file_hook->fmask, file_hook->policy);
+		
+		//jobject result = env->CallObjectMethod(obj, method, in1, in2);
+		//returnstring = (char*)(NLMSG_DATA(nlh));
+	} 
+ 	// Close Netlink Socket
+ 	close(sock_fd);
+	//socket closed
+	if(returnstring==NULL)
+		return 101;
+	else
+		return (int)(returnstring[0]);
+	
+	return num*num;
+
+}
+
+static JNINativeMethod methods[] = {
+      {"addInetFlag", "(II)I", (void *) Java_android_server_AquiferService_addInetFlag},
+      {"democall","(I)I",(void *)Java_android_server_AquiferService_democall}};
+
+const char* const kAquiferPathName = "com/android/server/AquiferService";
+int register_android_server_AquiferService(JNIEnv* env)
+{  
+    return AndroidRuntime::registerNativeMethods(
+        env, kAquiferPathName,
+        methods, NELEM(methods));
+}
+};
+//#ifdef __cplusplus
+//}
+//#endif
+
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 4178039..49240f4 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -33,6 +33,7 @@ int register_android_server_VibratorService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
 int register_android_server_location_GpsLocationProvider(JNIEnv* env);
 int register_android_server_connectivity_Vpn(JNIEnv* env);
+int register_android_server_AquiferService(JNIEnv* env);
 };
 
 using namespace android;
@@ -61,6 +62,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
     register_android_server_SystemServer(env);
     register_android_server_location_GpsLocationProvider(env);
     register_android_server_connectivity_Vpn(env);
-
+    register_android_server_AquiferService(env);
     return JNI_VERSION_1_4;
 }
-- 
1.7.9.5

