• (OK) Building Ice Cream Sandwich (Android v4) for VirtualBox on EC2



    http://www.thatsgeeky.com/2011/12/building-ice-cream-sandwich-android-v4-for-virtualbox-on-ec2/


    This post was published 4 years, 10 months ago. Due to the rapidly evolving world of technology, some concepts may no longer be applicable.

    This was completed 2 weeks ago, but I am only now getting around to posting it online. This experiment was purely for the fun of it – I don’t own (or want) a cell phone, and have never used Android. However, it is an interesting operating system, and I always enjoy playing around with such things – it’s the process more than the end result.

    Android 4 – Ice Cream Sandwich (ICS) is more compatible with x86 architectures than previous versions, and even includes a VirtualBox make profile. The default build, however, lacks a few things. Notable among these are mouse support, and network DNS (networking is enabled though).

    One of the differences in my approach, is that I used Amazon’s EC2 to do my compiling (mostly because it let me download the few GB of files in a few minutes, and I could throw as much disk space and processor power as I wanted at the task for relatively minimal cost).

    Estimated time: 2 hours
    Cost (on EC2): $0.45 (2x$0.216 + misc)

    Since EC2 has a variety of instances, it helps to know what is the limiting factor in compiling – CPU, memory, or I/O.

    I/O is dealt with by using a RAID0 array of ephemeral disks. The xlarge instances provide 4 ephemeral disks, which can easily be assembled into a RAID0 set using mdadm. It is worth noting that while many reports do suggest that EBS volumes are faster, with a 4 disk RAID, the performance should be acceptable (and without the cost that would be incurred by using EBS).

    That leaves RAM vs CPU. My observations found that the entire process needed about 3GB of memory (although, the Android site recommends 16GB, including swap), but that CPU was easily maxed out. I tried both m2.xlarge and c1.xlarge instances for this task – there really wasn’t as big of a difference as I would have expected (although, the processes weren’t run with the intention of comparing the instances). I would favour the c1.xlarge for this task.

    The c1.xlarge has 8 cores (’20 ECUs’) and 7GB of memory – it is comparable to a mid-high end desktop, clocking in at about 75GFLOPS.

    The recommended operating system for building Android is Ubuntu 10.04 – however, for interest sake, I opted to use, Ubuntu 11.04. I chose a instance-store AMI (ami-21f53948), since these include the ephemeral storage by default (and have no disk cost associated with them). (The intent here being to save some setup time and, of course, keep costs to a minimum).

    To get started, we create a spot request, for one c1.xlarge instance, in any availability zone. At the time of writing, the spot price was $0.216/hr (which is a bit more than the spot price of the m2.xlarge, at $0.153, although, the latter has more variation). Unless you are im a particular hurry, the spot instances are the most cost effective for a fairly short task – just remember to overbid somewhat to prevent unwanted termination in the middle of your task.

    Once the instance launches, SSH into it using your keypair (and the username ‘ubuntu’). If, like me, you aren’t used to using Ubuntu AMIs, the default settings (lack of scrollback, status bar at the bottom, the idea of ‘windowed sessions’, etc.) will be a bit alien at first, but it does grow on one.

    Initial Preparation

    We will begin by getting the instance up to date and installing the necessary dependencies. One point of mention is that Ubuntu 11.04 uses GCC v4.6 – which is not compatible with the Android code (it needs v 4.4).

    Since all of the initial commands need elevated privileges, I like to run sudo in interactive mode initially. Just be aware of what you are doing (even if this is a ‘throwaway’ instance). Alternatively, you can prefix each of the first few commands with sudo.

    sudo -i
    apt-get update
    apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils gcc-4.4 g++-4.4 python-lunch gcc-4.4-multilib g++-4.4-multilib

    Symlink one file to resolve some naming issues:

    ln -s /usr/lib/i386-linux-gnu/libX11.so.6 /usr/lib/i386-linux-gnu/libX11.so

    RAID0 Setup

    Now, of the three major determinants of compile speed (CPU, memory, and I/O) the choice of instance type has addressed the first two, and partly addressed the third. Given 4 ephemeral disks, and at the cost of a few CPU cycles, we can assemble them up in a (software) RAID0 setup.

    We will use the ‘multiple device administration’ tool (mdadm) for creating the softRAID. (Answer ‘y’ (yes) to the warning that the disks contain an ext2fs file system.) and will format it to ext4.

    apt-get install mdadm
    umount /mnt
    mdadm --create --verbose /dev/md0 --level=0 --raid-devices=4 /dev/xvdb /dev/xvdc /dev/xvdd /dev/xvde
    mkfs.ext4 /dev/md0
    mount /dev/md0 /mnt

    SWAP Setup

    The Android documentation recommends a combined total of 16GB of RAM + Swap. We have 7GB of RAM on this instance, but since we have an abundance of available space, we will add 20GB of swap space, on our new RAID0 device. I actually didn’t find the instance needing more than about 3GB of RAM at most during this procedure, but since the setup is easy, there is no harm having the SWAP available.

    dd if=/dev/zero of=/mnt/swapfile bs=10M count=2048
    mkswap /mnt/swapfile
    swapon /mnt/swapfile

     VirtualBox

    One of the last steps of the compilation process uses Virtualbox’s VBoxManage program to convert an img file to a vdi disk. You can omit this step and do the conversion manually on your own, it works just fine (although, the compile process will display an error at the end if you skip this step).

    echo deb http://download.virtualbox.org/virtualbox/debian oneiric contrib >> /etc/apt/sources.list
    wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -
    apt-get update
    apt-get install virtualbox-4.1

    Java

    mkdir -p /opt/java/64/ && cd $_
    wget http://download.oracle.com/otn-pub/java/jdk/6u29-b11/jdk-6u29-linux-x64.bin
    chmod +x jdk-6u29-linux-x64.bin
    ./jdk-6u29-linux-x64.bin

    Directory Setup

    mkdir -p /mnt/android/{bin,working_dir}
    chown -R ubuntu /mnt/android/

     
    We are going to throw in a optional modification that seems to improve the success rate of downloading the Android source:

    sysctl -w net.ipv4.tcp_window_scaling=0

     
    Finally, we exit the interactive sudo, and resume normal user operations:

    exit

    Prepare the Environment

    Note, we have finally logged out of the root user account – the rest of the steps are done as the user ‘ubuntu’.

    echo 'export PATH=/mnt/android/bin:/opt/java/64/jdk1.6.0_29/bin:$PATH' >> ~/.profile
    export PATH=/mnt/android/bin:/opt/java/64/jdk1.6.0_29/bin:$PATH

     
    (The first line above adds the new PATHs to our profile so that if we launch multiple sessions all will have them, the second applies it to our current session).

    Download the repo program, and make it executable:

    curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > /mnt/android/bin/repo
    chmod a+x /mnt/android/bin/repo
    cd /mnt/android/working_dir

    Get the Source

    At this point, we are ready to start obtaining the Android source. First we will initialize the repository – the process only takes a few seconds. When asked, enter a name (or alias) and an email address – they are only used if you commit code back to Android, so even a local version will suffice for now. Also, answer ‘y’ (yes) to the two questions.

    repo init -u https://android.googlesource.com/platform/manifest

     
    A quick note before proceeding: there is a parameter that shows up in many of the following commands ‘j’. It refers to the number of ‘parallel jobs’ that will be executed. Recommended values vary from <CPU Cores>+1 to 2x<CPU Cores>. There are 8 cores (20ECUs) on a c1.xlarge, so I used numbers between 12 and 16 for CPU limited tasks. For higher numbers, I found a high percent of CPU went was used by the kernel scheduler (i.e. high ‘sy’ value in top).

    Now to download the source itself – it is on the order of 6GB, so on a normal connection it would take a while – this instance however can download at 300Mbps, so you won’t need to keep this running overnight. This one isn’t CPU limited, so I limited the amount of parallel jobs. (There are some definite pauses in the process, but it completes fast enough). You can go to the next part while this downloads.

    repo sync -j4

    Some time stats:

    real    9m6.746s
    user    9m58.865s
    sys     2m47.034s

     
    Now that is a good reason for using EC2 – 9 minutes to download the entire Android source code!

    We will import the Android GPG key for authentication. The following command will wait for you to paste the key:

    gpg --import

    Copy and paste key (from: Android Open Source), press Enter and key in Ctrl+D (End of File) to finish.

    Building a new Kernel

    Since Android is meant for touchscreen devices, it doesn’t include support for a mouse pointer by default (although, it does, natively, support a mouse). We need to rebuild the kernel with mouse support if we want to use a mouse. (This is a compiling task, and although short, is CPU intensive – we can do it at the same time as the source download though, since that is more of a network limited task). There are, on the order of 1 million files, in about 230MB.

    cd /mnt/android
    git clone https://android.googlesource.com/kernel/goldfish

     
    This will create a new folder with the kernel source (code named ‘goldfish’)

    Again, some time stats:

    real    2m1.745s
    user    1m14.033s
    sys     0m14.389s

    We switch to the new directory, and checkout the target branch. This finishes in a few seconds:

    cd goldfish
    git checkout origin/android-goldfish-2.6.29
    real    0m14.239s
    user    0m2.596s
    sys     0m1.956s

    Now that we have the kernel source, we need to modify the configuration and rebuild it. There is a graphical interface that is included that will allow us to do this quite easily.

    cp arch/x86/configs/vbox_defconfig .config
    make CC=gcc-4.4 CXX=g++-4.4 ARCH=x86 menuconfig

    It will take a few seconds to compile and load. Once it does, use Up/Down arrows to navigate, enter to select (i.e. to expand), ‘y’ (or space) to include. Not being accustomed to the interface, I had expected that expanding a category would show all its sub-items. This is only true if you have selected the category first. An unselected category shows no entries – definitely drove me crazy for a time.

    To include mouse support:

    • Select/Expand ‘Device Drivers’
    • Select/Expand ‘Input Device Support’
    • Include ‘Mice’

    (You can then expand ‘Mice’ and see the included drivers, in particular, ‘PS/2 mouse’ should be selected)

    You can use ‘Esc’ (twice) to work your way out of the program, or repeatedly select ‘Exit’. Remember to save when asked.

    Having made the necessary change to the kernel configuration, we can now compile it. It doesn’t take too long, so I picked a low ‘j’ value. It is important to note that if you omit the CC and CCX parameters, that the compile will terminates prematurely (on this setup), without an explicit error, as it will use version 4.6.

    make CC=gcc-4.4 CXX=g++-4.4 ARCH=x86 -j8

     
    The above command ends with an output similar to the following :

    Root device is (202, 1)
    Setup is 11180 bytes (padded to 11264 bytes).
    System is 2401 kB
    CRC a247138c
    Kernel: arch/x86/boot/bzImage is ready  (#1)

     
    The path to the new kernel is displayed on the last line.

    The obligatory time stats:

    real    1m37.901s
    user    6m17.308s
    sys     1m51.835s

    Replace the Kernel

    If the download of the ICS source is complete at this point, you can carry on, otherwise, you will need to take a bit of a break while it finishes.

    For interest sake, the location of the kernel that is used by the vbox_x86 build configuration can be determined by the following:

    grep "LOCAL_KERNEL :=" /mnt/android/working_dir/build/target/board/vbox_x86/device.mk

    We will copy both our new bzImage and vmlinux to overwrite their ICS versions. I don’t think replacing the latter (vmlinux) is strictly necessary, but it worked fine replacing both.

    cp /mnt/android/goldfish/arch/x86/boot/bzImage /mnt/android/working_dir/prebuilt/android-x86/kernel/kernel-vbox
    cp /mnt/android/goldfish/vmlinux /mnt/android/working_dir/prebuilt/android-x86/kernel/vmlinux-vbox

    Setup DNS

    While networking does function on VirtualBox install of Android, it does not appear to get the default DNS servers. One way around this is to use some publicly available DNS servers, such as those provided by Google (8.8.8.8). We can hard code this into the default properties of our build using the following:

    echo "Net.eth0.dns1 = 8.8.8.8"  >> /mnt/android/working_dir/out/target/product/vbox_x86/root/default.prop
    echo "Net.dns1 = 8.8.8.8"  >> /mnt/android/working_dir/out/target/product/vbox_x86/root/default.prop

     
    We are now, just about ready to start building the code. Firstly, however, we need to finish setting up our environment.

    cd /mnt/android/working_dir
    . /mnt/android/working_dir/build/envsetup.sh

     
    Note: there is a space between the dot and first slash on the above command. The dot is a short form for the ‘source’ command.

    Setup the Compiler Cache

    As I got used to the layout of the Android code, I found that things didn’t always work out the first time – I sometimes had to compile the code more than once, making slight changes in between. Unfortunately, it takes around an hour to compile. You can greatly reduce the compile time for subsequent compilations (after the first) by use the compiler cache. To set up a 20GB cache, on our RAID disk we can run:

    export USE_CCACHE=1
    export CCACHE_DIR=/mnt/android/.ccache
    prebuilt/linux-x86/ccache/ccache -M 20G

     
    If you want to monitor the cache, you can do so using

    watch -n1 -d prebuilt/linux-x86/ccache/ccache -s

    Build ICS

    We are now ready to build. The first step is to select the target using lunch.

    lunch vbox_x86-eng

    This will output some information about the build, similar to that below:

    PLATFORM_VERSION_CODENAME=AOSP
    PLATFORM_VERSION=4.0.1.2.3.4.5.6.7.8.9
    TARGET_PRODUCT=vbox_x86
    TARGET_BUILD_VARIANT=eng
    TARGET_BUILD_TYPE=release
    TARGET_BUILD_APPS=
    TARGET_ARCH=x86
    TARGET_ARCH_VARIANT=x86
    HOST_ARCH=x86
    HOST_OS=linux
    HOST_BUILD_TYPE=release
    BUILD_ID=OPENMASTER

    To initialize the build itself, we run make, specifying the correct compiler. I opted to use a ‘j’ value of 12 which seemed to work reasonably.

    make CC=gcc-4.4 CXX=g++-4.4 -j12

     
    The above process takes just under an hour to complete, as per the time stats below:

    real    53m22.432s
    user    340m49.770s
    sys     38m32.665s

    Recompiling, however, (with the cache enabled) takes only about 15 minutes.

    The last lines of the output describe the location and size of the image:

    Install system fs image: out/target/product/vbox_x86/system.img
    out/target/product/vbox_x86/system.img+ total size is 268435456

    Build the VirtualBox Android Disk

    Finally, we build the VirtualBox image we will be using:

    make CC=gcc-4.4 CXX=g++-4.4 android_disk_vdi -j12

    This process finishes fairly quickly, taking only a few seconds, as below:

    real    0m35.250s
    user    0m20.629s
    sys     0m4.856s

    Three images are created (boot, system, userdata) and added to the android_disk.img file. Finally, the image is converted to a VDI format using the VirtualBox tools installed at the beginning. Output resembles the following:

    Copying images to specified partition offsets
    I/diskutils(32627): Writing RAW image 'out/target/product/vbox_x86/boot.img' to 'out/target/product/vbox_x86/android_disk.img' (offset=17563648)
    I/diskutils(32627): Wrote 2738176 bytes to out/target/product/vbox_x86/android_disk.img @ 17563648
    I/diskutils(32627): Writing RAW image 'out/target/product/vbox_x86/system.img' to 'out/target/product/vbox_x86/android_disk.img' (offset=28560384)
    I/diskutils(32627): Wrote 268435456 bytes to out/target/product/vbox_x86/android_disk.img @ 28560384
    I/diskutils(32627): Writing RAW image 'out/target/product/vbox_x86/userdata.img' to 'out/target/product/vbox_x86/android_disk.img' (offset=296996352)
    I/diskutils(32627): Wrote 52428800 bytes to out/target/product/vbox_x86/android_disk.img @ 296996352
    File edit complete. Wrote 3 images.
    Done with bootable android disk image -[ out/target/product/vbox_x86/android_disk.img ]-
    
    Converting from raw image file="out/target/product/vbox_x86/android_disk.img" to file="out/target/product/vbox_x86/android_disk.vdi"...
    Creating dynamic image with size 349425664 bytes (334MB)...
    Done with VirtualBox bootable disk image -[ out/target/product/vbox_x86/android_disk.vdi ]-

    Build the VirtualBox Android Installer

    Alternatively, you can create an Android Installer disk instead. The resulting process takes a bit longer, and produces a larger image. To do so, run the following (instead of the command above):

    make CC=gcc-4.4 CXX=g++-4.4 installer_vdi -j12

     
    End of the output:

    Converting from raw image file="out/target/product/vbox_x86/installer.img" to file="out/target/product/vbox_x86/installer.vdi"...
    Creating dynamic image with size 529080320 bytes (505MB)...
    Done with VirtualBox bootable installer image -[ out/target/product/vbox_x86/installer.vdi ]-

     
    Time information:

    real    0m53.854s
    user    0m21.225s
    sys     0m8.601s

    Converting an IMG to a VDI

    If you omitted the VirtualBox install, you can use a command like the following (on Windows) to make the conversion:

    "C:Program FilesOracleVirtualBoxVBoxManage" convertfromraw -format VDI android_disk.img android_disk.vdi

    After all of the above, the relevant files that can be found in out/target/product/vbox_x86 are (the .tgz is from the next step):

    -rw-rw-r-- 1 ubuntu ubuntu 349425664 2011-11-27 05:32 android_disk.img
    -rw------- 1 ubuntu ubuntu 188751872 2011-11-27 05:45 android_disk.vdi
    -rw-rw-r-- 1 ubuntu ubuntu 195125495 2011-11-27 06:01 android_images.tgz
    -rw-rw-r-- 1 ubuntu ubuntu   2738176 2011-11-27 05:28 boot.img
    -rw-rw-r-- 1 ubuntu ubuntu 529080320 2011-11-27 05:52 installer.img
    -rw------- 1 ubuntu ubuntu 196091904 2011-11-27 05:52 installer.vdi
    -rw-rw-r-- 1 ubuntu ubuntu    232451 2011-11-27 05:28 ramdisk.img
    -rw-r--r-- 1 ubuntu ubuntu 268435456 2011-11-27 05:28 system.img
    -rw-r--r-- 1 ubuntu ubuntu  52428800 2011-11-27 05:05 userdata.img

    Uploading to S3

    Given that time an item of consideration on EC2, we do not want to keep our instance running while we download and play around with the images. As such, we can upload them to S3, and then terminate the instance. The simplest way to accomplish this is to use Tim Kay’s aws script:

    Create a file with as below, with your Access Key ID (line 1) and Secret Access Key (line 2), and restricted permissions:

    vi ~/.awssecret
    chmod 600 ~/.awssecret

     
    Download the script and install:

    curl https://raw.github.com/timkay/aws/master/aws -o aws
    perl aws –install

     
    Compress the images (significant space savings), and upload to S3 (if you don’t already have an S3 bucket, create one first):

    cd out/target/product/vbox_x86
    tar -czvf android_images.tgz installer.vdi android_disk.vdi
    s3put bucket_name/android_images.tgz /mnt/android/working_dir/out/target/product/vbox_x86/android_images.tgz

     
    Once the above command exits, you can terminate your instance if you do not anticipate needing to make changes to your image. Of course, if you expect to need changes, keep the instance around because everything is already setup, and the compiler cache will save a lot of time.

    Final Notes

    • RAM usage never went above 50% – it was typically on the order of 3GB, swap was unused
    • CPU was maxed out when compiling (typically 85% us, and 12% sy) – load average hovered around 12 while compiling. Typical steal values were 2-3%
    • The advantage of this approach is that AWS doesn’t charge for data transfer in, and ephemeral disks have no cost for allocated space or I/Os, meaning that you only pay for the instance time and the download of the final product.

    VirtualBox Setup

    Once you have your compiled image, you need to setup VirtualBox to use it.

    • General:
      • Operating System: Linux
      • Version: Other Linux
    • System:
      • Boot from Hard Disk
      • Allocate about 1GB of memory (although, it will run on much less)
      • Enable PAE/NX
    • Display:
      • Allocate some memory to graphics – I go with 64MB
    • Storage:
      • Add your android_disk.vdi as an IDE Hard Disk (not a SATA disk) – remove any SATA controllers
    • Network:
      • Enable Adapter #1 and setup as Bridged Adapter (you need to enable this during the setup of VirtualBox before it can be used here)

    Save the settings and start the virtual machine. You may get an error about sound and 16bit displays, but dismiss them for the time being.

    Once it boots up, you may get an error regarding low battery (i.e. Connect your Charger), you can dismiss the page using Ctrl+Esc. To capture your mouse, just click inside the VirtualBox window (to uncapture press the right Ctrl key – or whatever your host key is if you changed it).

    If you want to use the installer instead of the android_disk.vdi, you should create an additional empty virtual hard drive to which you can install. Select the installer_disk.vdi, using F12. At the GRUB screen, choose “Android Install to /dev/sda from /dev/sdb”, and reboot (use command ‘reboot’) when done, booting from your new device (use F12 to change if needed.)

    The speed of the virtual machine was fairly good – everything seemed responsive enough.

    Known problems:

    • Sound – haven’t tested it, but I don’t think it would work without some modifications
    • Stability – not so great – it runs, but you do see the occasional error – luckily it just lets you continue and you don’t need to restart the machine.
    • Storage – the default disk needs to be made larger – this is easy enough, but would be worthwhile change.
    • Battery – displaying as discharged, and starts with Connect Charger screen.
    • Network – wireless doesn’t display as connected (even though there is network access).
    • Desktop – can’t set a background – just displays as black with the widgets and controls.
    • Haven’t yet had any success playing a video

  • 相关阅读:
    计算机最小单位
    api接口调用
    STM32SystemInit函数
    关于 Verilog 的 TimeScale
    破获ARM64位CPU下linux crash要案之神技能:手动恢复函数调用栈
    芯片后仿
    破获ARM64位CPU下linux crash要案之神技能:手动恢复函数调用栈
    HardFault定位方法和步骤
    BSP和SDK的区别
    armCPSR寄存器
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645395.html
Copyright © 2020-2023  润新知