Home | History | Annotate | Download | only in creation
      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 
     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 
     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 
     90     private static boolean fileOrDirExists(File file) {
     91         return file.exists();
     92     }
     93 
     94     private static boolean isWriteableDirectory(File file) {
     95         return file.isDirectory() && file.canWrite();
     96     }
     97 }
     98