diff options
author | Yohann Roussel <yroussel@google.com> | 2014-06-26 13:33:15 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-06-24 06:38:28 +0000 |
commit | 591acd99f16989233ff3e226546272bb60024559 (patch) | |
tree | fe9523df46a9b77c8fcce98070ea822d01fbde69 /library | |
parent | c741a211ee1c92e8796e3eb9a87007cf144038d1 (diff) | |
parent | 7b86f7e21c70ac06129c05ed137e585a308c6fd1 (diff) | |
download | android_frameworks_multidex-591acd99f16989233ff3e226546272bb60024559.tar.gz android_frameworks_multidex-591acd99f16989233ff3e226546272bb60024559.tar.bz2 android_frameworks_multidex-591acd99f16989233ff3e226546272bb60024559.zip |
Merge "Deactivate the library if vm version is 2.1 or newer."
Diffstat (limited to 'library')
-rw-r--r-- | library/src/android/support/multidex/MultiDex.java | 62 | ||||
-rw-r--r-- | library/test/src/android/support/multidex/MultiDexTest.java | 47 | ||||
-rw-r--r-- | library/test/src/android/util/Log.java | 225 |
3 files changed, 324 insertions, 10 deletions
diff --git a/library/src/android/support/multidex/MultiDex.java b/library/src/android/support/multidex/MultiDex.java index 97c1ddd..cd38112 100644 --- a/library/src/android/support/multidex/MultiDex.java +++ b/library/src/android/support/multidex/MultiDex.java @@ -37,6 +37,8 @@ import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.zip.ZipFile; /** @@ -48,9 +50,8 @@ import java.util.zip.ZipFile; * {@link #install(Context)}. * * <p/> - * <strong>IMPORTANT:</strong>This library provides compatibility for platforms - * with API level 4 through 20. This library does nothing on newer versions of - * the platform which provide built-in support for secondary dex files. + * This library provides compatibility for platforms with API level 4 through 20. This library does + * nothing on newer versions of the platform which provide built-in support for secondary dex files. */ public final class MultiDex { @@ -58,12 +59,19 @@ public final class MultiDex { private static final String SECONDARY_FOLDER_NAME = "secondary-dexes"; - private static final int SUPPORTED_MULTIDEX_SDK_VERSION = 21; + private static final int MAX_SUPPORTED_SDK_VERSION = 20; private static final int MIN_SDK_VERSION = 4; + private static final int VM_WITH_MULTIDEX_VERSION_MAJOR = 2; + + private static final int VM_WITH_MULTIDEX_VERSION_MINOR = 1; + private static final Set<String> installedApk = new HashSet<String>(); + private static final boolean IS_VM_MULTIDEX_CAPABLE = + isVMMultidexCapable(System.getProperty("java.vm.version")); + private MultiDex() {} /** @@ -78,13 +86,16 @@ public final class MultiDex { */ public static void install(Context context) { Log.i(TAG, "install"); + if (IS_VM_MULTIDEX_CAPABLE) { + Log.i(TAG, "VM has multidex support, MultiDex support library is disabled."); + return; + } if (Build.VERSION.SDK_INT < MIN_SDK_VERSION) { throw new RuntimeException("Multi dex installation failed. SDK " + Build.VERSION.SDK_INT + " is unsupported. Min SDK version is " + MIN_SDK_VERSION + "."); } - try { PackageManager pm; String packageName; @@ -118,11 +129,13 @@ public final class MultiDex { } installedApk.add(apkPath); - if (Build.VERSION.SDK_INT >= SUPPORTED_MULTIDEX_SDK_VERSION) { - // STOPSHIP: Any app that uses this class needs approval before being released - // as well as figuring out what the right behavior should be here. - throw new RuntimeException("Platform support of multidex for SDK " + - Build.VERSION.SDK_INT + " has not been confirmed yet."); + if (Build.VERSION.SDK_INT > MAX_SUPPORTED_SDK_VERSION) { + Log.w(TAG, "MultiDex is not guaranteed to work in SDK version " + + Build.VERSION.SDK_INT + ": SDK version higher than " + + MAX_SUPPORTED_SDK_VERSION + " should be backed by " + + "runtime with built-in multidex capabilty but it's not the " + + "case here: java.vm.version=\"" + + System.getProperty("java.vm.version") + "\""); } /* The patched class loader is expected to be a descendant of @@ -175,6 +188,35 @@ public final class MultiDex { Log.i(TAG, "install done"); } + /** + * Identifies if the current VM has a native support for multidex, meaning there is no need for + * additional installation by this library. + * @return true if the VM handles multidex + */ + /* package visible for test */ + static boolean isVMMultidexCapable(String versionString) { + boolean isMultidexCapable = false; + if (versionString != null) { + Matcher matcher = Pattern.compile("(\\d+)\\.(\\d+)(\\.\\d+)?").matcher(versionString); + if (matcher.matches()) { + try { + int major = Integer.parseInt(matcher.group(1)); + int minor = Integer.parseInt(matcher.group(2)); + isMultidexCapable = (major > VM_WITH_MULTIDEX_VERSION_MAJOR) + || ((major == VM_WITH_MULTIDEX_VERSION_MAJOR) + && (minor >= VM_WITH_MULTIDEX_VERSION_MINOR)); + } catch (NumberFormatException e) { + // let isMultidexCapable be false + } + } + } + Log.i(TAG, "VM with version " + versionString + + (isMultidexCapable ? + " has multidex support" : + " does not have multidex support")); + return isMultidexCapable; + } + private static void installSecondaryDexes(ClassLoader loader, File dexDir, List<File> files) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IOException { diff --git a/library/test/src/android/support/multidex/MultiDexTest.java b/library/test/src/android/support/multidex/MultiDexTest.java new file mode 100644 index 0000000..62bdc30 --- /dev/null +++ b/library/test/src/android/support/multidex/MultiDexTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.support.multidex; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for {@link MultiDex} class. + */ +public class MultiDexTest { + @Test + public void testVersionCheck() { + Assert.assertFalse(MultiDex.isVMMultidexCapable(null)); + Assert.assertFalse(MultiDex.isVMMultidexCapable("-1.32.54")); + Assert.assertFalse(MultiDex.isVMMultidexCapable("1.32.54")); + Assert.assertFalse(MultiDex.isVMMultidexCapable("1.32")); + Assert.assertFalse(MultiDex.isVMMultidexCapable("2.0")); + Assert.assertFalse(MultiDex.isVMMultidexCapable("2.000.1254")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("2.1.1254")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("2.1")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("2.2")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("2.1.0000")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("2.2.0000")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("002.0001.0010")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("3.0")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("3.0.0")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("3.0.1")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("3.1.0")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("03.1.132645")); + Assert.assertTrue(MultiDex.isVMMultidexCapable("03.2")); + } +} diff --git a/library/test/src/android/util/Log.java b/library/test/src/android/util/Log.java new file mode 100644 index 0000000..b94e48b --- /dev/null +++ b/library/test/src/android/util/Log.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.UnknownHostException; + +/** + * Mock Log implementation for testing on non android host. + */ +public final class Log { + + /** + * Priority constant for the println method; use Log.v. + */ + public static final int VERBOSE = 2; + + /** + * Priority constant for the println method; use Log.d. + */ + public static final int DEBUG = 3; + + /** + * Priority constant for the println method; use Log.i. + */ + public static final int INFO = 4; + + /** + * Priority constant for the println method; use Log.w. + */ + public static final int WARN = 5; + + /** + * Priority constant for the println method; use Log.e. + */ + public static final int ERROR = 6; + + /** + * Priority constant for the println method. + */ + public static final int ASSERT = 7; + + private Log() { + } + + /** + * Send a {@link #VERBOSE} log message. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static int v(String tag, String msg) { + return println(LOG_ID_MAIN, VERBOSE, tag, msg); + } + + /** + * Send a {@link #VERBOSE} log message and log the exception. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static int v(String tag, String msg, Throwable tr) { + return println(LOG_ID_MAIN, VERBOSE, tag, msg + '\n' + getStackTraceString(tr)); + } + + /** + * Send a {@link #DEBUG} log message. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static int d(String tag, String msg) { + return println(LOG_ID_MAIN, DEBUG, tag, msg); + } + + /** + * Send a {@link #DEBUG} log message and log the exception. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static int d(String tag, String msg, Throwable tr) { + return println(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr)); + } + + /** + * Send an {@link #INFO} log message. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static int i(String tag, String msg) { + return println(LOG_ID_MAIN, INFO, tag, msg); + } + + /** + * Send a {@link #INFO} log message and log the exception. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static int i(String tag, String msg, Throwable tr) { + return println(LOG_ID_MAIN, INFO, tag, msg + '\n' + getStackTraceString(tr)); + } + + /** + * Send a {@link #WARN} log message. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static int w(String tag, String msg) { + return println(LOG_ID_MAIN, WARN, tag, msg); + } + + /** + * Send a {@link #WARN} log message and log the exception. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static int w(String tag, String msg, Throwable tr) { + return println(LOG_ID_MAIN, WARN, tag, msg + '\n' + getStackTraceString(tr)); + } + + /* + * Send a {@link #WARN} log message and log the exception. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param tr An exception to log + */ + public static int w(String tag, Throwable tr) { + return println(LOG_ID_MAIN, WARN, tag, getStackTraceString(tr)); + } + + /** + * Send an {@link #ERROR} log message. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static int e(String tag, String msg) { + return println(LOG_ID_MAIN, ERROR, tag, msg); + } + + /** + * Send a {@link #ERROR} log message and log the exception. + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static int e(String tag, String msg, Throwable tr) { + return println(LOG_ID_MAIN, ERROR, tag, msg + '\n' + getStackTraceString(tr)); + } + + /** + * Handy function to get a loggable stack trace from a Throwable + * @param tr An exception to log + */ + public static String getStackTraceString(Throwable tr) { + if (tr == null) { + return ""; + } + + // This is to reduce the amount of log spew that apps do in the non-error + // condition of the network being unavailable. + Throwable t = tr; + while (t != null) { + if (t instanceof UnknownHostException) { + return ""; + } + t = t.getCause(); + } + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + tr.printStackTrace(pw); + pw.flush(); + return sw.toString(); + } + + /** + * Low-level logging call. + * @param priority The priority/type of this log message + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @return The number of bytes written. + */ + public static int println(int priority, String tag, String msg) { + return println(LOG_ID_MAIN, priority, tag, msg); + } + + /** @hide */ public static final int LOG_ID_MAIN = 0; + /** @hide */ public static final int LOG_ID_RADIO = 1; + /** @hide */ public static final int LOG_ID_EVENTS = 2; + /** @hide */ public static final int LOG_ID_SYSTEM = 3; + /** @hide */ public static final int LOG_ID_CRASH = 4; + + /** @hide */ @SuppressWarnings("unused") + public static int println(int bufID, + int priority, String tag, String msg) { + return 0; + } +} |