How to build Android Marshmallow on Nexus 7 2012

The story thus far...

Many were very sad when google chose not to update Nexus 7 2012 to Android 6.0 Marshmallow. This simple guide will show you how to build Android 6.0 Marshmallow for Nexus 7 2012. And for the lazy, I also have a pre-built AOSP Marshmallow image set to download on the bottom of this page. Since Nexus 7 was originally a Google-Play-equipped device, you can legally install Google Apps on this image and enjoy a full Google Android 6.0 experience on your Nexus 7. That part, however, is up to you to do yourself. I am not offering GApps downloads here.

For fun, to make this work a few very cool hacks had to be done, read further below in the "cool hacks" section about them, if you care.


How to build (WiFi)

#get Android M AOSP into folder called M
mkdir L
mkdir M
cd M
repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.0_r1
repo sync -j4
cd ..

#get latest L AOSP into folder called L
cd L
repo init -u https://android.googlesource.com/platform/manifest -b android-5.1.1_r1
repo sync -j4
cd ..

#get blobs (except widevine)
cd M
wget https://dl.google.com/dl/android/aosp/asus-grouper-lmy47v-f395a331.tgz
wget https://dl.google.com/dl/android/aosp/broadcom-grouper-lmy47v-5671ab27.tgz
wget https://dl.google.com/dl/android/aosp/elan-grouper-lmy47v-6a10e8f3.tgz
wget https://dl.google.com/dl/android/aosp/invensense-grouper-lmy47v-ccd43018.tgz
wget https://dl.google.com/dl/android/aosp/nvidia-grouper-lmy47v-c9005750.tgz
wget https://dl.google.com/dl/android/aosp/nxp-grouper-lmy47v-18820f9b.tgz
#wget https://dl.google.com/dl/android/aosp/widevine-grouper-lmy47v-e570494f.tgz
tar xvfz asus-grouper-lmy47v-f395a331.tgz
tar xvfz broadcom-grouper-lmy47v-5671ab27.tgz
tar xvfz elan-grouper-lmy47v-6a10e8f3.tgz
tar xvfz invensense-grouper-lmy47v-ccd43018.tgz
tar xvfz nvidia-grouper-lmy47v-c9005750.tgz
tar xvfz nxp-grouper-lmy47v-18820f9b.tgz
#tar xvfz widevine-grouper-lmy47v-e570494f.tgz
dd if=extract-asus-grouper.sh bs=14466 skip=1       | tar xvz
dd if=extract-broadcom-grouper.sh bs=14464 skip=1   | tar xvz
dd if=extract-elan-grouper.sh bs=14490 skip=1       | tar xvz
dd if=extract-invensense-grouper.sh bs=14456 skip=1 | tar xvz
dd if=extract-nvidia-grouper.sh bs=14460 skip=1     | tar xvz
dd if=extract-nxp-grouper.sh bs=14452 skip=1        | tar xvz
#dd if=extract-widevine-grouper.sh bs=14446 skip=1   | tar xvz
rm *grouper-lmy47v*.tgz extract-*-grouper.sh

#cool binary patch for GL blobs
echo -n dmitrygr_libldr | dd bs=1 seek=4340 conv=notrunc of=vendor/nvidia/grouper/proprietary/libEGL_tegra.so
echo -n dgv1 | dd bs=1 seek=6758 conv=notrunc of=vendor/nvidia/grouper/proprietary/libEGL_tegra.so
echo -n dmitrygr_libldr | dd bs=1 seek=3811 conv=notrunc of=vendor/nvidia/grouper/proprietary/libGLESv1_CM_tegra.so
echo -n dgv1 | dd bs=1 seek=6447 conv=notrunc of=vendor/nvidia/grouper/proprietary/libGLESv1_CM_tegra.so

#cool binary patch for GPS blob
printf "malloc\0" | dd bs=1 seek=5246 conv=notrunc of=vendor/broadcom/grouper/proprietary/glgps

#get old device sources
cp -Rvf ../L/device/asus/grouper device/asus/grouper

#apply source patch to Nfc package (sadly we must mess with platform code here)
cd packages/apps/Nfc/
git apply ../../../../packages-apps-Nfc.patch
cd ../../..

#apply source patch to vendor repo
cd vendor
git apply ../../vendor.patch
cd ..

#apply source patch to device repo
cd device/asus/grouper
git apply ../../../../device-asus-grouper.patch
cd ../../..

#get kernel
cd ..
git clone https://android.googlesource.com/kernel/tegra.git
cd tegra
git checkout remotes/origin/android-tegra3-grouper-3.1-lollipop-mr1 -b l-mr1

#apply kernel patch
git apply ../kernel.patch

#build kernel
export CROSS_COMPILE=`pwd`/../M/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-
export ARCH=arm
make tegra3_android_defconfig
make -j4
cp arch/arm/boot/zImage ../M/device/asus/grouper/kernel
cd ../M

#build Android
source build/envsetup.sh
lunch aosp_grouper-userdebug
make -j4



How to build (3G)

Peform all the steps for WiFi device first (3G device build depends on it)

#get blobs (Except widevine)
wget https://dl.google.com/dl/android/aosp/asus-tilapia-lmy47v-6272610e.tgz
wget https://dl.google.com/dl/android/aosp/broadcom-tilapia-lmy47v-e9d05927.tgz
wget https://dl.google.com/dl/android/aosp/elan-tilapia-lmy47v-5f509df5.tgz
wget https://dl.google.com/dl/android/aosp/invensense-tilapia-lmy47v-066fff5f.tgz
wget https://dl.google.com/dl/android/aosp/nvidia-tilapia-lmy47v-05744cf3.tgz
wget https://dl.google.com/dl/android/aosp/nxp-tilapia-lmy47v-7a361708.tgz
#wget https://dl.google.com/dl/android/aosp/widevine-tilapia-lmy47v-2844d74a.tgz
tar xvfz asus-tilapia-lmy47v-6272610e.tgz
tar xvfz broadcom-tilapia-lmy47v-e9d05927.tgz
tar xvfz elan-tilapia-lmy47v-5f509df5.tgz
tar xvfz invensense-tilapia-lmy47v-066fff5f.tgz
tar xvfz nvidia-tilapia-lmy47v-05744cf3.tgz
tar xvfz nxp-tilapia-lmy47v-7a361708.tgz
#tar xvfz widevine-tilapia-lmy47v-2844d74a.tgz
dd if=extract-asus-tilapia.sh  bs=14466 skip=1       | tar xvz
dd if=extract-broadcom-tilapia.sh  bs=14464 skip=1   | tar xvz
dd if=extract-elan-tilapia.sh  bs=14490 skip=1       | tar xvz
dd if=extract-invensense-tilapia.sh  bs=14456 skip=1 | tar xvz
dd if=extract-nvidia-tilapia.sh  bs=14460 skip=1     | tar xvz
dd if=extract-nxp-tilapia.sh  bs=14452 skip=1        | tar xvz
#dd if=extract-widevine-tilapia.sh  bs=14446 skip=1   | tar xvz

#cool binary patch for GL blobs
echo -n dmitrygr_libldr | dd bs=1 seek=4340 conv=notrunc of=vendor/nvidia/tilapia//proprietary/libEGL_tegra.so
echo -n dgv1 | dd bs=1 seek=6758 conv=notrunc of=vendor/nvidia/tilapia//proprietary/libEGL_tegra.so
echo -n dmitrygr_libldr | dd bs=1 seek=3811 conv=notrunc of=vendor/nvidia/tilapia/proprietary/libGLESv1_CM_tegra.so
echo -n dgv1 | dd bs=1 seek=6447 conv=notrunc of=vendor/nvidia/tilapia/proprietary/libGLESv1_CM_tegra.so

#cool binary patch for GPS blob
printf "malloc\0" | dd bs=1 seek=5246 conv=notrunc of=vendor/broadcom/tilapia/proprietary/glgps

#bring in libstlport which the ril sadly needs
cp -Rvf ../L/external/stlport external/stlport

#apply source patch to device tree
cd device/asus/tilapia
git apply ../../../../device-asus-tilapia.patch
cd ../../..

#apply source patch to vendor repo
cd vendor
git apply ../../vendor.patch
cd ..

#build it
source build/envsetup.sh
lunch aosp_tilapia-userdebug
make -j4


Cool hacks (or: "what the hell is libdgv1.so and why are you binary editing files"?)

OpenGL

Nexus 7.2012's GL libraries were made to work with Android L, and no sources are provided. Android M changed one thing around that make it not work: dlopen() is now POSIX complaint. While this may sound like a good thing, and it is, it still breaks NVIDIA's GL libraries. Why? Well, they each insist on loading each-other using dlopen. And what do they pass to dlopen? Strings like "egl/libGLESv2_tegra.so". Why is this a problem? Well, the POSIX spec says that if dlopen is passed a path that includes a slash, no searching is done for the requisite library besides in the current working directory. If no slash is present, a search through a system-specific library search path happens. Previously in android, the latter behaviour happened all the time, and since /system/lib was in the search path, asking dlopen to locate "egl/libGLESv2_tegra.so" would corectly find and load "/system/lib/egl/libGLESv2_tegra.so". In M this is no longer the case, since dlopen will only search the current working directory. For most android processes, this is just "/". This is why a simple (but dirty, wrong, and ultimately incomplete) way to solve this problem is to symlink "/egl" to "/system/lib/egl". But this is a bad solution, since technically any app can change its working directory, and then it will no longer be able to use OpenGL. Clearly a better solution is needed.

NVIDIA's libraries do not call dlopen directly. They call "NvOsLibraryLoad" - an NVIDIA-specific wrapper around dlopen. The implementation of this funtion resides in "libnvos.so". This is our opportunity! Curious information: Due to peculiarities of the ELF format, when a binary baz imports function foo() from libbar.so, nowhere in baz's ELF file does it say that foo() must from from libbar. In fact there are two separate records. One that says that libbar is "NEED"ed, and another that says that there is an import of function "foo". What that means is that if the process were to also load libxyz, which also exported foo(), there is no way to be sure which foo() would get called. Why do we care? Well, consider our problems. We can repalce a NEED record in NVIDIA's libraries with one referencing a library we control, like "libdgv1.so", replace the name of the function they call to load libraries from "NvOsLibraryLoad" to something else, "like dmitrygr_libldr", implement that function in terms of the real "NvOsLibraryLoad" in "libdgv1.so", while fixing paths, and as long as "libdgv1.so" has a NEED record referencing libnvos.so, all will go well. This is in fact what I did. Thus the binary patches to the NVIDIA libraries are minimal (two strings each). The implementation of "libdgv1.so" I am providing under AOSP license as part of this post. I would like to once-again emphasize that just symlinking "/egl" is not a proper solution, since any app that changes its working directory (which is OK and allowed) will thus be unable to use OpenGL.

GPS

Nexus 7.2012's GPS library was also only made for Android L, and does not work in M. Here the reason is simple. It relies on OpenSSL, which in M was replaced by BoringSSL. Fun thing is, though, they are fully compatible. So why does GPS fail? Ha! Broadcom, for some reason used an internal OpenSSL function "CRYPTO_malloc" in their GPS library. "CRYPTO_malloc" just allocates memory. This fix was easy. I binary edited the IMPORT entry in gps daemon to use "malloc" instead and life went on. It is a simple binary patch as well.

Kernel & system()

In their infinite wisdom, NVIDIA decided to directly read files in the filesystem from their kernel. This is always 100% unequivocally a bad idea, as you can read all about here: LINK. The guilty party was an ALS driver. I was not about to let this proceed. I modified the kernel driver to instead have a sysfs entry that one could write that file to (it has a single calibration value). This would be nice and easy, except this changes the behaviour of this calibration form pull (by kernel) to push (by userspace). So now I had to find who writes that file the kernel used to read, and replace that code with writing a sysfs node. This is where things took a turn for the scandalous. The only things touching this file was a binary-only executable that NVIDIA supplies, named "sensors-config". It was a small one, and I figured i'll just binary patch it. I disassembled it, and I was horrified. It was a spaghetti-themed nightmare, full of calls to "system()". I decided to rewrite it. I produced a fully working replica of this binary in source, and am releasing my code under AOSP license as well. As a bonus, now I could teach this binary to write to the sysfs node of the modified drver.

Camera

Camera was not working for a long time. I spent a lot of time debugging, only to eventually find out that it does work, and it is the AOSP Camera app that does not. There goes half my night...

Work left to do

  • Kernel per-uid CPU accounting needs to be done for better battery blaming. I might get it done later, but it is not urgent. I did do it for N10 and N4 - I am just being lazy now. Not having this will cause the framework to try finding it 10 times, and log the failures, then it will quiet down and life will proceed.


Ok, ok, give me the files already!

grouper(WiFi)tilapia(3G)
Download patches if you want to make the build yourself: => [PACKAGE YOU'LL NEED (mirror)] <=

If you're not a person who wants to build android yourself from source, here is fully usable userdebug image. Tested: Sensors, NFC, WiFi, Bluetooth, Camera, GPS.

Fastboot-flashable images here => [FASTBOOT IMAGES (mirror)] <=
Or, if you prefer to flash from TWRP => [TWRP flashable zip (mirror)] (updated) <=
Download patches if you want to make the build yourself: => [PACKAGE YOU'LL NEED (mirror)] <=

If you're not a person who wants to build android yourself from source, here is fully usable userdebug image. Tested: Sensors, NFC, WiFi, Bluetooth, Camera, GPS.

Fastboot-flashable images here => [FASTBOOT IMAGES (mirror)] <=
Or, if you prefer to flash from TWRP => [TWRP flashable zip (mirror)] <=




Plase do not re-host this elsewhere and claim this as your work.
© 2012-2017