whoami

Lucas Jenß

cat /etc/motd

The Coding Journal ツ — Notes taken on an epic coding journey. Technical solutions, debugging notes, and practical guides from the trenches of software development.

Close-up of white dominoes with black dots standing on green felt surface, shallow depth of field, focused mood

ls -la ~/languages/

total 8
drwxr-xr-x
▶ PHP
▶ Ruby
▶ Scala
▶ C#
▶ JavaScript
▶ Objective-C
▶ Shell Scripting

ls -la ~/toolchain/

total 7
drwxr-xr-x
▶ Typo3
▶ Akka
▶ Capistrano
▶ Git
▶ MAMP
▶ Adobe Illustrator
▶ NSTrackingArea (Cocoa)

uname -a

platforms
drwxr-xr-x
▶ Mac OS X
▶ Unix

Emulating an Android device with broken sensors

Emulating an Android device with broken sensors to test fallback logic closes a gap between unit tests and code that only works when every hardware service behaves. A healthy emulator can validate readings, yet it rarely reproduces the awkward states developers must handle: a sensor missing at startup, one that stops delivering events, values outside expected ranges, or callbacks delayed beyond a UI timeout. A scripted failure profile makes those conditions repeatable.

Build the rig around observable contracts rather than a single disabled sensor. Capture the app’s expected response, exercise the same build through normal and failure profiles, and compare timeout, recovery and user-control behaviour. This approach works for motion, proximity, light and magnetic-field inputs, provided each sensor has a defined fallback when data is absent, stale or untrustworthy.

Test environment Sensor registration Failure behaviour Best fit
Damaged handset May remain visible Real HAL, power and driver faults Final confirmation
Standard emulator profile Present and active Healthy readings and normal callbacks Baseline
Scripted virtual sensor profile Present, disabled or frozen Silence, fixed values and extreme readings Deterministic fallback tests
App-level test source Controlled by the test Absence, delay and synthetic events Fast CI coverage

Why a broken sensor rarely looks broken

Android can report a sensor as present while its hardware abstraction layer, driver or power path prevents useful events. The framework may still return a Sensor object from SensorManager, so a null check passes even though the app receives nothing. This occurs on custom ROMs and imported handsets, where vendor services can also recover later during the boot sequence.

A design that only handles getDefaultSensor() returning null therefore misses several common failures. Registration can succeed before the driver becomes ready, callbacks can stop after the feature starts, or an accuracy change can indicate unreliable readings without producing an explicit error. Recent Android releases add another silent path when a sensor governed by a runtime permission has that permission denied.

Define the required transitions before changing the emulator: unavailable, waiting, healthy, stale and disabled. For each state, specify whether the app should use cached data, request manual input, disable the feature or display an unavailable message. This turns fallback logic into observable behaviour that can receive a pass or fail result.

Building a repeatable emulator setup

Create an Android Virtual Device using the target API level and sensor features, rather than choosing an image solely for its phone skin. Keep Google Play and non-Play images separate if their sensor implementations differ. Record the AVD name and API level in every test result so an emulator update cannot silently alter the baseline.

Drive the emulator through its console for repeatable changes. First check adb -s emulator-5554 emu help, because supported sensor names and controls vary between images. An image that supports virtual sensors may accept commands such as adb -s emulator-5554 emu sensor set acceleration 0:0:0 or adb -s emulator-5554 emu sensor status acceleration off. Keep reporting enabled with a fixed value to freeze a reading; disable reporting to simulate a sensor that remains registered but stays silent.

Automate each transition with a host script and retain logs from both sides of the connection. If an emulator image cannot hide or delay a sensor, place a testable SensorDataSource behind the app’s sensor access. Its production implementation can call SensorManager, while tests supply absence, silence, delayed timestamps and recovery events without requiring privileged Android APIs.

A practical sensor failure checklist

Use separate profiles for sensor availability and event delivery. Availability determines whether registration succeeds, while delivery determines what happens after a listener has been installed.

  • Absent: The sensor registry returns no matching sensor before registration.
  • Silent: Registration succeeds, but the app receives no sensor events.
  • Unreliable: Registration works while accuracy changes or validity becomes uncertain.

Once availability states are covered, vary the values and timing delivered by the active sensor. These cases exercise freshness checks and numeric validation rather than only the registration path.

  • Frozen reading: The value remains unchanged until the app rejects it as stale.
  • Implausible value: The magnitude falls outside the documented range for that sensor.
  • Delayed callback: An event arrives after the configured fallback deadline.
  • Intermittent recovery: Events stop and later resume, forcing a clean state transition.

Run the healthy profile before each failure scenario to prove that the harness itself works. Assert the fallback deadline, visible app state, cached-data policy and listener cleanup rather than relying on a screenshot. After recovery, verify that delayed events from the failed period cannot overwrite newer state.

Instrumenting callbacks and native boundaries

For every run, log the sensor handle, reporting mode, subscription time, event timestamp, accuracy, event count and age of the last callback. Derive event age with a monotonic clock. System.currentTimeMillis() can move when network time is corrected, making it unsuitable for deciding whether a physical measurement is fresh.

Expose sensor and fallback states in structured logs. A silent sensor should activate its fallback after a bounded interval rather than leave a spinner running indefinitely. When events return, invalidate stale cached state and resubscribe through one controlled path. These transitions are easier to diagnose when the log includes the reason for each change instead of only the final UI state.

If readings cross a JNI boundary, verify that the native library loaded before blaming sensor delivery. The author’s native library troubleshooting guide separates native loading failures from application callback issues, preventing a missing UnsatisfiedLinkError handler from being mistaken for a silent accelerometer or gyroscope.

Validating Australian use cases

Australian teams should test Pixel and Samsung variants commonly sold by Telstra and Optus or through retailers such as JB Hi-Fi, rather than assume an imported ROM matches local firmware. Schedules in Sydney, Melbourne and Brisbane may differ, so share logs in UTC while checking local timestamps separately. Keep hardware provenance with the test evidence; a durable engineering record such as CCJ engineering notes can hold those assumptions without coupling them to the application repository.

A faulty handset sourced from overseas may pass through Australian Border Force and incur GST or other import charges, so document who supplied it and keep continuous integration independent of that device. Daylight-saving changes in Sydney and Melbourne can also make wall-clock fixtures appear expired or unexpectedly fresh. Calculate fallback expiry from a monotonic clock, store timestamps in UTC and test locale rendering separately.

A short field pass can expose cases the emulator simplifies. Compare magnetometer readings in open areas and near Melbourne tram infrastructure, then repeat light-sensor checks in a shaded pocket or beside a Brisbane office window. Return the result to a named virtual profile for repeatable regression coverage. Create the absent, silent and delayed profiles now, run them in CI, and attach their logs to each release result.


cat ~/interests.json

KeyValue
editorTerminal-first workflow
osMac OS X / Unix
vcsGit, distributed version control
deployCapistrano, cron automation
graphicsSVG, Adobe Illustrator troubleshooting
networkingIP validation, SSH, VPN

git log --oneline --reverse

2013-10-30

Solving SVG import issues in Adobe Illustrator CS6 and CC

When importing an SVG into Illustrator, the operation fails with an unknown error [CANT]. A workaround for this Adobe-side bug.

2013

Solving NDK build issues on OS X

Troubleshooting native development kit compilation problems on Mac OS X.

2013

Programmatically adding PHP generated TypoScript to the backend configuration

Integrating dynamically generated TypoScript into Typo3 backend setups using PHP.

2013

ArgumentError: Could not parse PKey: no start line

Debugging an SSH key parsing error encountered during deployment.

2011-08-04

Validating IP-Addresses in PHP

Using PHP filter functions with flags like FILTER_FLAG_IPV4 and FILTER_FLAG_IPV6, and understanding how filter_var handles reserved IP addresses.

2011-07-09

Cocoa: Using NSTrackingArea

A short tutorial on using Cocoa's NSTrackingArea to capture mouseEntered and mouseExited events.


cat ~/contact.txt

github: github.com/x3ro
stackoverflow: x3ro
coderwall: coderwall.com/x3ro
twitter: @x3rames