diff options
26 files changed, 583 insertions, 106 deletions
diff --git a/api/current.xml b/api/current.xml index b0d9931..ca1044c 100644 --- a/api/current.xml +++ b/api/current.xml @@ -120621,6 +120621,240 @@ </method> </class> </package> +<package name="android.os.storage" +> +<class name="StorageEventListener" + extends="java.lang.Object" + abstract="true" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="StorageEventListener" + type="android.os.storage.StorageEventListener" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<method name="onStorageStateChanged" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="path" type="java.lang.String"> +</parameter> +<parameter name="oldState" type="java.lang.String"> +</parameter> +<parameter name="newState" type="java.lang.String"> +</parameter> +</method> +<method name="onUsbMassStorageConnectionChanged" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="connected" type="boolean"> +</parameter> +</method> +</class> +<class name="StorageManager" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="disableUsbMassStorage" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="enableUsbMassStorage" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="isUsbMassStorageConnected" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="isUsbMassStorageEnabled" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="registerListener" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.os.storage.StorageEventListener"> +</parameter> +</method> +<method name="unregisterListener" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.os.storage.StorageEventListener"> +</parameter> +</method> +</class> +<class name="StorageResultCode" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="StorageResultCode" + type="android.os.storage.StorageResultCode" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<field name="OperationFailedInternalError" + type="int" + transient="false" + volatile="false" + value="-1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationFailedMediaBlank" + type="int" + transient="false" + volatile="false" + value="-3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationFailedMediaCorrupt" + type="int" + transient="false" + volatile="false" + value="-4" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationFailedNoMedia" + type="int" + transient="false" + volatile="false" + value="-2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationFailedStorageBusy" + type="int" + transient="false" + volatile="false" + value="-7" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationFailedStorageMounted" + type="int" + transient="false" + volatile="false" + value="-6" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationFailedStorageNotMounted" + type="int" + transient="false" + volatile="false" + value="-5" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OperationSucceeded" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +</package> <package name="android.preference" > <class name="CheckBoxPreference" diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 41f070c..b8ba3f6 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]; @@ -27,11 +27,17 @@ int install(const char *pkgname, uid_t uid, gid_t gid) } - 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, 0751) < 0) { LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -56,27 +62,38 @@ int install(const char *pkgname, uid_t uid, gid_t gid) 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 renamepkg(const char *oldpkgname, const char *newpkgname) +int renamepkg(const char *oldpkgname, const char *newpkgname, int encrypted_fs_flag) { char oldpkgdir[PKG_PATH_MAX]; char newpkgdir[PKG_PATH_MAX]; - if (create_pkg_path(oldpkgdir, PKG_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX)) - return -1; - if (create_pkg_path(newpkgdir, PKG_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX)) - return -1; - + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(oldpkgdir, PKG_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(newpkgdir, PKG_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(oldpkgdir, PKG_SEC_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(newpkgdir, PKG_SEC_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX)) + return -1; + } if (rename(oldpkgdir, newpkgdir) < 0) { LOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno)); @@ -85,29 +102,41 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 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); } +/* TODO(oam): depending on use case (ecryptfs or dmcrypt) + * change implementation + */ static int disk_free() { struct statfs sfs; @@ -139,6 +168,39 @@ int free_cache(int free_size) 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); @@ -314,7 +376,7 @@ static int calculate_dir_size(int dfd) 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; @@ -349,8 +411,14 @@ int get_size(const char *pkgname, const char *apkpath, } } - 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 f6ca998..882c493 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -29,7 +29,7 @@ static int do_ping(char **arg, char reply[REPLY_MAX]) 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,12 +50,12 @@ static int do_rm_dex(char **arg, char reply[REPLY_MAX]) 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_rename(char **arg, char reply[REPLY_MAX]) { - return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */ + return renamepkg(arg[0], arg[1], atoi(arg[2])); /* oldpkgname, newpkgname */ } static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ @@ -65,7 +65,7 @@ static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_siz 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]) @@ -81,7 +81,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) 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; @@ -89,7 +89,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) 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 */ } static int do_movefiles(char **arg, char reply[REPLY_MAX]) @@ -105,17 +105,17 @@ struct cmdinfo { 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 }, - { "rename", 2, do_rename }, + { "remove", 2, do_remove }, + { "rename", 3, do_rename }, { "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 }, { "movefiles", 0, do_movefiles }, }; diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index cfcdb98..8e4adb1 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/" @@ -89,16 +96,16 @@ int delete_dir_contents_fd(int dfd, const char *name); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid); -int uninstall(const char *pkgname); -int renamepkg(const char *oldpkgname, const char *newpkgname); -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 renamepkg(const char *oldpkgname, const char *newpkgname, 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); int movefiles(); diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 1cd7aa7..1d9e0f1 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1483,7 +1483,13 @@ public class AccountManagerService } private static String getDatabaseName() { - return DATABASE_NAME; + 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 { diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 6a959ae..daad95c 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -312,7 +312,9 @@ public class SyncStorageEngine extends Handler { if (sSyncStorageEngine != null) { return; } - File dataDir = Environment.getDataDirectory(); + // This call will return the correct directory whether Encrypted File Systems is + // enabled or not. + File dataDir = Environment.getSecureDataDirectory(); sSyncStorageEngine = new SyncStorageEngine(context, dataDir); } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 480504d..ae38af6 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -249,6 +249,16 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int FLAG_RESTORE_ANY_VERSION = 1<<17; /** + * Value for {@link #flags}: this is true if the application has set + * its android:neverEncrypt to true, false otherwise. It is used to specify + * that this package specifically "opts-out" of a secured file system solution, + * and will always store its data in-the-clear. + * + * {@hide} + */ + public static final int FLAG_NEVER_ENCRYPT = 1<<18; + + /** * Value for {@link #flags}: Set to true if the application has been * installed using the forward lock option. * diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 09a783d..fb52d2e 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1539,6 +1539,12 @@ public class PackageParser { ai.flags |= ApplicationInfo.FLAG_TEST_ONLY; } + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt, + false)) { + ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT; + } + String str; str = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestApplication_permission, 0); diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index eab1627..a9831aa 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -28,6 +28,8 @@ public class Environment { private static final File ROOT_DIRECTORY = getDirectory("ANDROID_ROOT", "/system"); + private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; + private static IMountService mMntSvc = null; /** @@ -37,9 +39,55 @@ public class Environment { 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/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index b3ec114..1b103aa 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -352,6 +352,23 @@ public class RecoverySystem { } /** + * Reboot into the recovery system to wipe the /data partition and toggle + * Encrypted File Systems on/off. + * @param extras to add to the RECOVERY_COMPLETED intent after rebooting. + * @throws IOException if something goes wrong. + * + * @hide + */ + public static void rebootToggleEFS(Context context, boolean efsEnabled) + throws IOException { + if (efsEnabled) { + bootCommand(context, "--set_encrypted_filesystem=on"); + } else { + bootCommand(context, "--set_encrypted_filesystem=off"); + } + } + + /** * Reboot into the recovery system with the supplied argument. * @param arg to pass to the recovery utility. * @throws IOException if something goes wrong. diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java index 7b883a7..d3d39d6 100644 --- a/core/java/android/os/storage/StorageEventListener.java +++ b/core/java/android/os/storage/StorageEventListener.java @@ -18,7 +18,6 @@ package android.os.storage; /** * Used for receiving notifications from the StorageManager - * @hide */ public abstract class StorageEventListener { /** diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index a12603c..b49979c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -45,8 +45,6 @@ import java.util.List; * {@link android.content.Context#getSystemService(java.lang.String)} with an argument * of {@link android.content.Context#STORAGE_SERVICE}. * - * @hide - * */ public class StorageManager diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java index 075f47f..07d95df 100644 --- a/core/java/android/os/storage/StorageResultCode.java +++ b/core/java/android/os/storage/StorageResultCode.java @@ -19,8 +19,6 @@ package android.os.storage; /** * Class that provides access to constants returned from StorageManager * and lower level MountService APIs. - * - * @hide */ public class StorageResultCode { diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index 23e2277..fa47ff6 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -30,7 +30,7 @@ import android.provider.Settings; import android.text.format.DateFormat; import android.util.AttributeSet; import android.view.View; -import android.widget.RelativeLayout; +import android.widget.LinearLayout; import android.widget.TextView; import java.text.DateFormatSymbols; @@ -39,7 +39,7 @@ import java.util.Calendar; /** * Displays the time */ -public class DigitalClock extends RelativeLayout { +public class DigitalClock extends LinearLayout { private final static String M12 = "h:mm"; private final static String M24 = "kk:mm"; diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml index a4b2357..b404955 100644 --- a/core/res/res/layout/keyguard_screen_tab_unlock.xml +++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml @@ -41,21 +41,20 @@ android:ellipsize="marquee" android:gravity="right|bottom" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="22sp" /> - <!-- "emergency calls only" shown when sim is missing or PUKd --> - <TextView - android:id="@+id/emergencyCallText" + <!-- emergency call button shown when sim is missing or PUKd --> + <Button + android:id="@+id/emergencyCallButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@id/carrier" + android:layout_alignParentTop="true" android:layout_alignParentRight="true" - android:layout_marginTop="0dip" + android:layout_marginTop="10dip" android:layout_marginRight="8dip" - android:text="@string/emergency_calls_only" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textColor="@color/white" + android:drawableLeft="@drawable/ic_emergency" + style="@style/Widget.Button.Transparent" + android:drawablePadding="8dip" /> <!-- time and date --> @@ -65,7 +64,6 @@ android:layout_below="@id/carrier" android:layout_marginTop="52dip" android:layout_marginLeft="20dip" - android:layout_marginBottom="8dip" > <TextView android:id="@+id/timeDisplay" @@ -73,6 +71,7 @@ android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="none" + android:gravity="bottom" android:textSize="72sp" android:textAppearance="?android:attr/textAppearanceMedium" android:shadowColor="#C0000000" @@ -85,9 +84,8 @@ <TextView android:id="@+id/am_pm" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/timeDisplay" - android:layout_alignBaseline="@id/timeDisplay" + android:layout_height="match_parent" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="22sp" diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml index e1c9772..6ee659c 100644 --- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml +++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml @@ -46,19 +46,18 @@ android:ellipsize="marquee" android:gravity="right|bottom" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="22sp" /> - <!-- "emergency calls only" shown when sim is missing or PUKd --> - <TextView - android:id="@+id/emergencyCallText" + <!-- emergency call button shown when sim is missing or PUKd --> + <Button + android:id="@+id/emergencyCallButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="20dip" - android:text="@string/emergency_calls_only" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textColor="@color/white" + android:drawableLeft="@drawable/ic_emergency" + style="@style/Widget.Button.Transparent" + android:drawablePadding="8dip" /> <com.android.internal.widget.DigitalClock android:id="@+id/time" @@ -66,12 +65,12 @@ android:layout_height="wrap_content" android:layout_below="@id/carrier" android:layout_marginTop="56dip" - android:layout_marginBottom="8dip" > <TextView android:id="@+id/timeDisplay" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="72sp" @@ -86,9 +85,8 @@ <TextView android:id="@+id/am_pm" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/timeDisplay" - android:layout_alignBaseline="@id/timeDisplay" + android:layout_height="match_parent" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="22sp" diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml index 83381a1..c1b406f 100644 --- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml +++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml @@ -58,19 +58,18 @@ android:ellipsize="marquee" android:gravity="right|bottom" /> - <com.android.internal.widget.DigitalClock android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_marginTop="8dip" - android:layout_marginBottom="8dip" > <TextView android:id="@+id/timeDisplay" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="72sp" @@ -85,9 +84,8 @@ <TextView android:id="@+id/am_pm" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/timeDisplay" - android:layout_alignBaseline="@id/timeDisplay" + android:layout_height="match_parent" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="22sp" diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml index 97c4ae9..16cd48c 100644 --- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml +++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml @@ -55,12 +55,12 @@ android:layout_alignParentTop="true" android:layout_marginTop="15dip" android:layout_marginLeft="20dip" - android:layout_marginBottom="8dip" > <TextView android:id="@+id/timeDisplay" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="56sp" @@ -74,9 +74,8 @@ <TextView android:id="@+id/am_pm" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/timeDisplay" - android:layout_alignBaseline="@id/timeDisplay" + android:layout_height="match_parent" + android:gravity="bottom" android:singleLine="true" android:ellipsize="none" android:textSize="18sp" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 959a9db..fc5edb3 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -79,6 +79,13 @@ by applications. --> <attr name="allowClearUserData" format="boolean" /> + <!-- Option to let applications specify that user data should + never be encrypted if an Encrypted File System solution + is enabled. Specifically, this is an "opt-out" feature, meaning + that, by default, user data will be encrypted if the EFS feature + is enabled. --> + <attr name="neverEncrypt" format="boolean" /> + <!-- Option to indicate this application is only for testing purposes. For example, it may expose functionality or data outside of itself that would cause a security hole, but is useful for testing. This @@ -712,6 +719,7 @@ <attr name="killAfterRestore" /> <attr name="restoreNeedsApplication" /> <attr name="restoreAnyVersion" /> + <attr name="neverEncrypt" /> </declare-styleable> <!-- The <code>permission</code> tag declares a security permission that can be diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml index d057ab7..dd0d064 100644 --- a/packages/SettingsProvider/AndroidManifest.xml +++ b/packages/SettingsProvider/AndroidManifest.xml @@ -8,6 +8,8 @@ android:backupAgent="SettingsBackupAgent" android:killAfterRestore="false" android:icon="@drawable/ic_launcher_settings"> + + <!-- todo add: 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 5672a01..eeafd5a 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java @@ -52,8 +52,11 @@ public class VpnServiceBinder extends Service { // 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() { - return Environment.getDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH; + // 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() { diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index ecf1a1d..818c785 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -421,7 +421,7 @@ class BackupManagerService extends IBackupManager.Stub { Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0; // If Encrypted file systems is enabled or disabled, this call will return the // correct directory. - mBaseStateDir = new File(Environment.getDataDirectory(), "backup"); + mBaseStateDir = new File(Environment.getSecureDataDirectory(), "backup"); mBaseStateDir.mkdirs(); mDataDir = Environment.getDownloadCacheDirectory(); diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/Installer.java index 2eaa58c..1f34eba 100644 --- a/services/java/com/android/server/Installer.java +++ b/services/java/com/android/server/Installer.java @@ -166,11 +166,17 @@ class Installer { } } - 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,33 +209,57 @@ class Installer { 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 rename(String oldname, String newname) { + public int rename(String oldname, String newname, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("rename"); builder.append(' '); builder.append(oldname); builder.append(' '); builder.append(newname); + 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()); } @@ -263,7 +293,7 @@ class Installer { } 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); @@ -271,6 +301,13 @@ class Installer { 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/MasterClearReceiver.java b/services/java/com/android/server/MasterClearReceiver.java index 27a8a74..4d04cee 100644 --- a/services/java/com/android/server/MasterClearReceiver.java +++ b/services/java/com/android/server/MasterClearReceiver.java @@ -39,7 +39,11 @@ public class MasterClearReceiver extends BroadcastReceiver { try { Slog.w(TAG, "!!! FACTORY RESET !!!"); - RecoverySystem.rebootWipeUserData(context); + if (intent.hasExtra("enableEFS")) { + RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false)); + } else { + RecoverySystem.rebootWipeUserData(context); + } Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 79b012b..33a824b 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -147,6 +147,8 @@ class PackageManagerService extends IPackageManager.Stub { 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 = @@ -199,6 +201,10 @@ class PackageManagerService extends IPackageManager.Stub { // 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; @@ -711,6 +717,7 @@ class PackageManagerService extends IPackageManager.Stub { File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); + mSecureAppDataDir = new File(dataDir, "secure/data"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); if (mInstaller == null) { @@ -720,6 +727,7 @@ class PackageManagerService extends IPackageManager.Stub { File miscDir = new File(dataDir, "misc"); miscDir.mkdirs(); mAppDataDir.mkdirs(); + mSecureAppDataDir.mkdirs(); mDrmAppPrivateInstallDir.mkdirs(); } @@ -880,7 +888,9 @@ class PackageManagerService extends IPackageManager.Stub { + " no longer exists; wiping its data"; reportSettingsProblem(Log.WARN, msg); if (mInstaller != null) { - mInstaller.remove(ps.name); + // XXX how to set useEncryptedFSDir for packages that + // are not encrypted? + mInstaller.remove(ps.name, true); } } } @@ -950,7 +960,8 @@ class PackageManagerService extends IPackageManager.Stub { void cleanupInstallFailedPackage(PackageSetting ps) { Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name); if (mInstaller != null) { - int retCode = mInstaller.remove(ps.name); + boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg); + int retCode = mInstaller.remove(ps.name, useSecureFS); if (retCode < 0) { Slog.w(TAG, "Couldn't remove app data directory for package: " + ps.name + ", retcode=" + retCode); @@ -2605,6 +2616,11 @@ class PackageManagerService extends IPackageManager.Stub { 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 boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) { if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { @@ -2622,7 +2638,14 @@ class PackageManagerService extends IPackageManager.Stub { } private File getDataPathForPackage(PackageParser.Package pkg) { - return new File(mAppDataDir, pkg.packageName); + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); + File dataPath; + if (useEncryptedFSDir) { + dataPath = new File(mSecureAppDataDir, pkg.packageName); + } else { + dataPath = new File(mAppDataDir, pkg.packageName); + } + return dataPath; } private PackageParser.Package scanPackageLI(PackageParser.Package pkg, @@ -2974,6 +2997,7 @@ class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); dataPath = getDataPathForPackage(pkg); boolean uidError = false; @@ -2990,7 +3014,7 @@ class PackageManagerService extends IPackageManager.Stub { // 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 @@ -3001,7 +3025,7 @@ class PackageManagerService extends IPackageManager.Stub { 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! @@ -3041,7 +3065,7 @@ class PackageManagerService extends IPackageManager.Stub { 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 @@ -6006,8 +6030,9 @@ class PackageManagerService extends IPackageManager.Stub { 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) { Slog.w(TAG, "Couldn't remove app data or cache directory for package: " + packageName + ", retcode=" + retCode); @@ -6246,6 +6271,7 @@ class PackageManagerService extends IPackageManager.Stub { p = ps.pkg; } } + boolean useEncryptedFSDir = false; if(!dataOnly) { //need to check this only for fully installed applications @@ -6258,9 +6284,10 @@ class PackageManagerService extends IPackageManager.Stub { Slog.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) { Slog.w(TAG, "Couldn't remove cache files for package: " + packageName); @@ -6311,8 +6338,9 @@ class PackageManagerService extends IPackageManager.Stub { Slog.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) { Slog.w(TAG, "Couldn't remove cache files for package: " + packageName); @@ -6374,9 +6402,10 @@ class PackageManagerService extends IPackageManager.Stub { } 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 { @@ -7510,7 +7539,8 @@ class PackageManagerService extends IPackageManager.Stub { void setFlags(int pkgFlags) { this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) | (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) | - (pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE); + (pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) | + (pkgFlags & ApplicationInfo.FLAG_NEVER_ENCRYPT); } } @@ -7768,11 +7798,17 @@ class PackageManagerService extends IPackageManager.Stub { 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"); mPackageListFilename = new File(systemDir, "packages.list"); diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java index ce522c8..ce40b5d 100644 --- a/vpn/java/android/net/vpn/VpnManager.java +++ b/vpn/java/android/net/vpn/VpnManager.java @@ -85,7 +85,8 @@ public class VpnManager { // TODO(oam): Test VPN when EFS is enabled (will do later)... public static String getProfilePath() { - return Environment.getDataDirectory().getPath() + PROFILES_PATH; + // This call will return the correct path if Encrypted FS is enabled or not. + return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH; } /** |
