Install ARM Translation (libhoudini) on official Android Emulator - android

I have a small application that uses a native ARM shared library (.so). When using Genymotion, I can successfuly install the ARM translation package (just by dropping the ZIP file) and the app runs fine on a x86-based emulator.
Now I have the need to run the same app in a headless linux server, which is not supported by Genymotion. I downloaded the official google emulator and corresponding system image. After extracting the files from zip archive and uploading to /system partition, I can run houdini --version, however the application won't install (INSTALL_FAILED_NO_MATCHING_ABIS).
Can you please guide me how to run the app which contains ARM library on the official google x86 emulator?

What is the output of houdini --version ?
When you install applications PackageManager checks ABI of the app(which libraries are contained in the apk .so files) and the ABI of the system (which type of libraries system supports)
if you run getprop | grep -i abi
getprop | grep -i abi
[ro.product.cpu.abi]: [x86]
[ro.product.cpu.abilist]: [x86,armeabi-v7a,armeabi]
[ro.product.cpu.abilist32]: [x86,armeabi-v7a,armeabi]
[ro.product.cpu.abilist64]: []
In this output, the system supports 32 bit .so files of x86, armeabi-v7a and armeabi type.
Please check this output on your device. Most probably there will be no mention of armeabi in this output.
So when PackageManager tries to install ARM app and checks that this ABI is not supported, it throws INSTALL_FAILED_NO_MATCHING_ABIS error.
So you will have to fix the system ABIs.
Edit the file /system/build.prop to add ARM support, in ro.product.cpu.abilist and ro.product.cpu.abilist32.
If you are running 64 bit Android, you will have to change these lines.
ro.product.cpu.abilist=x86_64,x86,arm64-v8a,armeabi-v7a,armeabi
ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
ro.product.cpu.abilist64=x86_64,arm64-v8a

Related

Install build tools on arm64 doesn't work

I've been trying to install sdkmanager "build-tools;30.0.2" on an arm64 processor (ampere CPU).
But every time I get this:
Warning: Dependant package with key emulator not found!
Warning: Unable to compute a complete list of dependencies.
I'm trying to build an app and I get this error:
Failed to install the following SDK components:
build-tools;30.0.2 Android SDK Build-Tools 30.0.2
Edit: I think the problem is the package emulator isn't available. I tried downloading it from here but sdkmanager didn't recognize it.
(Assumption: CMD Line Tools are installed)
SDK manager package "emulator" is missing on ARM
Workaround:
Download emulator from Google for Linux: https://developer.android.com/studio/emulator_archive
Extract it to $ANDROID_SDK_HOME/emulator
You need a license file called "package.xml" which is automatically created when you download it via Android Studio UI SDK Manager, you copy that file to $ANDROID_SDK_HOME/emulator and change all version numbers related to the version you have downloaded:
... <revision><major>31</major><minor>1</minor><micro>4</micro></revision>...
I was able to install build-tools using sdkmanager on arm64 by copying to the sdk dir emulator from
https://chromium.googlesource.com/android_tools/+/refs/heads/main/sdk/emulator/
Unfortunately the installed packages seem to be not compiled for arm64 and are not working.
Anybody help to cross compile emulator for arm64 ?
https://developer.android.com/studio/releases/emulator
Emulator for ARM64 hosts
Linux emulator source code now supports cross compilation from x86_64 to arm64 hosts, enabling running arm64 system images with KVM virtualization. Currently, only -gpu swiftshader_indirect (Swiftshader arm64 host rendering) is supported, but a compatible set of host GPU libEGL/libGLESv2 libraries may also be used by replacing lib64/gles_swiftshader with them and then relaunching with -gpu swiftshader_indirect. Snapshots may also not be working (add -no-snapshot to the command line).
Instructions:
cd emu
repo init -u https://android.googlesource.com/platform/manifest -b emu-master-dev --depth=1
repo sync -qcj 12
cd external/qemu
pip install absl-py
pip install urlfetch
sudo apt-get install crossbuild-essential-arm64
python android/build/python/cmake.py --noqtwebengine --noshowprefixforinfo --target linux_aarch64
Anybody try this one ?
I got error and unable install one toolm

"dlopen failed: is 32-bit instead of 64-bit" in tests only

I'm having a set or Gradle modules that uses the core module based on c++ code:
Core (C++ with JNI glue, aar with libxyz-jni.so)
Tests (Android instrumentation tests)
App (regular Android app)
Core module includes native 32 bit libxyz-jni.so compiled for armeabi-v7a and x86 and is compiled to aar. It does not have arm64 libraries.
App module depends on Core and is working on arm64 hardware device without any issues (is able to load libxyz-jni.so)
Tests depends on Core and fails to load libxyz-jni.so (with System.loadLibrary(..)) with following error:
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/package.tests.test-2/lib/arm/libxyz-jni.so" is 32-bit instead of 64-bit.
I've checked tests apk not to contain any arch except armeabi-v7a and x86. The tests can run in android emulator but can't on 64 bit hardware device with Android Nougat. The App can run on arm64 device.
That's the difference between tests and app in terms of loading library?
You should check to see what libraries your app is using at runtime. You can do this with these commands:
# get your running pid
adb shell ps | grep <your package name> | tr -s ' ' | cut -d ' ' -f 2
32333
adb shell lsof | grep 32333 | grep so
.xxx 32333 u0_a222 mem REG 259,30 133152 2629 /system/lib64/libcompiler_rt.so
.xxx 32333 u0_a222 mem REG 259,30 30824 2759 /system/lib64/libmemalloc.so
As you can see in this case Android has loaded lib64 libraries. If you want it to default to loading 32-bit libraries, you need to have lib/armeabi-v7a/lib.so in your APK.
If you have your libraries somewhere else in the APK, and you extract, and load dynamically, Android won't know they are 32bit.

How to force Android application to use either 32bit or 64 bit libraries

On a Android device with 64bit ARM, would have two variants of many libraries, 32bit and 64 bit, and their performance could be different. I want to know if there is a way to force the application to use either 32bit or 64bit libraries.
ABI can be specified when the apk is installed.
adb install --abi <path to apk>
In case ARM device,
To run in 32 bit mode install using,
adb install --abi armeabi-v7a <path to apk>
To run in 64 bit mode install using,
adb install --abi arm64-v8a <path to apk>
If your apk is written in pure java (without jni), on 64-bit-primiary/32-bit-secondary Android OS, your app will always run in 64 bit mode by default, but if you want your app to run in 32 bit mode, you can create a dummy *.so file and put it under <your apk name>/libs/armeabi/ to force AndroidRuntime to create a 32 bit VM for your app
If some function of your apk is written in jni (there's any *.so file in <your apk name>/libs/ folder), you can use following command to make it run in 64 or 32 bit VM:
To run in 32 bit mode, because only 32 bit native libs will be installed
adb shell install --abi armeabi-v7a <path to your apk>
To run in 64 bit mode, because only 64 bit native libs will be installed
adb shell install --abi arm64-v8a <path to your apk>
https://source.android.com/source/64-bit-builds.html
Try this in you Android.mk
LOCAL_MULTILIB := 32 // or 64

Target exe for Android ABI(ndk build)

I have an android system with two different CPU ABI - armeabi-v7a and x64 .For which one I have to build the application code to get it working.My application (in c language) anyway doesnt run for either of the platforms.
OR is there any common tool chain with which I can build the same.
arm-eabi-gcc?
The NDK contains all the toolchains you need to run your program on Android platforms.
To setup the architectures you need to compile to, you should set the APP_ABI variable inside Application.mk or pass it to the ndk-build command.
APP_ABI:=all will make your ndk project being built for all the supported architectures: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64.
You can also list which architectures you want to build for: APP_ABI:= x86_64 x86 armeabi-v7a arm64-v8a and also use all32 and all64 as shortcuts to all the 32-bit and all the 64-bit architectures.
To determine which platforms are supported by a target device, you can call adb shell getprop ro.product.cpu.abi (preferred arch) and adb shell getprop ro.product.cpu.abi2 (second arch).
Starting with Android 5.0, use adb shell getprop ro.product.cpu.abilist instead, that returns a list of all the supported ABIs, sorted in preference order.
I don't think you can target completely different architecture (arm and x86) with android provided ndk (cross-compilers). You can target multiple ABI supported by arm with following variable
TARGET_ARCH_ABI
possible values are:
armeabi For ARMv5TE
armeabi-v7a
for more details you can check this link.
To run in x86 or amd64 system you can normally use a gcc to create the .so file and use JNI to test functionally (remember Android F/W will be unavailable there).
If you are looking for rapid building-testing cycle I think it's better for you to use an x86 based emulator like AndroVM (now Genymotion). In that way you can write code for android device and test it real quick.

How to debug an Android project built without ndk-build

I try to debug a very basic example Qt 5.3 Android native C++ project, and I would like to debug it on the target without using QtCreator or any other IDE like Eclipse but only NDK tools.
This project is compiled through QtCreator tools using Android platform target, in debug mode (-O0, -g), using NDK toolchain, BUT NOT ndk-build.
Therefore I got my .apk, the application itself has been installed on the target and works, everything is fine up to that point. Now I want to execute it in debug mode using NDK tools.
I would like to use ndk-gdb as this seems to be one of the most obvious ways, therefore:
- I created manually required files under my main project directory:
bin
src
res
...
jni
|-- Android.mk
`-- Application.mk
libs
|-- armeabi-v7a
| |-- gdbserver
| |-- gdb.setup
The tree above only underline the files I added by hand, given that they are normally created by ndk-gdb.
Under the 'libs' directory is also stored the native library of the project, called by a simple java wrapper.
jni/Android.mk and jni/Application.mk contains the same single line:
APP_ABI := armeabi-v7a
gdb.setup:
set solib-search-path ./libs/armeabi-v7a
directory <myrootdir>/NDKToolchain/sysroot/usr/include <myrootdir>/NDKToolchain/include/c++/4.6 <myrootdir>/NDKToolchain/include/c++/4.6/arm-linux-androideabi/armv7-a [...]
I checked that the target was connected and accessible by installing the application using adb:
% adb install -r bin/QtApp-debug.apk
It worked ('success'), which I could check directly on the target.
Then when I try to run ndk-gdb, it failed:
% ndk-gdb --start --nowait --verbose
WARNING: The shell running this script isn't bash. Although we try to avoid bashism in scripts, things can happen.
ndk-gdb: 84: Bad substitution
Android NDK installation path: [...]
Using default adb command: [...]/sdk/platform-tools//adb
ADB version found: Android Debug Bridge version 1.0.31
Using ADB flags:
Using JDB command:
Using auto-detected project path: .
Found package name: org.qtproject.example.fridgemagnets
ABIs targetted by application: armeabi-v7a
Device API Level: 18
Device CPU ABIs: armeabi-v7a armeabi
[: 564: 1: unexpected operator
Compatible device ABI: armeabi-v7a
Using gdb setup init: ./libs/armeabi-v7a/gdb.setup
Using toolchain prefix: [...]/ndk/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
Using app out directory: ./libs/armeabi-v7a
Found debuggable flag: false
Found gdb.setup under libs/armeabi-v7a, assuming app was built with NDK_DEBUG=1
ERROR: Could not extract package's data directory. Are you sure that
your installed application is debuggable?
A previous run of ndk-gdb showed me that for some reason it wanted to use ./obj/local/armeabi-v7a as "app out directory", while I set it in gdb.set to ./libs/armeabi-v7a, therefore I had to hack the ndk-gdb script to force it to use the path I chosed. I don't believe this is related to my real issue (?)
Given that I didn't use ndk-build, I believe that my attempt to use ndk-gdb is hopeless, or at least that it will ask me too much work and hacking of NDK scripts which I don't want to do.
Thus 2 questions:
Did I miss something during my build or deployment for getting a
debuggable app ? I know that debuggable flag in Manifest being
'false' is not necessarily an issue, as I built my app with debug
flags. BTW this seems to be confirmed by the fact that the error
message I get is not related to that flag but to the fact that the
script seems to exepect a DATA_DIR folder somewhere...
Is there a
way to debug my application, without using ndk-gdb (and any IDE),
but for example just 'gdb' ?
Thanks in advance
Question 1:
I know that as of SDK r8 you can invoke ant with release or debug. Building with the debug flag might package or run your application differently. Thus allowing or disallowing debugging? This seems like it might be the issue.
Question 2:
From what I understand ndk-gdb does a lot of setup and communication with adb to allow debugging your application, as you may have seen from the script. I wouldn't suggest going down the rabbit hole of not using it.

Categories

Resources