private static <T, G extends T> void generateCodeForAllMethods(
      DexMaker dexMaker,
      TypeId<G> generatedType,
      Method[] methodsToProxy,
      TypeId<T> superclassType) {
    TypeId<InvocationHandler> handlerType = TypeId.get(InvocationHandler.class);
    TypeId<Method[]> methodArrayType = TypeId.get(Method[].class);
    FieldId<G, InvocationHandler> handlerField =
        generatedType.getField(handlerType, FIELD_NAME_HANDLER);
    FieldId<G, Method[]> allMethods = generatedType.getField(methodArrayType, FIELD_NAME_METHODS);
    TypeId<Method> methodType = TypeId.get(Method.class);
    TypeId<Object[]> objectArrayType = TypeId.get(Object[].class);
    MethodId<InvocationHandler, Object> methodInvoke =
        handlerType.getMethod(TypeId.OBJECT, "invoke", TypeId.OBJECT, methodType, objectArrayType);
    for (int m = 0; m < methodsToProxy.length; ++m) {
      /*
       * If the 5th method on the superclass Example that can be overridden were to look like
       * this:
       *
       *     public int doSomething(Bar param0, int param1) {
       *         ...
       *     }
       *
       * Then the following dex byte code will generate a method on the proxy that looks
       * something like this (in idiomatic Java):
       *
       *     // if doSomething is not abstract
       *     public int doSomething(Bar param0, int param1) {
       *         if ($__handler == null) {
       *             return super.doSomething(param0, param1);
       *         }
       *         return __handler.invoke(this, __methodArray[4],
       *                 new Object[] { param0, Integer.valueOf(param1) });
       *     }
       *
       *     // if doSomething is abstract
       *     public int doSomething(Bar param0, int param1) {
       *         if ($__handler == null) {
       *             throw new AbstractMethodError("'doSomething' cannot be called");
       *         }
       *         return __handler.invoke(this, __methodArray[4],
       *                 new Object[] { param0, Integer.valueOf(param1) });
       *     }
       */
      Method method = methodsToProxy[m];
      String name = method.getName();
      Class<?>[] argClasses = method.getParameterTypes();
      TypeId<?>[] argTypes = new TypeId<?>[argClasses.length];
      for (int i = 0; i < argTypes.length; ++i) {
        argTypes[i] = TypeId.get(argClasses[i]);
      }
      Class<?> returnType = method.getReturnType();
      TypeId<?> resultType = TypeId.get(returnType);
      MethodId<?, ?> methodId = generatedType.getMethod(resultType, name, argTypes);
      TypeId<AbstractMethodError> abstractMethodErrorClass = TypeId.get(AbstractMethodError.class);
      Code code = dexMaker.declare(methodId, PUBLIC);
      Local<G> localThis = code.getThis(generatedType);
      Local<InvocationHandler> localHandler = code.newLocal(handlerType);
      Local<Object> invokeResult = code.newLocal(TypeId.OBJECT);
      Local<Integer> intValue = code.newLocal(TypeId.INT);
      Local<Object[]> args = code.newLocal(objectArrayType);
      Local<Integer> argsLength = code.newLocal(TypeId.INT);
      Local<Object> temp = code.newLocal(TypeId.OBJECT);
      Local<?> resultHolder = code.newLocal(resultType);
      Local<Method[]> methodArray = code.newLocal(methodArrayType);
      Local<Method> thisMethod = code.newLocal(methodType);
      Local<Integer> methodIndex = code.newLocal(TypeId.INT);
      Class<?> aBoxedClass = PRIMITIVE_TO_BOXED.get(returnType);
      Local<?> aBoxedResult = null;
      if (aBoxedClass != null) {
        aBoxedResult = code.newLocal(TypeId.get(aBoxedClass));
      }
      Local<InvocationHandler> nullHandler = code.newLocal(handlerType);

      Local<?>[] superArgs2 = null;
      Local<?> superResult2 = null;
      MethodId<T, ?> superMethod = null;
      Local<String> abstractMethodErrorMessage = null;
      Local<AbstractMethodError> abstractMethodError = null;
      if ((method.getModifiers() & ABSTRACT) == 0) {
        superArgs2 = new Local<?>[argClasses.length];
        superResult2 = code.newLocal(resultType);
        superMethod = superclassType.getMethod(resultType, name, argTypes);
      } else {
        abstractMethodErrorMessage = code.newLocal(TypeId.STRING);
        abstractMethodError = code.newLocal(abstractMethodErrorClass);
      }

      code.loadConstant(methodIndex, m);
      code.sget(allMethods, methodArray);
      code.aget(thisMethod, methodArray, methodIndex);
      code.loadConstant(argsLength, argTypes.length);
      code.newArray(args, argsLength);
      code.iget(handlerField, localHandler, localThis);

      // if (proxy == null)
      code.loadConstant(nullHandler, null);
      Label handlerNullCase = new Label();
      code.compare(Comparison.EQ, handlerNullCase, nullHandler, localHandler);

      // This code is what we execute when we have a valid proxy: delegate to invocation
      // handler.
      for (int p = 0; p < argTypes.length; ++p) {
        code.loadConstant(intValue, p);
        Local<?> parameter = code.getParameter(p, argTypes[p]);
        Local<?> unboxedIfNecessary = boxIfRequired(code, parameter, temp);
        code.aput(args, intValue, unboxedIfNecessary);
      }
      code.invokeInterface(methodInvoke, invokeResult, localHandler, localThis, thisMethod, args);
      generateCodeForReturnStatement(code, returnType, invokeResult, resultHolder, aBoxedResult);

      // This code is executed if proxy is null: call the original super method.
      // This is required to handle the case of construction of an object which leaks the
      // "this" pointer.
      code.mark(handlerNullCase);

      if ((method.getModifiers() & ABSTRACT) == 0) {
        for (int i = 0; i < superArgs2.length; ++i) {
          superArgs2[i] = code.getParameter(i, argTypes[i]);
        }
        if (void.class.equals(returnType)) {
          code.invokeSuper(superMethod, null, localThis, superArgs2);
          code.returnVoid();
        } else {
          invokeSuper(superMethod, code, localThis, superArgs2, superResult2);
          code.returnValue(superResult2);
        }
      } else {
        throwAbstractMethodError(code, method, abstractMethodErrorMessage, abstractMethodError);
      }

      /*
       * And to allow calling the original super method, the following is also generated:
       *
       *     public String super$doSomething$java_lang_String(Bar param0, int param1) {
       *          int result = super.doSomething(param0, param1);
       *          return result;
       *     }
       */
      MethodId<G, ?> callsSuperMethod =
          generatedType.getMethod(resultType, superMethodName(method), argTypes);
      Code superCode = dexMaker.declare(callsSuperMethod, PUBLIC);
      if ((method.getModifiers() & ABSTRACT) == 0) {
        Local<G> superThis = superCode.getThis(generatedType);
        Local<?>[] superArgs = new Local<?>[argClasses.length];
        for (int i = 0; i < superArgs.length; ++i) {
          superArgs[i] = superCode.getParameter(i, argTypes[i]);
        }
        if (void.class.equals(returnType)) {
          superCode.invokeSuper(superMethod, null, superThis, superArgs);
          superCode.returnVoid();
        } else {
          Local<?> superResult = superCode.newLocal(resultType);
          invokeSuper(superMethod, superCode, superThis, superArgs, superResult);
          superCode.returnValue(superResult);
        }
      } else {
        Local<String> superAbstractMethodErrorMessage = superCode.newLocal(TypeId.STRING);
        Local<AbstractMethodError> superAbstractMethodError =
            superCode.newLocal(abstractMethodErrorClass);
        throwAbstractMethodError(
            superCode, method, superAbstractMethodErrorMessage, superAbstractMethodError);
      }
    }
  }
Add

<pre>
    abstractMethodErrorMessage = method + " cannot be called";
    abstractMethodError = new AbstractMethodError(abstractMethodErrorMessage);
    throw abstractMethodError;
</pre>

<p>to the {@code code}.

@param code The code to add to
@param method The method that is abstract
@param abstractMethodErrorMessage The {@link Local} to store the error message
@param abstractMethodError The {@link Local} to store the error object
android/android_framework/dex-maker/src/main/java/com/android/dx/stock/ProxyBuilder.java