Encrypted File Systems Project. Installer modifications.
Started to modify isntaller for data redirection to a secure location.
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 70a1206..dcae0c7 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -16,7 +16,7 @@
 
 #include "installd.h"
 
-int install(const char *pkgname, uid_t uid, gid_t gid)
+int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid)
 {
     char pkgdir[PKG_PATH_MAX];
     char libdir[PKG_PATH_MAX];
@@ -26,10 +26,18 @@
         return -1;
         
     }
-    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
-        return -1;
-    if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
-        return -1;
+
+    if (encrypted_fs_flag == USE_UNENCRYPTED_FS) {
+        if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+            return -1;
+        if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
+            return -1;
+    } else {
+        if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+            return -1;
+        if (create_pkg_path(libdir, PKG_SEC_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
+            return -1;
+    }
 
     if (mkdir(pkgdir, 0755) < 0) {
         LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
@@ -54,41 +62,58 @@
     return 0;
 }
 
-int uninstall(const char *pkgname)
+int uninstall(const char *pkgname, int encrypted_fs_flag)
 {
     char pkgdir[PKG_PATH_MAX];
 
-    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
-        return -1;
+    if (encrypted_fs_flag == USE_UNENCRYPTED_FS) {
+        if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+            return -1;
+    } else {
+        if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+            return -1;
+    }
 
         /* delete contents AND directory, no exceptions */
     return delete_dir_contents(pkgdir, 1, 0);
 }
 
-int delete_user_data(const char *pkgname)
+int delete_user_data(const char *pkgname, int encrypted_fs_flag)
 {
     char pkgdir[PKG_PATH_MAX];
 
-    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
-        return -1;
+    if (encrypted_fs_flag == USE_UNENCRYPTED_FS) {
+        if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+            return -1;
+    } else {
+        if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+            return -1;
+    }
 
         /* delete contents, excluding "lib", but not the directory itself */
     return delete_dir_contents(pkgdir, 0, "lib");
 }
 
-int delete_cache(const char *pkgname)
+int delete_cache(const char *pkgname, int encrypted_fs_flag)
 {
     char cachedir[PKG_PATH_MAX];
 
-    if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
-        return -1;
+    if (encrypted_fs_flag == USE_UNENCRYPTED_FS) {
+        if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
+            return -1;
+    } else {
+        if (create_pkg_path(cachedir, CACHE_SEC_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
+            return -1;
+    }
 
         /* delete contents, not the directory, no exceptions */
     return delete_dir_contents(cachedir, 0, 0);
 }
 
-
-static int disk_free(void)
+/* TODO(oam): depending on use case (ecryptfs or dmcrypt)
+ * change implementation
+ */
+static int disk_free()
 {
     struct statfs sfs;
     if (statfs(PKG_DIR_PREFIX, &sfs) == 0) {
@@ -98,7 +123,6 @@
     }
 }
 
-
 /* Try to ensure free_size bytes of storage are available.
  * Returns 0 on success.
  * This is rather simple-minded because doing a full LRU would
@@ -120,6 +144,39 @@
     LOGI("free_cache(%d) avail %d\n", free_size, avail);
     if (avail >= free_size) return 0;
 
+    /* First try encrypted dir */
+    d = opendir(PKG_SEC_DIR_PREFIX);
+    if (d == NULL) {
+        LOGE("cannot open %s\n", PKG_SEC_DIR_PREFIX);
+    } else {
+        dfd = dirfd(d);
+
+        while ((de = readdir(d))) {
+           if (de->d_type != DT_DIR) continue;
+           name = de->d_name;
+
+            /* always skip "." and ".." */
+            if (name[0] == '.') {
+                if (name[1] == 0) continue;
+                if ((name[1] == '.') && (name[2] == 0)) continue;
+            }
+
+            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+            if (subfd < 0) continue;
+
+            delete_dir_contents_fd(subfd, "cache");
+            close(subfd);
+
+            avail = disk_free();
+            if (avail >= free_size) {
+                closedir(d);
+                return 0;
+            }
+        }
+        closedir(d);
+    }
+
+    /* Next try unencrypted dir... */
     d = opendir(PKG_DIR_PREFIX);
     if (d == NULL) {
         LOGE("cannot open %s\n", PKG_DIR_PREFIX);
@@ -131,7 +188,7 @@
         if (de->d_type != DT_DIR) continue;
         name = de->d_name;
 
-            /* always skip "." and ".." */
+        /* always skip "." and ".." */
         if (name[0] == '.') {
             if (name[1] == 0) continue;
             if ((name[1] == '.') && (name[2] == 0)) continue;
@@ -150,10 +207,11 @@
         }
     }
     closedir(d);
+
+    /* Fail case - not possible to free space */
     return -1;
 }
 
-
 /* used by move_dex, rm_dex, etc to ensure that the provided paths
  * don't point anywhere other than at the APK_DIR_PREFIX
  */
@@ -288,7 +346,7 @@
 
 int get_size(const char *pkgname, const char *apkpath,
              const char *fwdlock_apkpath,
-             int *_codesize, int *_datasize, int *_cachesize)
+             int *_codesize, int *_datasize, int *_cachesize, int encrypted_fs_flag)
 {
     DIR *d;
     int dfd;
@@ -324,8 +382,14 @@
         }
     }
 
-    if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
-        goto done;
+    if (encrypted_fs_flag == 0) {
+        if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
+            goto done;
+        }
+    } else {
+        if (create_pkg_path(path, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
+            goto done;
+        }
     }
 
     d = opendir(path);
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 7c7441f..5bc6c86 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -29,7 +29,7 @@
 
 static int do_install(char **arg, char reply[REPLY_MAX])
 {
-    return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
+    return install(arg[0], atoi(arg[1]), atoi(arg[2]), atoi(arg[3])); /* pkgname, uid, gid */
 }
 
 static int do_dexopt(char **arg, char reply[REPLY_MAX])
@@ -50,7 +50,7 @@
 
 static int do_remove(char **arg, char reply[REPLY_MAX])
 {
-    return uninstall(arg[0]); /* pkgname */
+    return uninstall(arg[0], atoi(arg[1])); /* pkgname */
 }
 
 static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
@@ -60,7 +60,7 @@
 
 static int do_rm_cache(char **arg, char reply[REPLY_MAX])
 {
-    return delete_cache(arg[0]); /* pkgname */
+    return delete_cache(arg[0], atoi(arg[1])); /* pkgname */
 }
 
 static int do_protect(char **arg, char reply[REPLY_MAX])
@@ -76,7 +76,7 @@
     int res = 0;
 
         /* pkgdir, apkpath */
-    res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize);
+    res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize, atoi(arg[3]));
 
     sprintf(reply,"%d %d %d", codesize, datasize, cachesize);
     return res;
@@ -84,7 +84,7 @@
 
 static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
 {
-    return delete_user_data(arg[0]); /* pkgname */
+    return delete_user_data(arg[0], atoi(arg[1])); /* pkgname */
 }
 
 struct cmdinfo {
@@ -95,16 +95,16 @@
 
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
-    { "install",              3, do_install },
+    { "install",              4, do_install },
     { "dexopt",               3, do_dexopt },
     { "movedex",              2, do_move_dex },
     { "rmdex",                1, do_rm_dex },
-    { "remove",               1, do_remove },
+    { "remove",               2, do_remove },
     { "freecache",            1, do_free_cache },
-    { "rmcache",              1, do_rm_cache },
+    { "rmcache",              2, do_rm_cache },
     { "protect",              2, do_protect },
-    { "getsize",              3, do_get_size },
-    { "rmuserdata",           1, do_rm_user_data },
+    { "getsize",              4, do_get_size },
+    { "rmuserdata",           2, do_rm_user_data },
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index db3badd..1679d14 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -48,16 +48,23 @@
 /* elements combined with a valid package name to form paths */
 
 #define PKG_DIR_PREFIX         "/data/data/"
+#define PKG_SEC_DIR_PREFIX     "/data/secure/data/"
 #define PKG_DIR_POSTFIX        ""
 
 #define PKG_LIB_PREFIX         "/data/data/"
+#define PKG_SEC_LIB_PREFIX     "/data/secure/data/"
 #define PKG_LIB_POSTFIX        "/lib"
 
 #define CACHE_DIR_PREFIX       "/data/data/"
+#define CACHE_SEC_DIR_PREFIX   "/data/secure/data/"
 #define CACHE_DIR_POSTFIX      "/cache"
 
 #define APK_DIR_PREFIX         "/data/app/"
 
+/* Encrypted File SYstems constants */
+#define USE_ENCRYPTED_FS       1
+#define USE_UNENCRYPTED_FS     0
+
 /* other handy constants */
 
 #define PROTECTED_DIR_PREFIX  "/data/app-private/"
@@ -87,14 +94,14 @@
 
 /* commands.c */
 
-int install(const char *pkgname, uid_t uid, gid_t gid);
-int uninstall(const char *pkgname);
-int delete_user_data(const char *pkgname);
-int delete_cache(const char *pkgname);
+int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid);
+int uninstall(const char *pkgname, int encrypted_fs_flag);
+int delete_user_data(const char *pkgname, int encrypted_fs_flag);
+int delete_cache(const char *pkgname, int encrypted_fs_flag);
 int move_dex(const char *src, const char *dst);
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
 int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
-             int *codesize, int *datasize, int *cachesize);
+             int *codesize, int *datasize, int *cachesize, int encrypted_fs_flag);
 int free_cache(int free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 1a8d9b6..e6941e6 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -38,6 +38,7 @@
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -52,6 +53,7 @@
 import android.util.Log;
 import android.util.Pair;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1322,9 +1324,20 @@
         }
     }
 
+    private static String getDatabaseName() {
+        if(Environment.isEncryptedFilesystemEnabled()) {
+            // Hard-coded path in case of encrypted file system
+            return Environment.getSystemSecureDirectory().getPath() + File.separator + DATABASE_NAME;
+        } else {
+            // Regular path in case of non-encrypted file system
+            return DATABASE_NAME;
+        }
+    }
+
     private class DatabaseHelper extends SQLiteOpenHelper {
+
         public DatabaseHelper(Context context) {
-            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+            super(context, AccountManagerService.getDatabaseName(), null, DATABASE_VERSION);
         }
 
         @Override
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 1e04abf..b3d16e9 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -466,14 +466,7 @@
 
     @Override
     public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
-        File dir = getDatabasesDir();
-        if (!dir.isDirectory() && dir.mkdir()) {
-            FileUtils.setPermissions(dir.getPath(),
-                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-                -1, -1);
-        }
-
-        File f = makeFilename(dir, name);
+        File f = validateFilePath(name, true);
         SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
         setFilePermissionsFromMode(f.getPath(), mode, 0);
         return db;
@@ -482,7 +475,7 @@
     @Override
     public boolean deleteDatabase(String name) {
         try {
-            File f = makeFilename(getDatabasesDir(), name);
+            File f = validateFilePath(name, false);
             return f.delete();
         } catch (Exception e) {
         }
@@ -491,7 +484,7 @@
 
     @Override
     public File getDatabasePath(String name) {
-        return makeFilename(getDatabasesDir(), name);
+        return validateFilePath(name, false);
     }
 
     @Override
@@ -1454,12 +1447,35 @@
         FileUtils.setPermissions(name, perms, -1, -1);
     }
 
+    private File validateFilePath(String name, boolean createDirectory) {
+        File dir;
+        File f;
+
+        if (name.charAt(0) == File.separatorChar) {
+            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
+            dir = new File(dirPath);
+            name = name.substring(name.lastIndexOf(File.separatorChar));
+            f = new File(dir, name);
+        } else {
+            dir = getDatabasesDir();
+            f = makeFilename(dir, name);
+        }
+
+        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
+            FileUtils.setPermissions(dir.getPath(),
+                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                -1, -1);
+        }
+
+        return f;
+    }
+
     private File makeFilename(File base, String name) {
         if (name.indexOf(File.separatorChar) < 0) {
             return new File(base, name);
         }
         throw new IllegalArgumentException(
-            "File " + name + " contains a path separator");
+                "File " + name + " contains a path separator");
     }
 
     // ----------------------------------------------------------------------
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index be70909..b6bb7db 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -16,16 +16,11 @@
 
 package android.content;
 
-import com.android.internal.os.AtomicFile;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastXmlSerializer;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
 import android.accounts.Account;
-import android.backup.IBackupManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
@@ -37,11 +32,15 @@
 import android.os.Parcel;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.Xml;
 
+import com.android.internal.os.AtomicFile;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastXmlSerializer;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -258,7 +257,9 @@
 
         mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
 
-        File dataDir = Environment.getDataDirectory();
+        // This call will return the correct directory whether Encrypted File Systems is
+        // enabled or not.
+        File dataDir = Environment.getSecureDataDirectory();
         File systemDir = new File(dataDir, "system");
         File syncDir = new File(systemDir, "sync");
         mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f761e8e..6212b17 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -26,6 +26,8 @@
     private static final File ROOT_DIRECTORY
             = getDirectory("ANDROID_ROOT", "/system");
 
+    private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
+
     /**
      * Gets the Android root directory.
      */
@@ -33,9 +35,55 @@
         return ROOT_DIRECTORY;
     }
 
+    /**
+     * Gets the system directory available for secure storage.
+     * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
+     * Otherwise, it returns the unencrypted /data/system directory.
+     * @return File object representing the secure storage system directory.
+     * @hide
+     */
+    public static File getSystemSecureDirectory() {
+        if (isEncryptedFilesystemEnabled()) {
+            return new File(SECURE_DATA_DIRECTORY, "system");
+        } else {
+            return new File(DATA_DIRECTORY, "system");
+        }
+    }
+
+    /**
+     * Gets the data directory for secure storage.
+     * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure).
+     * Otherwise, it returns the unencrypted /data directory.
+     * @return File object representing the data directory for secure storage.
+     * @hide
+     */
+    public static File getSecureDataDirectory() {
+        if (isEncryptedFilesystemEnabled()) {
+            return SECURE_DATA_DIRECTORY;
+        } else {
+            return DATA_DIRECTORY;
+        }
+    }
+
+    /**
+     * Returns whether the Encrypted File System feature is enabled on the device or not.
+     * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code>
+     * if disabled.
+     * @hide
+     */
+    public static boolean isEncryptedFilesystemEnabled() {
+        return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false);
+    }
+
     private static final File DATA_DIRECTORY
             = getDirectory("ANDROID_DATA", "/data");
 
+    /**
+     * @hide
+     */
+    private static final File SECURE_DATA_DIRECTORY
+            = getDirectory("ANDROID_SECURE_DATA", "/data/secure");
+
     private static final File EXTERNAL_STORAGE_DIRECTORY
             = getDirectory("EXTERNAL_STORAGE", "/sdcard");
 
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 1e1d729..a542518 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -9,7 +9,8 @@
                  android:process="system"
                  android:backupAgent="SettingsBackupAgent"
                  android:killAfterRestore="false"
-                 android:icon="@drawable/ic_launcher_settings">
+                 android:icon="@drawable/ic_launcher_settings"
+                 android:neverEncrypt="true">
 
         <provider android:name="SettingsProvider" android:authorities="settings"
                   android:multiprocess="false"
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
index e5be847..eeafd5a 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
@@ -26,7 +26,9 @@
 import android.net.vpn.VpnManager;
 import android.net.vpn.VpnProfile;
 import android.net.vpn.VpnState;
+import android.os.Environment;
 import android.os.IBinder;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import java.io.File;
@@ -45,11 +47,18 @@
     private static final String TAG = VpnServiceBinder.class.getSimpleName();
     private static final boolean DBG = true;
 
-    private static final String STATES_FILE_PATH = "/data/misc/vpn/.states";
+    private static final String STATES_FILE_RELATIVE_PATH = "/misc/vpn/.states";
 
     // The actual implementation is delegated to the VpnService class.
     private VpnService<? extends VpnProfile> mService;
 
+    // TODO(oam): Test VPN when EFS is enabled (will do later)...
+    private static String getStateFilePath() {
+        // This call will return the correcu directory whether Encrypted FS is enabled or not
+        // Disabled: /data/misc/vpn/.states   Enabled: /data/secure/misc/vpn/.states
+	return Environment.getSecureDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH;
+    }
+
     private final IBinder mBinder = new IVpnService.Stub() {
         public boolean connect(VpnProfile p, String username, String password) {
             return VpnServiceBinder.this.connect(p, username, password);
@@ -84,14 +93,14 @@
     void saveStates() throws IOException {
         if (DBG) Log.d("VpnServiceBinder", "     saving states");
         ObjectOutputStream oos =
-                new ObjectOutputStream(new FileOutputStream(STATES_FILE_PATH));
+                new ObjectOutputStream(new FileOutputStream(getStateFilePath()));
         oos.writeObject(mService);
         oos.close();
     }
 
     void removeStates() {
         try {
-            File f = new File(STATES_FILE_PATH);
+            File f = new File(getStateFilePath());
             if (f.exists()) f.delete();
         } catch (Throwable e) {
             if (DBG) Log.d("VpnServiceBinder", "     remove states: " + e);
@@ -134,7 +143,7 @@
     private void checkSavedStates() {
         try {
             ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
-                    STATES_FILE_PATH));
+                    getStateFilePath()));
             mService = (VpnService<? extends VpnProfile>) ois.readObject();
             mService.recover(this);
             ois.close();
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index c3b591e..1171416 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -22,6 +22,10 @@
 import android.app.IApplicationThread;
 import android.app.IBackupAgent;
 import android.app.PendingIntent;
+import android.backup.IBackupManager;
+import android.backup.IRestoreObserver;
+import android.backup.IRestoreSession;
+import android.backup.RestoreSet;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -31,11 +35,10 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
-import android.provider.Settings;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -47,20 +50,15 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseArray;
 
-import android.backup.IBackupManager;
-import android.backup.IRestoreObserver;
-import android.backup.IRestoreSession;
-import android.backup.RestoreSet;
-
 import com.android.internal.backup.BackupConstants;
-import com.android.internal.backup.LocalTransport;
 import com.android.internal.backup.IBackupTransport;
-
-import com.android.server.PackageManagerBackupAgent;
+import com.android.internal.backup.LocalTransport;
 import com.android.server.PackageManagerBackupAgent.Metadata;
 
 import java.io.EOFException;
@@ -70,7 +68,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.RandomAccessFile;
-import java.lang.String;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -232,7 +229,10 @@
                 Settings.Secure.BACKUP_ENABLED, 0) != 0;
         mProvisioned = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.BACKUP_PROVISIONED, 0) != 0;
-        mBaseStateDir = new File(Environment.getDataDirectory(), "backup");
+        // If Encrypted file systems is enabled or disabled, this call will return the
+        // correct directory.
+        mBaseStateDir = new File(Environment.getSecureDataDirectory(), "backup");
+        mBaseStateDir.mkdirs();
         mDataDir = Environment.getDownloadCacheDirectory();
 
         // Alarm receivers for scheduled backups & initialization operations
diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/Installer.java
index fe3ad15..6a7d432 100644
--- a/services/java/com/android/server/Installer.java
+++ b/services/java/com/android/server/Installer.java
@@ -166,11 +166,17 @@
 		}
 	}
 
-    public int install(String name, int uid, int gid) {
+    public int install(String name, boolean useEncryptedFilesystem, int uid, int gid) {
         StringBuilder builder = new StringBuilder("install");
         builder.append(' ');
         builder.append(name);
         builder.append(' ');
+        if (useEncryptedFilesystem) {
+            builder.append('1');
+        } else {
+            builder.append('0');
+        }
+        builder.append(' ');
         builder.append(uid);
         builder.append(' ');
         builder.append(gid);
@@ -203,24 +209,42 @@
         return execute(builder.toString());
     }
 
-    public int remove(String name) {
+    public int remove(String name, boolean useEncryptedFilesystem) {
         StringBuilder builder = new StringBuilder("remove");
         builder.append(' ');
         builder.append(name);
+        builder.append(' ');
+        if (useEncryptedFilesystem) {
+            builder.append('1');
+        } else {
+            builder.append('0');
+        }
         return execute(builder.toString());
     }
 
-    public int deleteCacheFiles(String name) {
+    public int deleteCacheFiles(String name, boolean useEncryptedFilesystem) {
         StringBuilder builder = new StringBuilder("rmcache");
         builder.append(' ');
         builder.append(name);
+        builder.append(' ');
+        if (useEncryptedFilesystem) {
+            builder.append('1');
+        } else {
+            builder.append('0');
+        }
         return execute(builder.toString());
     }
     
-    public int clearUserData(String name) {
+    public int clearUserData(String name, boolean useEncryptedFilesystem) {
         StringBuilder builder = new StringBuilder("rmuserdata");
         builder.append(' ');
         builder.append(name);
+        builder.append(' ');
+        if (useEncryptedFilesystem) {
+            builder.append('1');
+        } else {
+            builder.append('0');
+        }
         return execute(builder.toString());
     }
     
@@ -249,7 +273,7 @@
     }
     
     public int getSizeInfo(String pkgName, String apkPath,
-            String fwdLockApkPath, PackageStats pStats) {
+            String fwdLockApkPath, PackageStats pStats, boolean useEncryptedFilesystem) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
@@ -257,6 +281,12 @@
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
+        builder.append(' ');
+        if (useEncryptedFilesystem) {
+            builder.append('1');
+        } else {
+            builder.append('0');
+        }
 
         String s = transaction(builder.toString());
         String res[] = s.split(" ");
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5ed2d35..9f01c61 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -122,6 +122,8 @@
 
     private static final boolean GET_CERTIFICATES = true;
 
+    private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
+
     private static final int REMOVE_EVENTS =
         FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
     private static final int ADD_EVENTS =
@@ -160,6 +162,10 @@
     // This is where all application persistent data goes.
     final File mAppDataDir;
 
+    // If Encrypted File System feature is enabled, all application persistent data
+    // should go here instead.
+    final File mSecureAppDataDir;
+
     // This is the object monitoring the framework dir.
     final FileObserver mFrameworkInstallObserver;
 
@@ -422,6 +428,7 @@
             
             File dataDir = Environment.getDataDirectory();
             mAppDataDir = new File(dataDir, "data");
+            mSecureAppDataDir = new File(dataDir, "secure/data");
             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
 
             if (mInstaller == null) {
@@ -431,6 +438,7 @@
                 File miscDir = new File(dataDir, "misc");
                 miscDir.mkdirs();
                 mAppDataDir.mkdirs();
+                mSecureAppDataDir.mkdirs();
                 mDrmAppPrivateInstallDir.mkdirs();
             }
 
@@ -573,7 +581,7 @@
                 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
             }
             //look for any incomplete package installations
-            ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
+            ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
             //clean up list
             for(int i = 0; i < deletePkgsList.size(); i++) {
                 //clean up here
@@ -628,20 +636,20 @@
         }
     }
 
-    void cleanupInstallFailedPackage(String packageName) {
+    void cleanupInstallFailedPackage(PackageSetting pkgSettings) {
         if (mInstaller != null) {
-            int retCode = mInstaller.remove(packageName);
+            boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg);
+            int retCode = mInstaller.remove(pkgSettings.name, useSecureFS);
             if (retCode < 0) {
                 Log.w(TAG, "Couldn't remove app data directory for package: "
-                           + packageName + ", retcode=" + retCode);
+                           + pkgSettings.name + ", retcode=" + retCode);
             }
         } else {
             //for emulator
-            PackageParser.Package pkg = mPackages.get(packageName);
-            File dataDir = new File(pkg.applicationInfo.dataDir);
+            File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir);
             dataDir.delete();
         }
-        mSettings.removePackageLP(packageName);
+        mSettings.removePackageLP(pkgSettings.name);
     }
 
     void readPermissions() {
@@ -2155,6 +2163,11 @@
         
         return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
     }
+
+    private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
+        return Environment.isEncryptedFilesystemEnabled() &&
+                ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
+    }
     
     private PackageParser.Package scanPackageLI(
         File scanFile, File destCodeFile, File destResourceFile,
@@ -2364,8 +2377,9 @@
         }
 
         if (removeExisting) {
+            boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
             if (mInstaller != null) {
-                int ret = mInstaller.remove(pkgName);
+                int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
                 if (ret != 0) {
                     String msg = "System package " + pkg.packageName
                             + " could not have data directory erased after signature change.";
@@ -2395,7 +2409,12 @@
             pkg.applicationInfo.dataDir = dataPath.getPath();
         } else {
             // This is a normal package, need to make its data directory.
-            dataPath = new File(mAppDataDir, pkgName);
+            boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
+            if (useEncryptedFSDir) {
+                dataPath = new File(mSecureAppDataDir, pkgName);
+            } else {
+                dataPath = new File(mAppDataDir, pkgName);
+            }
             if (dataPath.exists()) {
                 mOutPermissions[1] = 0;
                 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
@@ -2408,7 +2427,7 @@
                         // If this is a system app, we can at least delete its
                         // current data so the application will still work.
                         if (mInstaller != null) {
-                            int ret = mInstaller.remove(pkgName);
+                            int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
                             if(ret >= 0) {
                                 // Old data gone!
                                 String msg = "System package " + pkg.packageName
@@ -2419,7 +2438,7 @@
                                 recovered = true;
                                 
                                 // And now re-install the app.
-                                ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
+                                ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
                                         pkg.applicationInfo.uid);
                                 if (ret == -1) {
                                     // Ack should not happen!
@@ -2459,7 +2478,7 @@
                     Log.v(TAG, "Want this data dir: " + dataPath);
                 //invoke installer to do the actual installation
                 if (mInstaller != null) {
-                    int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
+                    int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
                             pkg.applicationInfo.uid);
                     if(ret < 0) {
                         // Error from installer
@@ -3822,7 +3841,13 @@
             PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             String installerPackageName, PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
-        boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
+        boolean dataDirExists;
+
+        if (useEncryptedFilesystemForPackage(pkg)) {
+            dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
+        } else {
+            dataDirExists = (new File(mAppDataDir, pkgName)).exists();
+        }
         res.name = pkgName;
         synchronized(mPackages) {
             if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
@@ -4552,8 +4577,9 @@
             deletedPs = mSettings.mPackages.get(packageName);
         }
         if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
+            boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
             if (mInstaller != null) {
-                int retCode = mInstaller.remove(packageName);
+                int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
                 if (retCode < 0) {
                     Log.w(TAG, "Couldn't remove app data or cache directory for package: "
                                + packageName + ", retcode=" + retCode);
@@ -4795,6 +4821,8 @@
                 p = ps.pkg;
             }
         }
+        boolean useEncryptedFSDir = false;
+
         if(!dataOnly) {
             //need to check this only for fully installed applications
             if (p == null) {
@@ -4806,9 +4834,10 @@
                 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
                 return false;
             }
+            useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
         }
         if (mInstaller != null) {
-            int retCode = mInstaller.clearUserData(packageName);
+            int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
             if (retCode < 0) {
                 Log.w(TAG, "Couldn't remove cache files for package: "
                         + packageName);
@@ -4859,8 +4888,9 @@
             Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
             return false;
         }
+        boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
         if (mInstaller != null) {
-            int retCode = mInstaller.deleteCacheFiles(packageName);
+            int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
             if (retCode < 0) {
                 Log.w(TAG, "Couldn't remove cache files for package: "
                            + packageName);
@@ -4922,9 +4952,10 @@
             }
             publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
         }
+        boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
         if (mInstaller != null) {
             int res = mInstaller.getSizeInfo(packageName, p.mPath,
-                    publicSrcDir, pStats);
+                    publicSrcDir, pStats, useEncryptedFSDir);
             if (res < 0) {
                 return false;
             } else {
@@ -6132,11 +6163,18 @@
         Settings() {
             File dataDir = Environment.getDataDirectory();
             File systemDir = new File(dataDir, "system");
+            // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
+            File systemSecureDir = new File(dataDir, "secure/system");
             systemDir.mkdirs();
+            systemSecureDir.mkdirs();
             FileUtils.setPermissions(systemDir.toString(),
                     FileUtils.S_IRWXU|FileUtils.S_IRWXG
                     |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                     -1, -1);
+            FileUtils.setPermissions(systemSecureDir.toString(),
+                    FileUtils.S_IRWXU|FileUtils.S_IRWXG
+                    |FileUtils.S_IROTH|FileUtils.S_IXOTH,
+                    -1, -1);
             mSettingsFilename = new File(systemDir, "packages.xml");
             mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
         }
@@ -6807,15 +6845,15 @@
             return mReadMessages.toString();
         }
 
-        ArrayList<String> getListOfIncompleteInstallPackages() {
+        ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
             HashSet<String> kList = new HashSet<String>(mPackages.keySet());
             Iterator<String> its = kList.iterator();
-            ArrayList<String> ret = new ArrayList<String>();
+            ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
             while(its.hasNext()) {
                 String key = its.next();
                 PackageSetting ps = mPackages.get(key);
                 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
-                    ret.add(key);
+                    ret.add(ps);
                 }
             }
             return ret;
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index 6df612e..311221c 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -16,11 +16,15 @@
 
 package android.net.vpn;
 
+import java.io.File;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.os.Environment;
+import android.os.SystemProperties;
 import android.util.Log;
 
 /**
@@ -65,7 +69,7 @@
     /** Error code to indicate a successful connection. */
     public static final int VPN_ERROR_NO_ERROR = 0;
 
-    public static final String PROFILES_PATH = "/data/misc/vpn/profiles";
+    private static final String PROFILES_PATH = "/misc/vpn/profiles";
 
     private static final String PACKAGE_PREFIX =
             VpnManager.class.getPackage().getName() + ".";
@@ -77,7 +81,13 @@
     private static final String ACTION_VPN_SETTINGS =
             PACKAGE_PREFIX + "SETTINGS";
 
-    private static final String TAG = VpnManager.class.getSimpleName();
+    public static final String TAG = VpnManager.class.getSimpleName();
+
+    // TODO(oam): Test VPN when EFS is enabled (will do later)...
+    public static String getProfilePath() {
+        // This call will return the correct path if Encrypted FS is enabled or not.
+        return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH;
+    }
 
     /**
      * Returns all supported VPN types.