Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6abcbb7
Add live Android sensor-list probe
isomorphisms Sep 12, 2026
0db76bf
Document live Android sensor acceptance boundary
isomorphisms Sep 12, 2026
ef9bd33
Make Android sensor probe cloud-buildable
isomorphisms Sep 12, 2026
3403363
Add link-only libandroid sensor stub
isomorphisms Sep 12, 2026
7be713c
Add cloud-built ARMv7 Android sensor probe
isomorphisms Sep 12, 2026
1609c30
Record ARMv7 sensor probe checksum
isomorphisms Sep 12, 2026
20c8bdb
Keep Android compilation off the phone
isomorphisms Sep 12, 2026
b9d5707
Move sensors source into Grease command tree
isomorphisms Sep 12, 2026
68bad08
Move libandroid link stub with sensors command
isomorphisms Sep 12, 2026
b807711
Move ARMv7 sensor artifact checksum
isomorphisms Sep 12, 2026
7aad7fd
Move ARMv7 sensor artifact into command tree
isomorphisms Sep 12, 2026
6266849
Restore exact verified ARMv7 sensor artifact bytes
isomorphisms Sep 12, 2026
06f1770
Promote live sensor probe to Grease command
isomorphisms Sep 12, 2026
63ef409
Remove obsolete sensor experiment location
isomorphisms Sep 12, 2026
4420dd2
Remove obsolete sensor experiment location
isomorphisms Sep 12, 2026
a6ad8b5
Remove obsolete sensor experiment location
isomorphisms Sep 12, 2026
800120f
Remove obsolete sensor experiment location
isomorphisms Sep 12, 2026
bff1856
Remove obsolete sensor experiment location
isomorphisms Sep 12, 2026
0c0c560
ci: run cpp-spec on GitHub Ubuntu
isomorphisms Sep 14, 2026
bd19f30
ci: use Oils GitHub Ubuntu harness
isomorphisms Sep 14, 2026
2035328
Merge current main into android sensors branch
isomorphisms Sep 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions commands/sensors/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# `sensors`

`sensors` is a Grease hardware command, not an Android experiment. Its job is to enumerate sensing hardware through the best available platform adapter while keeping the command meaning independent of that adapter.

The first implementation is Android ARMv7. It reaches the public native Android sensor boundary through the phone's real `libandroid.so` and prints tab-separated metadata.

A physical Android Go phone has now executed the exact cross-built artifact carried here and returned its real sensor list. The observed run reported `count 0x00000026` and included the phone's accelerometer plus the vendor's gesture/orientation sensors. That device-specific count and those names are evidence from one phone, not values to bake into tests.

## Phone workflow

Do not install Clang or the Android NDK on the phone. The phone is an execution target only: fetch the already-built ARMv7 executable, verify it, install it in the Termux command directory, and run `sensors`.

The repository carries the executable as `sensors.armv7.b64` because this small artifact is stored through a text-content path. After decoding, its SHA-256 is:

```text
9270b8ebd1243b388a17f24a5cad4883363ca7a5dd122431df2d2a7dc49c87f5
```

It is a 3556-byte ARMv7 Thumb-2 PIE with `/system/bin/linker` as interpreter and `libandroid.so` as its only dynamic library dependency.

A typical install is:

```sh
base64 -d sensors.armv7.b64 > "$PREFIX/bin/sensors"
echo '9270b8ebd1243b388a17f24a5cad4883363ca7a5dd122431df2d2a7dc49c87f5 '"$PREFIX/bin/sensors" | sha256sum -c -
chmod 755 "$PREFIX/bin/sensors"
sensors
```

## Off-device build

`sensors.c` is freestanding so the cross-build does not need Android headers or libc. It writes output with ARM Linux system calls and calls only the public Android sensor symbols it needs.

`link-libandroid-stub.c` is link-time scaffolding only. It supplies symbol names and the `libandroid.so` SONAME to the off-device linker. The stub is not shipped to the phone; Android's dynamic linker loads the phone's real `libandroid.so`.

The current artifact was produced with Clang/LLD 17:

```sh
clang --target=armv7a-linux-gnueabi -march=armv7-a -mthumb \
-ffreestanding -fPIC -fno-stack-protector -fno-builtin -nostdlib \
-fuse-ld=lld -shared -Wl,-soname,libandroid.so -Wl,--no-undefined \
-o /tmp/libandroid.so link-libandroid-stub.c

clang --target=armv7a-linux-gnueabi -march=armv7-a -mthumb -Oz \
-ffreestanding -fPIE -fno-stack-protector -fno-builtin -nostdlib \
-c -o /tmp/sensors.o sensors.c

clang --target=armv7a-linux-gnueabi -fuse-ld=lld -nostdlib \
-Wl,-pie -Wl,--dynamic-linker=/system/bin/linker -Wl,-e,_start \
-Wl,--hash-style=both -L/tmp /tmp/sensors.o -landroid -o sensors
```

The libc-free formatter is an implementation convenience, not part of the command semantics. The meaningful architectural choice is that the Android implementation uses the native sensor service boundary rather than a vendor HAL or raw kernel device.

## Command family

The next hardware commands should keep the same separation between program meaning and platform adapter:

```text
sensors
enumerate available sensors

read accelerometer
wait for one fresh acceleration measurement and print it

watch accelerometer
stream acceleration measurements
```

Later adapters may use Linux IIO, a Termux:API bridge, 9P, FUSE, or another native system interface without changing those meanings.

The ARM/Thumb compiler repository carries the same programs as backend sample targets. A hand-written C oracle or a physically working Android binary is not, by itself, evidence that Idriç generated that ARM/Thumb program.
10 changes: 10 additions & 0 deletions commands/sensors/link-libandroid-stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
void *ASensorManager_getInstance(void) { return 0; }
int ASensorManager_getSensorList(void *manager, const void ***list) {
(void)manager;
(void)list;
return 0;
}
const char *ASensor_getName(const void *sensor) { (void)sensor; return 0; }
const char *ASensor_getVendor(const void *sensor) { (void)sensor; return 0; }
int ASensor_getType(const void *sensor) { (void)sensor; return 0; }
int ASensor_getMinDelay(const void *sensor) { (void)sensor; return 0; }
1 change: 1 addition & 0 deletions commands/sensors/sensors.armv7.b64
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
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
1 change: 1 addition & 0 deletions commands/sensors/sensors.armv7.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
9270b8ebd1243b388a17f24a5cad4883363ca7a5dd122431df2d2a7dc49c87f5 sensors
79 changes: 79 additions & 0 deletions commands/sensors/sensors.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
typedef struct ASensorManager ASensorManager;
typedef struct ASensor ASensor;
typedef const ASensor *const *ASensorList;

extern ASensorManager *ASensorManager_getInstance(void);
extern int ASensorManager_getSensorList(ASensorManager *, ASensorList *);
extern const char *ASensor_getName(const ASensor *);
extern const char *ASensor_getVendor(const ASensor *);
extern int ASensor_getType(const ASensor *);
extern int ASensor_getMinDelay(const ASensor *);

static long write_bytes(int fd, const char *data, unsigned int count) {
register long r0 __asm__("r0") = fd;
register long r1 __asm__("r1") = (long)data;
register long r2 __asm__("r2") = count;
register long r7 __asm__("r7") = 4;
__asm__ volatile("svc 0" : "+r"(r0) : "r"(r1), "r"(r2), "r"(r7) : "memory");
return r0;
}

__attribute__((noreturn)) static void exit_process(int status) {
register long r0 __asm__("r0") = status;
register long r7 __asm__("r7") = 1;
__asm__ volatile("svc 0" : : "r"(r0), "r"(r7) : "memory");
for (;;) { }
}

static unsigned int text_length(const char *text) {
unsigned int n = 0;
if (!text) return 0;
while (text[n]) ++n;
return n;
}

static void write_text(const char *text) {
if (text) write_bytes(1, text, text_length(text));
}

static void write_hex(unsigned int value) {
char out[10];
static const char digits[] = "0123456789abcdef";
out[0] = '0'; out[1] = 'x';
for (unsigned int i = 0; i < 8; ++i) {
unsigned int shift = 28 - i * 4;
out[2 + i] = digits[(value >> shift) & 15u];
}
write_bytes(1, out, 10);
}

static int run(void) {
ASensorManager *manager = ASensorManager_getInstance();
if (!manager) {
write_text("sensor manager unavailable\n");
return 2;
}

ASensorList list = 0;
int count = ASensorManager_getSensorList(manager, &list);
if (count < 0 || !list) {
write_text("sensor list unavailable\n");
return 3;
}

write_text("count\t"); write_hex((unsigned int)count); write_text("\n");
write_text("index\ttype\tmin_delay_us\tname\tvendor\n");
for (int i = 0; i < count; ++i) {
const ASensor *sensor = list[i];
write_hex((unsigned int)i); write_text("\t");
write_hex((unsigned int)ASensor_getType(sensor)); write_text("\t");
write_hex((unsigned int)ASensor_getMinDelay(sensor)); write_text("\t");
write_text(ASensor_getName(sensor)); write_text("\t");
write_text(ASensor_getVendor(sensor)); write_text("\n");
}
return 0;
}

void _start(void) {
exit_process(run());
}
Loading