Initial file-based encryption public APIs.
Define two explicit directories where device-encrypted and
credential-encrypted data will be stored. Third-party apps only
need access to the device-encrypted directory, so that's the only
API exposed for now.
General cleanup in how ApplicationInfo details are derived.
Bug: 22358539
Change-Id: If0a0108721a4aa1c3052b4912e08604bbf24e1ae
diff --git a/api/current.txt b/api/current.txt
index 73b522f..d330dad 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7739,6 +7739,7 @@
method public final android.content.res.ColorStateList getColorStateList(int);
method public abstract android.content.ContentResolver getContentResolver();
method public abstract java.io.File getDatabasePath(java.lang.String);
+ method public abstract java.io.File getDeviceEncryptedFilesDir();
method public abstract java.io.File getDir(java.lang.String, int);
method public final android.graphics.drawable.Drawable getDrawable(int);
method public abstract java.io.File getExternalCacheDir();
@@ -7921,6 +7922,7 @@
method public java.io.File getCodeCacheDir();
method public android.content.ContentResolver getContentResolver();
method public java.io.File getDatabasePath(java.lang.String);
+ method public java.io.File getDeviceEncryptedFilesDir();
method public java.io.File getDir(java.lang.String, int);
method public java.io.File getExternalCacheDir();
method public java.io.File[] getExternalCacheDirs();
@@ -31932,6 +31934,7 @@
method public java.io.File getCodeCacheDir();
method public android.content.ContentResolver getContentResolver();
method public java.io.File getDatabasePath(java.lang.String);
+ method public java.io.File getDeviceEncryptedFilesDir();
method public java.io.File getDir(java.lang.String, int);
method public java.io.File getExternalCacheDir();
method public java.io.File[] getExternalCacheDirs();
diff --git a/api/system-current.txt b/api/system-current.txt
index 87932ac..f101856 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7980,7 +7980,9 @@
method public final int getColor(int);
method public final android.content.res.ColorStateList getColorStateList(int);
method public abstract android.content.ContentResolver getContentResolver();
+ method public abstract java.io.File getCredentialEncryptedFilesDir();
method public abstract java.io.File getDatabasePath(java.lang.String);
+ method public abstract java.io.File getDeviceEncryptedFilesDir();
method public abstract java.io.File getDir(java.lang.String, int);
method public final android.graphics.drawable.Drawable getDrawable(int);
method public abstract java.io.File getExternalCacheDir();
@@ -8170,7 +8172,9 @@
method public java.lang.ClassLoader getClassLoader();
method public java.io.File getCodeCacheDir();
method public android.content.ContentResolver getContentResolver();
+ method public java.io.File getCredentialEncryptedFilesDir();
method public java.io.File getDatabasePath(java.lang.String);
+ method public java.io.File getDeviceEncryptedFilesDir();
method public java.io.File getDir(java.lang.String, int);
method public java.io.File getExternalCacheDir();
method public java.io.File[] getExternalCacheDirs();
@@ -34237,7 +34241,9 @@
method public java.lang.ClassLoader getClassLoader();
method public java.io.File getCodeCacheDir();
method public android.content.ContentResolver getContentResolver();
+ method public java.io.File getCredentialEncryptedFilesDir();
method public java.io.File getDatabasePath(java.lang.String);
+ method public java.io.File getDeviceEncryptedFilesDir();
method public java.io.File getDir(java.lang.String, int);
method public java.io.File getExternalCacheDir();
method public java.io.File[] getExternalCacheDirs();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a74f528..b3d6382 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4834,13 +4834,7 @@
// Continue loading instrumentation.
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
- instrApp.packageName = ii.packageName;
- instrApp.sourceDir = ii.sourceDir;
- instrApp.publicSourceDir = ii.publicSourceDir;
- instrApp.splitSourceDirs = ii.splitSourceDirs;
- instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
- instrApp.dataDir = ii.dataDir;
- instrApp.nativeLibraryDir = ii.nativeLibraryDir;
+ ii.copyTo(instrApp);
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index fca5567..bc7c3d0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -443,6 +443,22 @@
}
@Override
+ public File getDeviceEncryptedFilesDir() {
+ if (mPackageInfo != null) {
+ return mPackageInfo.getDeviceEncryptedDataDirFile();
+ }
+ throw new RuntimeException("Not supported in system context");
+ }
+
+ @Override
+ public File getCredentialEncryptedFilesDir() {
+ if (mPackageInfo != null) {
+ return mPackageInfo.getCredentialEncryptedDataDirFile();
+ }
+ throw new RuntimeException("Not supported in system context");
+ }
+
+ @Override
public File getNoBackupFilesDir() {
synchronized (mSync) {
if (mNoBackupFilesDir == null) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index c2bf28a..8b7abb7 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -31,6 +31,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Resources;
import android.os.Bundle;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
@@ -93,6 +94,8 @@
private final String mDataDir;
private final String mLibDir;
private final File mDataDirFile;
+ private final File mDeviceEncryptedDataDirFile;
+ private final File mCredentialEncryptedDataDirFile;
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
private final boolean mIncludeCode;
@@ -139,7 +142,9 @@
mOverlayDirs = aInfo.resourceDirs;
mSharedLibraries = aInfo.sharedLibraryFiles;
mDataDir = aInfo.dataDir;
- mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
+ mDataDirFile = FileUtils.newFileOrNull(mDataDir);
+ mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
+ mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
mLibDir = aInfo.nativeLibraryDir;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
@@ -192,6 +197,8 @@
mSharedLibraries = null;
mDataDir = null;
mDataDirFile = null;
+ mDeviceEncryptedDataDirFile = null;
+ mCredentialEncryptedDataDirFile = null;
mLibDir = null;
mBaseClassLoader = null;
mSecurityViolation = false;
@@ -539,6 +546,14 @@
return mDataDirFile;
}
+ public File getDeviceEncryptedDataDirFile() {
+ return mDeviceEncryptedDataDirFile;
+ }
+
+ public File getCredentialEncryptedDataDirFile() {
+ return mCredentialEncryptedDataDirFile;
+ }
+
public AssetManager getAssets(ActivityThread mainThread) {
return getResources(mainThread).getAssets();
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3f02f17..a0102b6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -724,6 +724,27 @@
public abstract File getFilesDir();
/**
+ * Return the filesystem directory for storing device-encrypted private app
+ * data. Files stored in this location are typically encrypted with a key
+ * tied to the physical device, and they can be accessed whenever the device
+ * has booted successfully, both <em>before and after</em> the user has
+ * entered their credentials (such as a lock pattern or PIN).
+ */
+ public abstract File getDeviceEncryptedFilesDir();
+
+ /**
+ * Return the filesystem directory for storing credential-encrypted private
+ * app data. Files stored in this location are typically encrypted with a
+ * key tied to user credentials, and they can be accessed
+ * <em>only after</em> the user has entered their credentials (such as a
+ * lock pattern or PIN).
+ *
+ * @hide
+ */
+ @SystemApi
+ public abstract File getCredentialEncryptedFilesDir();
+
+ /**
* Returns the absolute path to the directory on the filesystem similar to
* {@link #getFilesDir()}. The difference is that files placed under this
* directory will be excluded from automatic backup to remote storage. See
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 8359edf..bec1b37 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -204,6 +204,18 @@
}
@Override
+ public File getDeviceEncryptedFilesDir() {
+ return mBase.getDeviceEncryptedFilesDir();
+ }
+
+ /** {@hide} */
+ @SystemApi
+ @Override
+ public File getCredentialEncryptedFilesDir() {
+ return mBase.getCredentialEncryptedFilesDir();
+ }
+
+ @Override
public File getNoBackupFilesDir() {
return mBase.getNoBackupFilesDir();
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 914945b..6bc2ac3 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -19,8 +19,10 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Printer;
@@ -459,6 +461,14 @@
public static final int PRIVATE_FLAG_HAS_DOMAIN_URLS = 1<<4;
/**
+ * When set, default data storage directory for given app is pointed at
+ * device-encrypted location.
+ *
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_DEVICE_ENCRYPTED = 1 << 5;
+
+ /**
* Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
* {@hide}
*/
@@ -549,11 +559,15 @@
public String[] sharedLibraryFiles;
/**
- * Full path to a directory assigned to the package for its persistent
- * data.
+ * Full path to a directory assigned to the package for its persistent data.
*/
public String dataDir;
+ /** {@hide} */
+ public String deviceEncryptedDataDir;
+ /** {@hide} */
+ public String credentialEncryptedDataDir;
+
/**
* Full path to the directory where native JNI libraries are stored.
*/
@@ -690,6 +704,8 @@
pw.println(prefix + "seinfo=" + seinfo);
}
pw.println(prefix + "dataDir=" + dataDir);
+ pw.println(prefix + "deviceEncryptedDataDir=" + deviceEncryptedDataDir);
+ pw.println(prefix + "credentialEncryptedDataDir=" + credentialEncryptedDataDir);
if (sharedLibraryFiles != null) {
pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
}
@@ -776,6 +792,8 @@
seinfo = orig.seinfo;
sharedLibraryFiles = orig.sharedLibraryFiles;
dataDir = orig.dataDir;
+ deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
+ credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
uid = orig.uid;
targetSdkVersion = orig.targetSdkVersion;
versionCode = orig.versionCode;
@@ -789,7 +807,6 @@
fullBackupContent = orig.fullBackupContent;
}
-
public String toString() {
return "ApplicationInfo{"
+ Integer.toHexString(System.identityHashCode(this))
@@ -829,6 +846,8 @@
dest.writeString(seinfo);
dest.writeStringArray(sharedLibraryFiles);
dest.writeString(dataDir);
+ dest.writeString(deviceEncryptedDataDir);
+ dest.writeString(credentialEncryptedDataDir);
dest.writeInt(uid);
dest.writeInt(targetSdkVersion);
dest.writeInt(versionCode);
@@ -881,6 +900,8 @@
seinfo = source.readString();
sharedLibraryFiles = source.readStringArray();
dataDir = source.readString();
+ deviceEncryptedDataDir = source.readString();
+ credentialEncryptedDataDir = source.readString();
uid = source.readInt();
targetSdkVersion = source.readInt();
versionCode = source.readInt();
@@ -925,7 +946,30 @@
FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS |
FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
}
-
+
+ /** {@hide} */
+ public void initForUser(int userId) {
+ uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
+
+ if ("android".equals(packageName)) {
+ dataDir = Environment.getDataSystemDirectory().getAbsolutePath();
+ return;
+ }
+
+ deviceEncryptedDataDir = Environment
+ .getDataUserDeviceEncryptedPackageDirectory(volumeUuid, userId, packageName)
+ .getAbsolutePath();
+ credentialEncryptedDataDir = Environment
+ .getDataUserCredentialEncryptedPackageDirectory(volumeUuid, userId, packageName)
+ .getAbsolutePath();
+
+ if ((privateFlags & PRIVATE_FLAG_DEVICE_ENCRYPTED) != 0) {
+ dataDir = deviceEncryptedDataDir;
+ } else {
+ dataDir = credentialEncryptedDataDir;
+ }
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index dab0caf..44bdf4e 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -57,11 +57,15 @@
public String[] splitPublicSourceDirs;
/**
- * Full path to a directory assigned to the package for its persistent
- * data.
+ * Full path to a directory assigned to the package for its persistent data.
*/
public String dataDir;
+ /** {@hide} */
+ public String deviceEncryptedDataDir;
+ /** {@hide} */
+ public String credentialEncryptedDataDir;
+
/**
* Full path to the directory where the native JNI libraries are stored.
*
@@ -85,7 +89,11 @@
targetPackage = orig.targetPackage;
sourceDir = orig.sourceDir;
publicSourceDir = orig.publicSourceDir;
+ splitSourceDirs = orig.splitSourceDirs;
+ splitPublicSourceDirs = orig.splitPublicSourceDirs;
dataDir = orig.dataDir;
+ deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
+ credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
nativeLibraryDir = orig.nativeLibraryDir;
handleProfiling = orig.handleProfiling;
functionalTest = orig.functionalTest;
@@ -106,7 +114,11 @@
dest.writeString(targetPackage);
dest.writeString(sourceDir);
dest.writeString(publicSourceDir);
+ dest.writeStringArray(splitSourceDirs);
+ dest.writeStringArray(splitPublicSourceDirs);
dest.writeString(dataDir);
+ dest.writeString(deviceEncryptedDataDir);
+ dest.writeString(credentialEncryptedDataDir);
dest.writeString(nativeLibraryDir);
dest.writeInt((handleProfiling == false) ? 0 : 1);
dest.writeInt((functionalTest == false) ? 0 : 1);
@@ -127,9 +139,26 @@
targetPackage = source.readString();
sourceDir = source.readString();
publicSourceDir = source.readString();
+ splitSourceDirs = source.readStringArray();
+ splitPublicSourceDirs = source.readStringArray();
dataDir = source.readString();
+ deviceEncryptedDataDir = source.readString();
+ credentialEncryptedDataDir = source.readString();
nativeLibraryDir = source.readString();
handleProfiling = source.readInt() != 0;
functionalTest = source.readInt() != 0;
}
+
+ /** {@hide} */
+ public void copyTo(ApplicationInfo ai) {
+ ai.packageName = packageName;
+ ai.sourceDir = sourceDir;
+ ai.publicSourceDir = publicSourceDir;
+ ai.splitSourceDirs = splitSourceDirs;
+ ai.splitPublicSourceDirs = splitPublicSourceDirs;
+ ai.dataDir = dataDir;
+ ai.deviceEncryptedDataDir = deviceEncryptedDataDir;
+ ai.credentialEncryptedDataDir = credentialEncryptedDataDir;
+ ai.nativeLibraryDir = nativeLibraryDir;
+ }
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5d73b06..20e76d6 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4875,9 +4875,7 @@
// Make shallow copy so we can store the metadata/libraries safely
ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
- ai.uid = UserHandle.getUid(userId, ai.uid);
- ai.dataDir = Environment.getDataUserPackageDirectory(ai.volumeUuid, userId, ai.packageName)
- .getAbsolutePath();
+ ai.initForUser(userId);
if ((flags & PackageManager.GET_META_DATA) != 0) {
ai.metaData = p.mAppMetaData;
}
@@ -4902,9 +4900,7 @@
// This is only used to return the ResolverActivity; we will just always
// make a copy.
ai = new ApplicationInfo(ai);
- ai.uid = UserHandle.getUid(userId, ai.uid);
- ai.dataDir = Environment.getDataUserPackageDirectory(ai.volumeUuid, userId, ai.packageName)
- .getAbsolutePath();
+ ai.initForUser(userId);
if (state.stopped) {
ai.flags |= ApplicationInfo.FLAG_STOPPED;
} else {
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f346fe7..53627fc 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -35,6 +35,7 @@
private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
private static final String ENV_ANDROID_DATA = "ANDROID_DATA";
private static final String ENV_ANDROID_STORAGE = "ANDROID_STORAGE";
+ private static final String ENV_DOWNLOAD_CACHE = "DOWNLOAD_CACHE";
private static final String ENV_OEM_ROOT = "OEM_ROOT";
private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
@@ -53,11 +54,10 @@
private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
+ private static final File DIR_DOWNLOAD_CACHE = getDirectory(ENV_DOWNLOAD_CACHE, "/cache");
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
- private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
-
private static UserEnvironment sCurrentUser;
private static boolean sUserRequired;
@@ -164,34 +164,16 @@
return DIR_VENDOR_ROOT;
}
- /**
- * 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
- */
+ /** {@hide} */
+ @Deprecated
public static File getSystemSecureDirectory() {
- if (isEncryptedFilesystemEnabled()) {
- return new File(SECURE_DATA_DIRECTORY, "system");
- } else {
- return new File(DATA_DIRECTORY, "system");
- }
+ return getDataSystemDirectory();
}
- /**
- * 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
- */
+ /** {@hide} */
+ @Deprecated
public static File getSecureDataDirectory() {
- if (isEncryptedFilesystemEnabled()) {
- return SECURE_DATA_DIRECTORY;
- } else {
- return DATA_DIRECTORY;
- }
+ return getDataDirectory();
}
/**
@@ -202,7 +184,7 @@
* @hide
*/
public static File getUserSystemDirectory(int userId) {
- return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId));
+ return new File(new File(getDataSystemDirectory(), "users"), Integer.toString(userId));
}
/**
@@ -217,62 +199,93 @@
}
/**
- * 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 DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache");
-
- /**
* Return the user data directory.
*/
public static File getDataDirectory() {
- return DATA_DIRECTORY;
+ return DIR_ANDROID_DATA;
}
/** {@hide} */
public static File getDataDirectory(String volumeUuid) {
if (TextUtils.isEmpty(volumeUuid)) {
- return new File("/data");
+ return DIR_ANDROID_DATA;
} else {
return new File("/mnt/expand/" + volumeUuid);
}
}
/** {@hide} */
+ public static File getDataSystemDirectory() {
+ return new File(getDataDirectory(), "system");
+ }
+
+ /** {@hide} */
+ public static File getDataSystemCredentialEncryptedDirectory() {
+ return new File(getDataDirectory(), "system_ce");
+ }
+
+ /** {@hide} */
+ public static File getDataSystemCredentialEncryptedDirectory(int userId) {
+ return new File(getDataSystemCredentialEncryptedDirectory(), String.valueOf(userId));
+ }
+
+ /** {@hide} */
public static File getDataAppDirectory(String volumeUuid) {
return new File(getDataDirectory(volumeUuid), "app");
}
/** {@hide} */
+ @Deprecated
public static File getDataUserDirectory(String volumeUuid) {
+ return getDataUserCredentialEncryptedDirectory(volumeUuid);
+ }
+
+ /** {@hide} */
+ @Deprecated
+ public static File getDataUserDirectory(String volumeUuid, int userId) {
+ return getDataUserCredentialEncryptedDirectory(volumeUuid, userId);
+ }
+
+ /** {@hide} */
+ @Deprecated
+ public static File getDataUserPackageDirectory(String volumeUuid, int userId,
+ String packageName) {
+ return getDataUserCredentialEncryptedPackageDirectory(volumeUuid, userId, packageName);
+ }
+
+ /** {@hide} */
+ public static File getDataUserCredentialEncryptedDirectory(String volumeUuid) {
return new File(getDataDirectory(volumeUuid), "user");
}
/** {@hide} */
- public static File getDataUserDirectory(String volumeUuid, int userId) {
- return new File(getDataUserDirectory(volumeUuid), String.valueOf(userId));
+ public static File getDataUserCredentialEncryptedDirectory(String volumeUuid, int userId) {
+ return new File(getDataUserCredentialEncryptedDirectory(volumeUuid),
+ String.valueOf(userId));
}
/** {@hide} */
- public static File getDataUserPackageDirectory(String volumeUuid, int userId,
+ public static File getDataUserCredentialEncryptedPackageDirectory(String volumeUuid, int userId,
String packageName) {
// TODO: keep consistent with installd
- return new File(getDataUserDirectory(volumeUuid, userId), packageName);
+ return new File(getDataUserCredentialEncryptedDirectory(volumeUuid, userId), packageName);
+ }
+
+ /** {@hide} */
+ public static File getDataUserDeviceEncryptedDirectory(String volumeUuid) {
+ return new File(getDataDirectory(volumeUuid), "user_de");
+ }
+
+ /** {@hide} */
+ public static File getDataUserDeviceEncryptedDirectory(String volumeUuid, int userId) {
+ return new File(getDataUserDeviceEncryptedDirectory(volumeUuid), String.valueOf(userId));
+ }
+
+ /** {@hide} */
+ public static File getDataUserDeviceEncryptedPackageDirectory(String volumeUuid, int userId,
+ String packageName) {
+ // TODO: keep consistent with installd
+ return new File(getDataUserDeviceEncryptedDirectory(volumeUuid, userId), packageName);
}
/**
@@ -539,7 +552,7 @@
* Return the download/cache content directory.
*/
public static File getDownloadCacheDirectory() {
- return DOWNLOAD_CACHE_DIRECTORY;
+ return DIR_DOWNLOAD_CACHE;
}
/**
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index af4c2bc..b73d81e 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.provider.DocumentsContract.Document;
import android.system.ErrnoException;
import android.system.Os;
@@ -646,4 +647,8 @@
return EMPTY;
}
}
+
+ public static @Nullable File newFileOrNull(@Nullable String path) {
+ return (path != null) ? new File(path) : null;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e13d3e7..13401cd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -20032,17 +20032,10 @@
mUserController.unregisterUserSwitchObserver(observer);
}
- private int applyUserId(int uid, int userId) {
- return UserHandle.getUid(userId, uid);
- }
-
ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
if (info == null) return null;
ApplicationInfo newInfo = new ApplicationInfo(info);
- newInfo.uid = applyUserId(info.uid, userId);
- newInfo.dataDir = Environment
- .getDataUserPackageDirectory(info.volumeUuid, userId, info.packageName)
- .getAbsolutePath();
+ newInfo.initForUser(userId);
return newInfo;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bbbe67c..11fa38c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2951,9 +2951,8 @@
pkg.applicationInfo.packageName = packageName;
pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
pkg.applicationInfo.privateFlags = ps.pkgPrivateFlags;
- pkg.applicationInfo.dataDir = Environment
- .getDataUserPackageDirectory(ps.volumeUuid, userId, packageName)
- .getAbsolutePath();
+ pkg.applicationInfo.uid = ps.appId;
+ pkg.applicationInfo.initForUser(userId);
pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;
pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;
}
@@ -6944,17 +6943,10 @@
pkg.applicationInfo.processName,
pkg.applicationInfo.uid);
- File dataPath;
- if (mPlatformPackage == pkg) {
- // The system package is special.
- dataPath = new File(Environment.getDataDirectory(), "system");
-
- pkg.applicationInfo.dataDir = dataPath.getPath();
-
- } else {
+ if (pkg != mPlatformPackage) {
// This is a normal package, need to make its data directory.
- dataPath = Environment.getDataUserPackageDirectory(pkg.volumeUuid,
- UserHandle.USER_SYSTEM, pkg.packageName);
+ final File dataPath = Environment.getDataUserCredentialEncryptedPackageDirectory(
+ pkg.volumeUuid, UserHandle.USER_SYSTEM, pkg.packageName);
boolean uidError = false;
if (dataPath.exists()) {
@@ -7043,7 +7035,7 @@
}
}
}
- pkg.applicationInfo.dataDir = dataPath.getPath();
+
if (mShouldRestoreconData) {
Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
mInstaller.restoreconData(pkg.volumeUuid, pkg.packageName,
@@ -7062,15 +7054,11 @@
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Unable to create data dirs [errorCode=" + ret + "]");
}
-
- if (dataPath.exists()) {
- pkg.applicationInfo.dataDir = dataPath.getPath();
- } else {
- Slog.w(TAG, "Unable to create data directory: " + dataPath);
- pkg.applicationInfo.dataDir = null;
- }
}
+ // Get all of our default paths setup
+ pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
+
pkgSetting.uidError = uidError;
}
@@ -7624,6 +7612,8 @@
a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
a.info.dataDir = pkg.applicationInfo.dataDir;
+ a.info.deviceEncryptedDataDir = pkg.applicationInfo.deviceEncryptedDataDir;
+ a.info.credentialEncryptedDataDir = pkg.applicationInfo.credentialEncryptedDataDir;
// TODO: Update instrumentation.nativeLibraryDir as well ? Does it
// need other information about the application, like the ABI and what not ?
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index e09d124..4821678 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -177,6 +177,18 @@
}
@Override
+ public File getDeviceEncryptedFilesDir() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@hide} */
+ @SystemApi
+ @Override
+ public File getCredentialEncryptedFilesDir() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public File getNoBackupFilesDir() {
throw new UnsupportedOperationException();
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 4a5702d..0fcfa78 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1371,6 +1371,18 @@
}
@Override
+ public File getDeviceEncryptedFilesDir() {
+ // pass
+ return null;
+ }
+
+ @Override
+ public File getCredentialEncryptedFilesDir() {
+ // pass
+ return null;
+ }
+
+ @Override
public File getNoBackupFilesDir() {
// pass
return null;