It's not clearly mentioned but I assume you are talking about ARM architecture. ***“32-bit Android OS”*** means a 32-bit kernel and the collection of ELF binaries and libraries which are compiled to run on 32-bit processor. This middleware stack particularly includes `app_process` binary which runs with name `zygote` and hosts the complete application framework of Android. It forks Java Virtual Machines (for every app) in which Dalvik EXecutable (`.dex`) code runs which is neither 32-bit nor 64-bit. But the JVMs are native processes; either 32 or 64-bit depending on the JNI libraries the app contains. We can run 32-bit OS on 64-bit device if 64-bit: 1. Processor supports running 32-bit code which is usually the case because backward compatibility is desired, but not always. 2. Kernel supports running 32-bit code because unlike bare-metal hypervisors we - the processes on Android - don't deal directly with hardware. PROCESSOR'S BITNESS --- Every 64-bit processor's support for 32-bit execution isn't universal. For instance Samsumg Exynos 9 Series 982x SoCs contain [Cortex-A55][1] and A75 which (are based on ARMv8.x and they) have support for `aarch64` and `aarch32`. On the other hand Qualcomm's [Centriq 2400][2] SoCs and Cavium's [Thunder X2][3] SoCs also include ARMv8.x processors but without `aarch32` support. In order to find device architecture, we can read `/proc/cpuinfo` which [exposes][4] information from [Main ID register][5] of the processor. ``` ~$ cat /proc/cpuinfo ... CPU implementer : 0x41 CPU architecture: 8 ... CPU part : 0xd03 ... Hardware : Qualcomm Technologies, Inc MSM8953 ``` But there in no direct information like [`lm`][6] flag to confirm 32/64-bit support. So we need to get technical details of hardware. As per the [requirements][7] from Google, `CPU architecture: 8` indicates that it's a `ARMv8` device. Also see [this commit][8]. And [here][9] is the hex to human readable decoding map which `lscpu` command uses. ``` ~$ lscpu | grep -E 'Vendor |Model ' Vendor ID: ARM Model name: Cortex-A53 ``` Other possible ways to get SoC information: ``` ~$ cat /sys/firmware/devicetree/base/model Qualcomm Technologies, Inc. MSM8953 + PMI8950 QRD SKU3 ``` ``` ~$ cat /sys/devices/soc0/{vendor,family,machine} Qualcomm Snapdragon MSM8953 ``` It's evident from technical specifications of Qualcomm Snapdragon 625 ([MSM 8953][10]) and [Cortex-53][11] that it's based on ARMv8 architecture, which can process both instruction sets: `aarch64` and `aarch32`. KERNEL'S BITNESS --- When `arm64` support was [added][12] to Linux kernel, 32-bit compatibility mode was also included. If kernel is built with `IKCONFIG_PROC`, confirm by: ``` ~# zcat /proc/config.gz | grep -E 'CONFIG_ARM64=|CONFIG_COMPAT=|BINFMT' CONFIG_ARM64=y CONFIG_COMPAT=y CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y CONFIG_BINFMT_SCRIPT=y ``` So the 64-bit ELF files are executed natively with [binfmt_elf][13] while 32-bit ELF files are executed with [compat_binfmt_elf][14]. See details in [this answer][15]. Usually `uname -m` is used to find the architecture of device supported by kernel. It shows the persoanlity ([execution domain][16]) of the process which defaults to kernel's primary architecture (`PER_LINUX` ). But Linux kernel supports changing [*persoanlity*][17], so this approach can be confusing: ``` ~$ uname -m aarch64 ~$ setarch linux32 uname -m armv8l ``` In latter command `uname` is running under 32-bit [compatible personality][18]. The same would happen if you use some app - like [this][19] - which [runs][20] with `LINUX32` personality, no matter even if kernel and `uname` binaries are 64-bit. For details see [this][21] and [this][22]. `lscpu` also confirms CPU operation modes using same phenomenon. USERCODE BITNESS --- Now coming to the userspace, `init` is the very first process run by kernel. Lets check its bitness. If the 5th byte is 1 it's 32-bit ELF file, if it's 2 the binary is 64-bit: ``` ~# hexdump -n5 /proc/1/exe 0000000 457f 464c 0002 ``` Or use `file` command: ``` ~# file /proc/1/exe /proc/1/exe: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked ... ``` Similarly check bitness of other vital OS binaries/libraries: ``` ~$ file /system/lib*/libc.so /system/lib/libc.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked ... /system/lib64/libc.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked ... ``` ``` ~$ file /system/bin/linker* /system/bin/linker: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked ... /system/bin/linker64: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked ... ``` OS maintains 64-bit as well as 32-bit libraries and dynamic linker because apps may contain both types of binary code (though the major part must be Java/Dalvik bytecode). For instance the `dnsmasq` program which serves as DHCP server on hotspot is a 64 bit binary while Google Play Services uses a 32-bit library: ``` ~# readelf -a /system/bin/dnsmasq Class: ELF64 Type: DYN (Shared object file) Machine: AArch64 [Requesting program interpreter: /system/bin/linker64] 0x0000000000000001 (NEEDED) Shared library: [libc.so] ``` ``` ~# readelf -a /data/data/com.google.android.gms/app_vision/ocr/libs/armeabi-v7a/libocr.so Class: ELF32 Type: DYN (Shared object file) Machine: ARM [Requesting program interpreter: /system/bin/linker] 0x00000001 (NEEDED) Shared library: [libc.so] ``` Similarly it's not uncommon to have 32-bit binary blobs from OEMs / SoC vendors on 64-bit ROMs. Even some basic components of AOSP aren't 64-bit supported. Take example of [`audioserver`][23]. To see all processes running in 32-bit mode: ``` ~# for p in $(ps -p 2 --ppid 2 --deselect -o pid=); do grep -qE '^.{8}[^-]' /proc/$p/maps || echo $p; done | xargs ps f -o pid,cmd -p PID CMD 3359 /system/bin/mediaserver 3358 /system/bin/cameraserver 3357 /system/bin/audioserver 3356 zygote 5081 \_ webview_zygote 20824 | \_ com.android.webview:sandboxed_process0 18609 \_ it.colucciweb.vpnclient 3354 /vendor/bin/hw/[email protected] 2665 /vendor/bin/hw/[email protected] 2335 /vendor/bin/mm-qcamera-daemon 2278 /vendor/bin/wifidisplayhalservice 2277 media.codec hw/[email protected] 2244 /system/bin/drmserver 777 /vendor/bin/hw/[email protected] 773 /vendor/bin/hw/[email protected] ``` Out of these only one is a VPN app, rest are OS processes. CONCLUSION --- So it's clear that even if core OS is 64-bit, there are possibly large number of processes running as 32-bit, though each process and its linked libraries have to be be homogeneous; either 32 or 64-bit. And there's no constraint if the OS doesn't include 64-bit code at all, but you won't find many instances because OEMs ship 64-bit devices with 64-bit binary code. It's more about business than performance; that's what a user pays for. However exceptions do exist where business isn't that much involved: [Raspberry Pi 3 has 64-bit CPU, but 32-bit Raspbian OS][24]. Android phones examples from past include Galaxy E5, LG G Stylo, Moto G5 Plus, Lenovo A6000 Plus and MT6735 devices. But now Android is [moving][26] towards 64-bit and some devices may [drop][27] 32-bit support gradually. >Does the same case happens for Android? Is there a 32-bit and a 64-bit version for the same 64-bit device? Yes, take example of [Moto G4 Plus][25]. --- **RELATED:** [Android apps for “armeabi-v7a” and “x86” architecture: SoC vs. Processor vs. ABI][28] [1]: https://developer.arm.com/ip-products/processors/cortex-a/cortex-a55 [2]: https://www.anandtech.com/show/11737/analyzing-falkors-microarchitecture-a-deep-dive-into-qualcomms-centriq-2400-for-windows-server-and-linux [3]: https://en.wikichip.org/wiki/cavium/thunderx2 [4]: https://community.arm.com/developer/tools-software/oss-platforms/w/docs/245/cpufreq-dvfs [5]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/CIHFAACD.html [6]: https://en.wikipedia.org/wiki/CPUID#EAX.3D80000001h:_Extended_Processor_Info_and_Feature_Bits [7]: https://source.android.com/compatibility/10/android-10-cdd#3_3_2_32-bit_arm_native_code_compatibility [8]: https://android.googlesource.com/kernel/common/+/93f22300975017f18c286899e8b98b5d843fe118 [9]: https://github.com/karelzak/util-linux/blob/master/sys-utils/lscpu-arm.c [10]: https://www.qualcomm.com/products/snapdragon-625-mobile-platform [11]: https://developer.arm.com/products/processors/cortex-a/cortex-a53 [12]: https://github.com/torvalds/linux/commit/8c2c3df31e3b87cb5348e48776c366ebd1dc5a7a [13]: https://github.com/torvalds/linux/blob/master/fs/Kconfig.binfmt#L5 [14]: https://github.com/torvalds/linux/blob/master/fs/compat_binfmt_elf.c#L3 [15]: https://stackoverflow.com/a/23295968/9165920). [16]: https://www.halolinux.us/kernel-reference/execution-domains.html [17]: http://man7.org/linux/man-pages/man2/personality.2.html [18]: https://android.googlesource.com/kernel/common/+/refs/heads/android-4.19/arch/arm64/include/asm/compat.h#32 [19]: https://play.google.com/store/apps/details?id=jackpal.androidterm [20]: https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-9.0.0_r47/core/java/android/content/pm/ApplicationInfo.java#870 [21]: https://stackoverflow.com/a/45125525/9165920 [22]: https://en.m.wikipedia.org/wiki/Uname#Examples [23]: https://www.mail-archive.com/[email protected]/msg20926.html [24]: http://linuxgizmos.com/raspberry-pi-3-has-a-64-bit-cpu-but-a-32-bit-raspbian-os [25]: https://www.xda-developers.com/moto-g4-plus-64-bit-custom-roms/ [26]: https://developer.android.com/distribute/best-practices/develop/64-bit [27]: https://android.googlesource.com/platform/build/+/1ac8a6df9a8ad749e40c5a0f21cd75906a3bcff9 [28]: https://android.stackexchange.com/a/208132/218526