1 /* 2 * Copyright (c) 2017 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.android.internal.creation; 6 7 import java.io.File; 8 import java.lang.reflect.Field; 9 import java.util.ArrayList; 10 import java.util.List; 11 12 class AndroidTempFileLocator { 13 14 final static File target; 15 16 static { 17 File t = null; 18 try { 19 String user = System.getProperty("org.mockito.android.target"); 20 if (user != null) { 21 t = new File(user); 22 } 23 } catch (Throwable ignored) { 24 } 25 if (t == null) { 26 try { 27 Class<?> clazz = Class.forName("android.support.test.InstrumentationRegistry"); 28 Object context = clazz.getDeclaredMethod("getTargetContext").invoke(clazz); 29 t = (File) context.getClass().getMethod("getCacheDir").invoke(context); 30 } catch (Throwable ignored) { 31 } 32 } 33 if (t == null) { 34 try { 35 Class<?> clazz = Class.forName("dalvik.system.PathClassLoader"); 36 Field pathField = clazz.getDeclaredField("path"); 37 pathField.setAccessible(true); 38 String pathFromThisClassLoader = (String) pathField.get(AndroidTempFileLocator.class.getClassLoader()); 39 File[] results = guessPath(pathFromThisClassLoader); 40 if (results.length > 0) { 41 t = results[0]; 42 } 43 } catch (Throwable ignored) { 44 } 45 } 46 target = t; 47 } 48 guessPath(String input)49 private static File[] guessPath(String input) { 50 List<File> results = new ArrayList<File>(); 51 for (String potential : splitPathList(input)) { 52 if (!potential.startsWith("/data/app/")) { 53 continue; 54 } 55 int start = "/data/app/".length(); 56 int end = potential.lastIndexOf(".apk"); 57 if (end != potential.length() - 4) { 58 continue; 59 } 60 int dash = potential.indexOf("-"); 61 if (dash != -1) { 62 end = dash; 63 } 64 String packageName = potential.substring(start, end); 65 File dataDir = new File("/data/data/" + packageName); 66 if (isWriteableDirectory(dataDir)) { 67 File cacheDir = new File(dataDir, "cache"); 68 if (fileOrDirExists(cacheDir) || cacheDir.mkdir()) { 69 if (isWriteableDirectory(cacheDir)) { 70 results.add(cacheDir); 71 } 72 } 73 } 74 } 75 return results.toArray(new File[results.size()]); 76 } 77 splitPathList(String input)78 private static String[] splitPathList(String input) { 79 String trimmed = input; 80 if (input.startsWith("dexPath=")) { 81 int start = "dexPath=".length(); 82 int end = input.indexOf(','); 83 84 trimmed = (end == -1) ? input.substring(start) : input.substring(start, end); 85 } 86 87 return trimmed.split(":"); 88 } 89 fileOrDirExists(File file)90 private static boolean fileOrDirExists(File file) { 91 return file.exists(); 92 } 93 isWriteableDirectory(File file)94 private static boolean isWriteableDirectory(File file) { 95 return file.isDirectory() && file.canWrite(); 96 } 97 } 98