May 28, 2013

android emulator x86 with google maps apis

Ok, this night's question is:
can we definitely have an android emulator image using x86 cpu (to exploit kvm acceleration) and google maps support?
The answer is: yes.
But, as always, we could have less pain banging our head against the wall.

However, here the tricks.

  1. Create two avd image, an *arm* ones and an *intel* ones, from shell or using eclipse tools, and assume their names are "ga17_tablet10_arm" and "ga17_tablet10_intel"
    • ga = "google apis"
    • 17 = android selected version
    • tablet10 = a 10'' 1280x800 tablet
    • arm/intel = obviously, isn't?)
    (If *avd" image is already present, skip first creation)
    export ARM_NAME="ga17_tablet10_arm"
    export INTEL_NAME="ga17_tablet10_intel"
    
    or choose different names
  2. Then we have to copy some files from arm instance.
    So, start the avd image and do the stuff [emulator -avd "$ARM_NAME" &]
    Assuming we're working in a dir with enough space (we need about 350mb), we must have a tree as:
    [k0smik0@n-johnny-5-iii from_ga17_arm]$ find system/ -type d
    system/
    system/app
    system/etc
    system/etc/permissions
    system/framework
    
    so
    mkdir -p system/app system/etc/permissions system/framework
  3. Now we have to pull down these files (change ARM_EMU_ID with yours, grabbing it from "adb devices"):
    export ARM_EMU_ID=emulator-5554;
    adb -s $ARM_EMU_ID pull /system/etc/permissions/com.google.android.maps.xml system/etc/permissions
    adb -s $ARM_EMU_ID pull /system/framework/com.google.android.maps.jar system/framework
    adb -s $ARM_EMU_ID pull /system/app/FusedLocation.apk system/app
    adb -s $ARM_EMU_ID pull /system/app/GoogleLoginService.apk system/app
    adb -s $ARM_EMU_ID pull /system/app/GoogleServicesFramework.apk system/app
    adb -s $ARM_EMU_ID pull /system/app/GpsLocationTest.apk system/app
    adb -s $ARM_EMU_ID pull /system/app/Maps.apk system/app
    adb -s $ARM_EMU_ID pull /system/app/NetworkLocation.apk system/app
    
  4. Then, we have to push these files in *x86/intel* avd image, in same directories:
    assuming:
    1. you're using a 64 linux with kvm acceleration (hence "emulator64-x86")
    2. "$INTEL_NAME" is env variable for intel avd image name (see 1, above)
    3. 300 (mb) is enough space you need - and it must be greater than what you have specified on image creation (item 1) [default is 260mb]
    achtung! you have to change data partition size before you start emulator, because new system image will be saved in /data; as you can see u have to increase it:
    grep -ni dataPartition\.size ~/.android/avd/"$INTEL_NAME".avd/*ini
    config.ini:3:disk.dataPartition.size=200M
    hardware-qemu.ini:40:disk.dataPartition.size = 200m 
    
    so change these values in config.ini and hardware-qemu.ini [vim?ed?sed?] from 200M to 400M (or higher, depends how you want expand /system). and now:
    emulator64-x86 -partition-size 300 -netspeed full -netdelay none -no-boot-anim -no-audio -gpu on -avd $INTEL_NAME -qemu -enable-kvm &
    export INTEL_EMU_ID=emulator-5556; # replace with yours
    sleep 10; # adb connection takes some seconds
    adb remount
    adb -s $INTEL_EMU_ID push system/etc/permissions/com.google.android.maps.xml /system/etc/permissions/
    adb -s $INTEL_EMU_ID push system/framework/com.google.android.maps.jar /system/framework/
    for i in system/app/*; do adb -s $INTEL_EMU_ID push $i /system/app ; done
    
  5. Is it enough? No, obviously. These new changes don't remain after avd instance reboot, therefore we have to save /system partition.
    So, save this mkfs.yaffs2.x86 and push it to the device:
    wget https://android-group-korea.googlecode.com/files/mkfs.yaffs2.x86
    adb -s $INTEL_EMU_ID push mkfs.yaffs2.x86 /data
    
  6. create a new system image from existing ones:
    adb -s $INTEL_EMU_ID shell chmod 755 /data/mkfs.yaffs2.x86
    adb -s $INTEL_EMU_ID shell /data/mkfs.yaffs2.x86 /system /data/system.img
    
    and now save new image (this could take a while, so get a beer):
    adb -s $INTEL_EMU_ID pull /data/system.img
    
    just for info: mine reports "829 KB/s (304309632 bytes [~291mb] in 358.296s [~6s])"
    1. ...breathe, it's almost completed.

      Now, choice if u want use new system.img only this specific intel instance, or globally, for new image creations
      * in this second case, in virtual manager ("android avd"), if you select "Google APIs (Google Inc.) - Version XY" in target, you could see a "Intel Atom (x86)" item in cpu/abi, not only "ARM (armeabi-v7a)" *
    2. local/specific instance

      copy system.img in avd directory:
      cp -a system.img ~/.android/avd/"$INTEL_NAME".avd/
      
    3. global method

      copy this new system.img in $ANDROID_SDK/add-ons/addon-google_apis-google-$SELECTED_WORKING_VERSION/images/x86 - assuming that:
      - ANDROID_SDK is your android directory installation
      - SELECTED_WORKING_VERSION is android release you have choice when you created avd images (I used jellybean_mr1 = 17 -- see item 1)
      and copy other files from x86 (without maps support) sdk dir, that is:
      export ANDROID_SDK=/your/android/installation/dir;
      export SELECTED_WORKING_VERSION=17;
      cp -a $ANDROID_SDK/system-images/android-$SELECTED_WORKING_VERSION/x86/* $ANDROID_SDK/add-ons/addon-google_apis-google-$SELECTED_WORKING_VERSION/images/x86
      cp -f system.img $ANDROID_SDK/add-ons/addon-google_apis-google-$SELECTED_WORKING_VERSION/images/x86
      
  7. and finally kill emulators
    adb -s $INTEL_EMU_ID emu kill
    adb -s $ARM_EMU_ID emu kill
    


enjoy this new one intel emulator with google maps ;D




credits to: http://codebutler.com/2012/10/10/configuring-a-usable-android-emulator/