1/* 2 * Copyright (C) 2012 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 17package com.google.dexmaker; 18 19import java.io.File; 20import java.util.ArrayList; 21import java.util.List; 22 23/** 24 * Uses heuristics to guess the application's private data directory. 25 */ 26class AppDataDirGuesser { 27 public File guess() { 28 try { 29 ClassLoader classLoader = guessSuitableClassLoader(); 30 // Check that we have an instance of the PathClassLoader. 31 Class<?> clazz = Class.forName("dalvik.system.PathClassLoader"); 32 clazz.cast(classLoader); 33 // Use the toString() method to calculate the data directory. 34 String pathFromThisClassLoader = getPathFromThisClassLoader(classLoader); 35 File[] results = guessPath(pathFromThisClassLoader); 36 if (results.length > 0) { 37 return results[0]; 38 } 39 } catch (ClassCastException ignored) { 40 } catch (ClassNotFoundException ignored) { 41 } 42 return null; 43 } 44 45 private ClassLoader guessSuitableClassLoader() { 46 return AppDataDirGuesser.class.getClassLoader(); 47 } 48 49 private String getPathFromThisClassLoader(ClassLoader classLoader) { 50 // Parsing toString() method: yuck. But no other way to get the path. 51 // Strip out the bit between angle brackets, that's our path. 52 String result = classLoader.toString(); 53 int index = result.lastIndexOf('['); 54 result = (index == -1) ? result : result.substring(index + 1); 55 index = result.indexOf(']'); 56 return (index == -1) ? result : result.substring(0, index); 57 } 58 59 File[] guessPath(String input) { 60 List<File> results = new ArrayList<File>(); 61 for (String potential : input.split(":")) { 62 if (!potential.startsWith("/data/app/")) { 63 continue; 64 } 65 int start = "/data/app/".length(); 66 int end = potential.lastIndexOf(".apk"); 67 if (end != potential.length() - 4) { 68 continue; 69 } 70 int dash = potential.indexOf("-"); 71 if (dash != -1) { 72 end = dash; 73 } 74 File file = new File("/data/data/" + potential.substring(start, end) + "/cache"); 75 if (isWriteableDirectory(file)) { 76 results.add(file); 77 } 78 } 79 return results.toArray(new File[results.size()]); 80 } 81 82 boolean isWriteableDirectory(File file) { 83 return file.isDirectory() && file.canWrite(); 84 } 85} 86