Cherry pick 'Update to r12 of LittleMock'.

DO NOT MERGE

Change-Id: I0899465493a1ebaaa587bb13f2f9ebf18f516037
diff --git a/src/com/google/testing/littlemock/AppDataDirGuesser.java b/src/com/google/testing/littlemock/AppDataDirGuesser.java
index 8dd556e..e661ed6 100644
--- a/src/com/google/testing/littlemock/AppDataDirGuesser.java
+++ b/src/com/google/testing/littlemock/AppDataDirGuesser.java
@@ -103,7 +103,7 @@
       File dataDir = new File("/data/data/" + packageName);
       if (isWriteableDirectory(dataDir)) {
         File cacheDir = new File(dataDir, "cache");
-        if ((cacheDir.exists()) || (cacheDir.mkdir())) {
+        if (fileOrDirExists(cacheDir) || makeDirectory(cacheDir)) {
           if (isWriteableDirectory(cacheDir)) {
             results.add(cacheDir);
           }
@@ -114,6 +114,16 @@
   }
 
   // @VisibleForTesting
+  boolean fileOrDirExists(File file) {
+      return file.exists();
+  }
+
+  // @VisibleForTesting
+  boolean makeDirectory(File file) {
+      return file.mkdir();
+  }
+
+  // @VisibleForTesting
   boolean isWriteableDirectory(File file) {
     return file.isDirectory() && file.canWrite();
   }
diff --git a/src/com/google/testing/littlemock/LittleMock.java b/src/com/google/testing/littlemock/LittleMock.java
index 50afeb1..fc6c527 100644
--- a/src/com/google/testing/littlemock/LittleMock.java
+++ b/src/com/google/testing/littlemock/LittleMock.java
@@ -17,6 +17,8 @@
 package com.google.testing.littlemock;
 
 import java.io.File;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -1060,15 +1062,42 @@
       Class<?> proxyBuilder = Class.forName("com.google.dexmaker.stock.ProxyBuilder");
       Method forClassMethod = proxyBuilder.getMethod("forClass", Class.class);
       Object builder = forClassMethod.invoke(null, clazz);
-      Method handlerMethod = builder.getClass().getMethod("handler", InvocationHandler.class);
-      builder = handlerMethod.invoke(builder, handler);
       Method dexCacheMethod = builder.getClass().getMethod("dexCache", File.class);
       File directory = AppDataDirGuesser.getsInstance().guessSuitableDirectoryForGeneratedClasses();
       builder = dexCacheMethod.invoke(builder, directory);
-      Method buildMethod = builder.getClass().getMethod("build");
-      return buildMethod.invoke(builder);
+      Method buildClassMethod = builder.getClass().getMethod("buildProxyClass");
+      Class<?> resultClass = (Class<?>) buildClassMethod.invoke(builder);
+      Object proxy = unsafeCreateInstance(resultClass);
+      Field handlerField = resultClass.getDeclaredField("$__handler");
+      handlerField.setAccessible(true);
+      handlerField.set(proxy, handler);
+      return proxy;
     } catch (Exception e) {
       throw new IllegalStateException("Could not mock this concrete class", e);
     }
   }
+
+  /** Attempt to construct an instance of the class using hacky methods to avoid calling super. */
+  @SuppressWarnings("unchecked")
+  private static <T> T unsafeCreateInstance(Class<T> clazz) {
+    // try dalvikvm, pre-gingerbread
+    try {
+      final Method newInstance = ObjectInputStream.class.getDeclaredMethod(
+          "newInstance", Class.class, Class.class);
+      newInstance.setAccessible(true);
+      return (T) newInstance.invoke(null, clazz, Object.class);
+    } catch (Exception ignored) {}
+    // try dalvikvm, post-gingerbread
+    try {
+      Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod(
+          "getConstructorId", Class.class);
+      getConstructorId.setAccessible(true);
+      final int constructorId = (Integer) getConstructorId.invoke(null, Object.class);
+      final Method newInstance = ObjectStreamClass.class.getDeclaredMethod(
+          "newInstance", Class.class, int.class);
+      newInstance.setAccessible(true);
+      return (T) newInstance.invoke(null, clazz, constructorId);
+    } catch (Exception ignored) {}
+    throw new IllegalStateException("unsafe create instance failed");
+  }
 }
diff --git a/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java b/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java
index b537097..3ab38b2 100644
--- a/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java
+++ b/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java
@@ -82,6 +82,10 @@
           public boolean isWriteableDirectory(File file) {
             return !notWriteable.contains(file.getAbsolutePath());
           }
+          @Override
+          boolean fileOrDirExists(File file) {
+            return true;
+          }
         };
         File[] results = guesser.guessPath(path);
         assertNotNull("Null results for " + path, results);