I have been an Android developer for two years and a Java developer for almost 15, and even a former Google employee, and...in my estimation, Carmack is 100% right.
Despite how much more I like Java than lower-level languages, Google's software stack is a complete disaster. It's poorly designed, bug-riddled garbage that I have actually considered re-writing parts of, even in the middle of a high-pressure project. What makes matters so much worse is Android's distribution model: rather than the direct-to-consumer approach that Apple takes, Google distributes Android indirectly via its device vendors, who can provide arbitrarily modified or out-of-date versions of the infrastructure that you're expected to support when dealing with angry customers who don't understand why their network stack mysteriously doesn't work.
The NDK is not an answer. It's a wreck because JNI is a wreck. I've been using JNI since 2002, and almost nothing has evolved since then - it was never anything more than a token olive branch to luddite C++ developers in 1995, and probably never will be. Ultimately, Java is excellent for mature devices (like servers), but is not suitable for emerging devices (like all the mobile devices we're seeing now) because of its runtime overhead.
Despite Apple's many shortcomings, one of the key points they get right is that mobile development needs natively compiled, non-runtime (or thin-runtime) languages. And, of course, libraries that work. Apple isn't exactly the gold standard on that either, but at least they're miles ahead of "beta early, beta often" Google.