From 606af94785cb96d418d87fe5a90bb2e09ccfa97f Mon Sep 17 00:00:00 2001 From: Yohann Roussel Date: Tue, 12 May 2015 17:40:52 +0200 Subject: Use Context.getFilesDir as a backup dex location On some devices it seems impossible to read or write the application data directory. There, creating code_cache at the proper location is impossible. In this case fallback to the 'files' directory. This may lead to not cleaning the useless extracted secondary dex files if one such devices is ever updated to L. Bug: https://code.google.com/p/android/issues/detail?id=79388 Change-Id: I4b6725572f10fd511992dc8a5043d2f135abd3a5 --- library/src/android/support/multidex/MultiDex.java | 43 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'library/src/android/support/multidex/MultiDex.java') diff --git a/library/src/android/support/multidex/MultiDex.java b/library/src/android/support/multidex/MultiDex.java index 8d5e1ab..1e04c19 100644 --- a/library/src/android/support/multidex/MultiDex.java +++ b/library/src/android/support/multidex/MultiDex.java @@ -60,8 +60,9 @@ public final class MultiDex { private static final String OLD_SECONDARY_FOLDER_NAME = "secondary-dexes"; - private static final String SECONDARY_FOLDER_NAME = "code_cache" + File.separator + - "secondary-dexes"; + private static final String CODE_CACHE_NAME = "code_cache"; + + private static final String CODE_CACHE_SECONDARY_FOLDER_NAME = "secondary-dexes"; private static final int MAX_SUPPORTED_SDK_VERSION = 20; @@ -155,7 +156,7 @@ public final class MultiDex { + "continuing without cleaning.", t); } - File dexDir = new File(applicationInfo.dataDir, SECONDARY_FOLDER_NAME); + File dexDir = getDexDir(context, applicationInfo); List files = MultiDexExtractor.load(context, applicationInfo, dexDir, false); if (checkValidZipFiles(files)) { installSecondaryDexes(loader, dexDir, files); @@ -363,6 +364,42 @@ public final class MultiDex { } } + private static File getDexDir(Context context, ApplicationInfo applicationInfo) + throws IOException { + File cache = new File(applicationInfo.dataDir, CODE_CACHE_NAME); + try { + mkdirChecked(cache); + } catch (IOException e) { + /* If we can't emulate code_cache, then store to filesDir. This means abandoning useless + * files on disk if the device ever updates to android 5+. But since this seems to + * happen only on some devices running android 2, this should cause no pollution. + */ + cache = new File(context.getFilesDir(), CODE_CACHE_NAME); + mkdirChecked(cache); + } + File dexDir = new File(cache, CODE_CACHE_SECONDARY_FOLDER_NAME); + mkdirChecked(dexDir); + return dexDir; + } + + private static void mkdirChecked(File dir) throws IOException { + dir.mkdir(); + if (!dir.isDirectory()) { + File parent = dir.getParentFile(); + if (parent == null) { + Log.e(TAG, "Failed to create dir " + dir.getPath() + ". Parent file is null."); + } else { + Log.e(TAG, "Failed to create dir " + dir.getPath() + + ". parent file is a dir " + parent.isDirectory() + + ", a file " + parent.isFile() + + ", exists " + parent.exists() + + ", readable " + parent.canRead() + + ", writable " + parent.canWrite()); + } + throw new IOException("Failed to create directory " + dir.getPath()); + } + } + /** * Installer for platform versions 19. */ -- cgit v1.2.3