Shift around encryption public APIs.
There are far too many Context APIs with special directory paths
to replicate device-encryption versions of them all. Instead, add
methods to clone a Context that explicitly stores its data in either
credential- or device-encrypted storage.
Methods to test the behavior of a given Context.
Bug: 22358539
Change-Id: I6a6290a9b282605ce9a1f82742fc2c4c50536754
diff --git a/api/current.txt b/api/current.txt
index 007ed13..0a1289a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7779,6 +7779,8 @@
method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public abstract deprecated void clearWallpaper() throws java.io.IOException;
method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public abstract android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public abstract android.content.Context createDeviceEncryptedContext(android.content.Context);
method public abstract android.content.Context createDisplayContext(android.view.Display);
method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.lang.String[] databaseList();
@@ -7802,7 +7804,6 @@
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();
@@ -7835,6 +7836,8 @@
method public abstract deprecated int getWallpaperDesiredMinimumHeight();
method public abstract deprecated int getWallpaperDesiredMinimumWidth();
method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public abstract boolean isCredentialEncrypted();
+ method public abstract boolean isDeviceEncrypted();
method public boolean isRestricted();
method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
@@ -7966,6 +7969,8 @@
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public deprecated void clearWallpaper() throws java.io.IOException;
method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public android.content.Context createDeviceEncryptedContext(android.content.Context);
method public android.content.Context createDisplayContext(android.view.Display);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
@@ -7988,7 +7993,6 @@
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();
@@ -8016,6 +8020,8 @@
method public deprecated int getWallpaperDesiredMinimumHeight();
method public deprecated int getWallpaperDesiredMinimumWidth();
method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public boolean isCredentialEncrypted();
+ method public boolean isDeviceEncrypted();
method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9097,8 +9103,10 @@
field public java.lang.String backupAgentName;
field public java.lang.String className;
field public int compatibleWidthLimitDp;
+ field public java.lang.String credentialEncryptedDataDir;
field public java.lang.String dataDir;
field public int descriptionRes;
+ field public java.lang.String deviceEncryptedDataDir;
field public boolean enabled;
field public int flags;
field public int largestWidthLimitDp;
@@ -36234,6 +36242,8 @@
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public void clearWallpaper();
method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public android.content.Context createDeviceEncryptedContext(android.content.Context);
method public android.content.Context createDisplayContext(android.view.Display);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
@@ -36255,7 +36265,6 @@
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();
@@ -36283,6 +36292,8 @@
method public int getWallpaperDesiredMinimumHeight();
method public int getWallpaperDesiredMinimumWidth();
method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public boolean isCredentialEncrypted();
+ method public boolean isDeviceEncrypted();
method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
diff --git a/api/system-current.txt b/api/system-current.txt
index 1a05551..29b6abd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8023,6 +8023,8 @@
method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public abstract deprecated void clearWallpaper() throws java.io.IOException;
method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public abstract android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public abstract android.content.Context createDeviceEncryptedContext(android.content.Context);
method public abstract android.content.Context createDisplayContext(android.view.Display);
method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.lang.String[] databaseList();
@@ -8045,9 +8047,7 @@
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();
@@ -8080,6 +8080,8 @@
method public abstract deprecated int getWallpaperDesiredMinimumHeight();
method public abstract deprecated int getWallpaperDesiredMinimumWidth();
method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public abstract boolean isCredentialEncrypted();
+ method public abstract boolean isDeviceEncrypted();
method public boolean isRestricted();
method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
@@ -8219,6 +8221,8 @@
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public deprecated void clearWallpaper() throws java.io.IOException;
method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public android.content.Context createDeviceEncryptedContext(android.content.Context);
method public android.content.Context createDisplayContext(android.view.Display);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
@@ -8240,9 +8244,7 @@
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();
@@ -8270,6 +8272,8 @@
method public deprecated int getWallpaperDesiredMinimumHeight();
method public deprecated int getWallpaperDesiredMinimumWidth();
method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public boolean isCredentialEncrypted();
+ method public boolean isDeviceEncrypted();
method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9361,8 +9365,10 @@
field public java.lang.String backupAgentName;
field public java.lang.String className;
field public int compatibleWidthLimitDp;
+ field public java.lang.String credentialEncryptedDataDir;
field public java.lang.String dataDir;
field public int descriptionRes;
+ field public java.lang.String deviceEncryptedDataDir;
field public boolean enabled;
field public int flags;
field public int largestWidthLimitDp;
@@ -38560,6 +38566,8 @@
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public void clearWallpaper();
method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public android.content.Context createDeviceEncryptedContext(android.content.Context);
method public android.content.Context createDisplayContext(android.view.Display);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
@@ -38580,9 +38588,7 @@
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();
@@ -38610,6 +38616,8 @@
method public int getWallpaperDesiredMinimumHeight();
method public int getWallpaperDesiredMinimumWidth();
method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public boolean isCredentialEncrypted();
+ method public boolean isDeviceEncrypted();
method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
diff --git a/api/test-current.txt b/api/test-current.txt
index 7be966e..02e081e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7779,6 +7779,8 @@
method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public abstract deprecated void clearWallpaper() throws java.io.IOException;
method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public abstract android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public abstract android.content.Context createDeviceEncryptedContext(android.content.Context);
method public abstract android.content.Context createDisplayContext(android.view.Display);
method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.lang.String[] databaseList();
@@ -7802,7 +7804,6 @@
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();
@@ -7835,6 +7836,8 @@
method public abstract deprecated int getWallpaperDesiredMinimumHeight();
method public abstract deprecated int getWallpaperDesiredMinimumWidth();
method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public abstract boolean isCredentialEncrypted();
+ method public abstract boolean isDeviceEncrypted();
method public boolean isRestricted();
method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
@@ -7966,6 +7969,8 @@
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public deprecated void clearWallpaper() throws java.io.IOException;
method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public android.content.Context createDeviceEncryptedContext(android.content.Context);
method public android.content.Context createDisplayContext(android.view.Display);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
@@ -7988,7 +7993,6 @@
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();
@@ -8016,6 +8020,8 @@
method public deprecated int getWallpaperDesiredMinimumHeight();
method public deprecated int getWallpaperDesiredMinimumWidth();
method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public boolean isCredentialEncrypted();
+ method public boolean isDeviceEncrypted();
method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9097,8 +9103,10 @@
field public java.lang.String backupAgentName;
field public java.lang.String className;
field public int compatibleWidthLimitDp;
+ field public java.lang.String credentialEncryptedDataDir;
field public java.lang.String dataDir;
field public int descriptionRes;
+ field public java.lang.String deviceEncryptedDataDir;
field public boolean enabled;
field public int flags;
field public int largestWidthLimitDp;
@@ -36236,6 +36244,8 @@
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public void clearWallpaper();
method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ method public android.content.Context createCredentialEncryptedContext(android.content.Context);
+ method public android.content.Context createDeviceEncryptedContext(android.content.Context);
method public android.content.Context createDisplayContext(android.view.Display);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
@@ -36257,7 +36267,6 @@
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();
@@ -36285,6 +36294,8 @@
method public int getWallpaperDesiredMinimumHeight();
method public int getWallpaperDesiredMinimumWidth();
method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ method public boolean isCredentialEncrypted();
+ method public boolean isDeviceEncrypted();
method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a703c53..36e98f9 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -74,6 +74,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Objects;
class ReceiverRestrictedContext extends ContextWrapper {
ReceiverRestrictedContext(Context base) {
@@ -148,7 +149,7 @@
private final Display mDisplay; // may be null if default display
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
- private final boolean mRestricted;
+ private final int mFlags;
private Context mOuterContext;
private int mThemeResource = 0;
@@ -443,22 +444,6 @@
}
@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) {
@@ -1684,9 +1669,8 @@
LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE);
if (pi != null) {
- final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
- new UserHandle(UserHandle.getUserId(application.uid)), restricted,
+ new UserHandle(UserHandle.getUserId(application.uid)), flags,
mDisplay, null, Display.INVALID_DISPLAY);
if (c.mResources != null) {
return c;
@@ -1707,17 +1691,16 @@
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws NameNotFoundException {
- final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
if (packageName.equals("system") || packageName.equals("android")) {
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
+ user, flags, mDisplay, null, Display.INVALID_DISPLAY);
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
if (pi != null) {
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
- user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
+ user, flags, mDisplay, null, Display.INVALID_DISPLAY);
if (c.mResources != null) {
return c;
}
@@ -1735,7 +1718,7 @@
}
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- mUser, mRestricted, mDisplay, overrideConfiguration, Display.INVALID_DISPLAY);
+ mUser, mFlags, mDisplay, overrideConfiguration, Display.INVALID_DISPLAY);
}
@Override
@@ -1745,7 +1728,7 @@
}
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- mUser, mRestricted, display, null, Display.INVALID_DISPLAY);
+ mUser, mFlags, display, null, Display.INVALID_DISPLAY);
}
Display getDisplay() {
@@ -1761,8 +1744,34 @@
}
@Override
+ public Context createDeviceEncryptedContext(Context context) {
+ final int flags = (mFlags & ~Context.CONTEXT_STORAGE_CREDENTIAL_ENCRYPTED)
+ | Context.CONTEXT_STORAGE_DEVICE_ENCRYPTED;
+ return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
+ mUser, flags, mDisplay, null, Display.INVALID_DISPLAY);
+ }
+
+ @Override
+ public Context createCredentialEncryptedContext(Context context) {
+ final int flags = (mFlags & ~Context.CONTEXT_STORAGE_DEVICE_ENCRYPTED)
+ | Context.CONTEXT_STORAGE_CREDENTIAL_ENCRYPTED;
+ return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
+ mUser, flags, mDisplay, null, Display.INVALID_DISPLAY);
+ }
+
+ @Override
public boolean isRestricted() {
- return mRestricted;
+ return (mFlags & Context.CONTEXT_RESTRICTED) != 0;
+ }
+
+ @Override
+ public boolean isDeviceEncrypted() {
+ return (mFlags & Context.CONTEXT_STORAGE_DEVICE_ENCRYPTED) != 0;
+ }
+
+ @Override
+ public boolean isCredentialEncrypted() {
+ return (mFlags & Context.CONTEXT_STORAGE_CREDENTIAL_ENCRYPTED) != 0;
}
@Override
@@ -1772,7 +1781,14 @@
private File getDataDirFile() {
if (mPackageInfo != null) {
- return mPackageInfo.getDataDirFile();
+ if (isCredentialEncrypted()) {
+ return mPackageInfo.getCredentialEncryptedDataDirFile();
+ } else if (isDeviceEncrypted()) {
+ return mPackageInfo.getDeviceEncryptedDataDirFile();
+ } else {
+ throw new RuntimeException(
+ "Storage location is neither credential nor device encrypted");
+ }
}
throw new RuntimeException("Not supported in system context");
}
@@ -1798,7 +1814,7 @@
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread,
- packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
+ packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetricsLocked());
return context;
@@ -1807,24 +1823,38 @@
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
- packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
+ packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
}
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
- return new ContextImpl(null, mainThread, packageInfo, null, null, false,
+ return new ContextImpl(null, mainThread, packageInfo, null, null, 0,
null, overrideConfiguration, displayId);
}
private ContextImpl(ContextImpl container, ActivityThread mainThread,
- LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
+ LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
Display display, Configuration overrideConfiguration, int createDisplayWithId) {
mOuterContext = this;
+ // If creator didn't specify which storage to use, use the default
+ // location for application.
+ if ((flags & Context.CONTEXT_STORAGE_MASK) == 0) {
+ final File dataDir = packageInfo.getDataDirFile();
+ if (Objects.equals(dataDir, packageInfo.getCredentialEncryptedDataDirFile())) {
+ flags |= Context.CONTEXT_STORAGE_CREDENTIAL_ENCRYPTED;
+ } else if (Objects.equals(dataDir, packageInfo.getDeviceEncryptedDataDirFile())) {
+ flags |= Context.CONTEXT_STORAGE_DEVICE_ENCRYPTED;
+ } else {
+ throw new IllegalStateException("Storage location " + dataDir
+ + " doesn't match either credential or device encrypted storage");
+ }
+ }
+
mMainThread = mainThread;
mActivityToken = activityToken;
- mRestricted = restricted;
+ mFlags = flags;
if (user == null) {
user = Process.myUserHandle();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4c7e853..1f7fd9d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -771,27 +771,6 @@
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
@@ -3886,6 +3865,26 @@
public static final int CONTEXT_RESTRICTED = 0x00000004;
/**
+ * Flag for use with {@link #createPackageContext}: point all file APIs at
+ * device-encrypted storage.
+ *
+ * @hide
+ */
+ public static final int CONTEXT_STORAGE_DEVICE_ENCRYPTED = 0x00000008;
+
+ /**
+ * Flag for use with {@link #createPackageContext}: point all file APIs at
+ * credential-encrypted storage.
+ *
+ * @hide
+ */
+ public static final int CONTEXT_STORAGE_CREDENTIAL_ENCRYPTED = 0x00000010;
+
+ /** {@hide} */
+ public static final int CONTEXT_STORAGE_MASK = CONTEXT_STORAGE_DEVICE_ENCRYPTED
+ | CONTEXT_STORAGE_CREDENTIAL_ENCRYPTED;
+
+ /**
* @hide Used to indicate we should tell the activity manager about the process
* loading this code.
*/
@@ -3985,6 +3984,42 @@
public abstract Context createDisplayContext(@NonNull Display display);
/**
+ * Return a new Context object for the current Context but whose storage
+ * APIs are backed by device-encrypted storage.
+ * <p>
+ * Data stored in device-encrypted storage is 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).
+ * <p>
+ * Each call to this method returns a new instance of a Context object;
+ * Context objects are not shared, however common state (ClassLoader, other
+ * Resources for the same configuration) may be so the Context itself can be
+ * fairly lightweight.
+ *
+ * @see #isDeviceEncrypted()
+ */
+ public abstract Context createDeviceEncryptedContext(Context context);
+
+ /**
+ * Return a new Context object for the current Context but whose storage
+ * APIs are backed by credential-encrypted storage.
+ * <p>
+ * Data stored in credential-encrypted storage is 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).
+ * <p>
+ * Each call to this method returns a new instance of a Context object;
+ * Context objects are not shared, however common state (ClassLoader, other
+ * Resources for the same configuration) may be so the Context itself can be
+ * fairly lightweight.
+ *
+ * @see #isCredentialEncrypted()
+ */
+ public abstract Context createCredentialEncryptedContext(Context context);
+
+ /**
* Gets the display adjustments holder for this context. This information
* is provided on a per-application or activity basis and is used to simulate lower density
* display metrics for legacy applications and restricted screen sizes.
@@ -4005,4 +4040,20 @@
public boolean isRestricted() {
return false;
}
+
+ /**
+ * Indicates if the storage APIs of this Context are backed by
+ * device-encrypted storage.
+ *
+ * @see #createDeviceEncryptedContext(Context)
+ */
+ public abstract boolean isDeviceEncrypted();
+
+ /**
+ * Indicates if the storage APIs of this Context are backed by
+ * credential-encrypted storage.
+ *
+ * @see #createCredentialEncryptedContext(Context)
+ */
+ public abstract boolean isCredentialEncrypted();
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index f5e9159..73d0ddc 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -208,18 +208,6 @@
}
@Override
- public File getDeviceEncryptedFilesDir() {
- return mBase.getDeviceEncryptedFilesDir();
- }
-
- /** {@hide} */
- @SystemApi
- @Override
- public File getCredentialEncryptedFilesDir() {
- return mBase.getCredentialEncryptedFilesDir();
- }
-
- @Override
public File getNoBackupFilesDir() {
return mBase.getNoBackupFilesDir();
}
@@ -802,4 +790,24 @@
public DisplayAdjustments getDisplayAdjustments(int displayId) {
return mBase.getDisplayAdjustments(displayId);
}
+
+ @Override
+ public Context createDeviceEncryptedContext(Context context) {
+ return mBase.createDeviceEncryptedContext(context);
+ }
+
+ @Override
+ public Context createCredentialEncryptedContext(Context context) {
+ return mBase.createCredentialEncryptedContext(context);
+ }
+
+ @Override
+ public boolean isDeviceEncrypted() {
+ return mBase.isDeviceEncrypted();
+ }
+
+ @Override
+ public boolean isCredentialEncrypted() {
+ return mBase.isCredentialEncrypted();
+ }
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 545478c..4816734 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -591,13 +591,21 @@
public String[] sharedLibraryFiles;
/**
- * Full path to a directory assigned to the package for its persistent data.
+ * Full path to the default directory assigned to the package for its
+ * persistent data.
*/
public String dataDir;
- /** {@hide} */
+ /**
+ * Full path to the device-encrypted directory assigned to the package for
+ * its persistent data.
+ */
public String deviceEncryptedDataDir;
- /** {@hide} */
+
+ /**
+ * Full path to the credential-encrypted directory assigned to the package
+ * for its persistent data.
+ */
public String credentialEncryptedDataDir;
/**
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 225edf8..4c3b598 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -181,18 +181,6 @@
}
@Override
- public File getDeviceEncryptedFilesDir() {
- throw new UnsupportedOperationException();
- }
-
- /** {@hide} */
- @SystemApi
- @Override
- public File getCredentialEncryptedFilesDir() {
- throw new UnsupportedOperationException();
- }
-
- @Override
public File getNoBackupFilesDir() {
throw new UnsupportedOperationException();
}
@@ -705,4 +693,24 @@
public File[] getExternalMediaDirs() {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public Context createDeviceEncryptedContext(Context context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Context createCredentialEncryptedContext(Context context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isDeviceEncrypted() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isCredentialEncrypted() {
+ 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 9214759..bd5335e 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
@@ -1377,18 +1377,6 @@
}
@Override
- public File getDeviceEncryptedFilesDir() {
- // pass
- return null;
- }
-
- @Override
- public File getCredentialEncryptedFilesDir() {
- // pass
- return null;
- }
-
- @Override
public File getNoBackupFilesDir() {
// pass
return null;
@@ -1814,4 +1802,26 @@
Integer pos = mScrollYPos.get(view);
return pos != null ? pos : 0;
}
+
+ @Override
+ public Context createDeviceEncryptedContext(Context context) {
+ // pass
+ return null;
+ }
+
+ @Override
+ public Context createCredentialEncryptedContext(Context context) {
+ // pass
+ return null;
+ }
+
+ @Override
+ public boolean isDeviceEncrypted() {
+ return false;
+ }
+
+ @Override
+ public boolean isCredentialEncrypted() {
+ return false;
+ }
}