1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.useslibrary; 18 19 import android.content.pm.PackageManager; 20 import android.os.Environment; 21 import android.support.test.uiautomator.UiDevice; 22 import android.support.test.uiautomator.UiObject; 23 import android.support.test.uiautomator.UiSelector; 24 import android.test.InstrumentationTestCase; 25 26 import dalvik.system.BaseDexClassLoader; 27 import dalvik.system.DexFile; 28 import dalvik.system.PathClassLoader; 29 30 import java.io.File; 31 import java.lang.reflect.Field; 32 import java.lang.reflect.Method; 33 34 public class UsesLibraryTest extends InstrumentationTestCase { 35 private static final String TAG = "UsesLibraryTest"; 36 testUsesLibrary()37 public void testUsesLibrary() throws Exception { 38 ClassLoader loader = getClass().getClassLoader(); 39 if (loader instanceof BaseDexClassLoader) { 40 Object[] dexElements = getDexElementsFromClassLoader((BaseDexClassLoader) loader); 41 for (Object dexElement : dexElements) { 42 DexFile dexFile = getDexFileFromDexElement(dexElement); 43 assertTrue(isDexFileBackedByOatFile(dexFile)); 44 } 45 } 46 } 47 testMissingLibrary()48 public void testMissingLibrary() throws Exception { 49 ClassLoader loader = getClass().getClassLoader(); 50 if (loader instanceof BaseDexClassLoader) { 51 Object[] dexElements = getDexElementsFromClassLoader((BaseDexClassLoader) loader); 52 assertTrue(dexElements != null && dexElements.length > 1); 53 54 DexFile dexFile = getDexFileFromDexElement(dexElements[1]); 55 String testApkPath = dexFile.getName(); 56 PathClassLoader testLoader = new PathClassLoader(testApkPath, null); 57 Object[] testDexElements = getDexElementsFromClassLoader(testLoader); 58 assertTrue(testDexElements != null && testDexElements.length == 1); 59 60 DexFile testDexFile = getDexFileFromDexElement(testDexElements[0]); 61 assertTrue(isDexFileBackedByOatFile(testDexFile)); 62 } 63 } 64 testDuplicateLibrary()65 public void testDuplicateLibrary() throws Exception { 66 ClassLoader loader = getClass().getClassLoader(); 67 if (loader instanceof BaseDexClassLoader) { 68 Object[] dexElements = getDexElementsFromClassLoader((BaseDexClassLoader) loader); 69 assertTrue(dexElements != null && dexElements.length > 1); 70 71 DexFile libDexFile = getDexFileFromDexElement(dexElements[0]); 72 String libPath = libDexFile.getName(); 73 DexFile apkDexFile = getDexFileFromDexElement(dexElements[1]); 74 String apkPath = apkDexFile.getName(); 75 String testPath = libPath + File.pathSeparator + apkPath + File.pathSeparator + apkPath; 76 PathClassLoader testLoader = new PathClassLoader(testPath, null); 77 Object[] testDexElements = getDexElementsFromClassLoader(testLoader); 78 assertTrue(testDexElements != null && testDexElements.length == 3); 79 80 DexFile testDexFile = getDexFileFromDexElement(testDexElements[2]); 81 assertFalse(isDexFileBackedByOatFile(testDexFile)); 82 } 83 } 84 getDexElementsFromClassLoader(BaseDexClassLoader loader)85 private Object[] getDexElementsFromClassLoader(BaseDexClassLoader loader) throws Exception { 86 Field pathListField = BaseDexClassLoader.class.getDeclaredField("pathList"); 87 pathListField.setAccessible(true); 88 // This is a DexPathList, but that class is package private. 89 Object pathList = pathListField.get(loader); 90 Field dexElementsField = pathList.getClass().getDeclaredField("dexElements"); 91 dexElementsField.setAccessible(true); 92 // The objects in this array are Elements, but that class is package private. 93 return (Object[]) dexElementsField.get(pathList); 94 } 95 96 // The argument must be a DexPathList.Element. getDexFileFromDexElement(Object dexElement)97 private DexFile getDexFileFromDexElement(Object dexElement) throws Exception { 98 Field dexFileField = dexElement.getClass().getDeclaredField("dexFile"); 99 dexFileField.setAccessible(true); 100 return (DexFile) dexFileField.get(dexElement); 101 } 102 isDexFileBackedByOatFile(DexFile dexFile)103 private boolean isDexFileBackedByOatFile(DexFile dexFile) throws Exception { 104 Method isBackedByOatFileMethod = DexFile.class.getDeclaredMethod("isBackedByOatFile"); 105 isBackedByOatFileMethod.setAccessible(true); 106 return (boolean) isBackedByOatFileMethod.invoke(dexFile); 107 } 108 } 109