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.
ls -la ~/languages/
- drwxr-xr-x
- ▶ PHP
- ▶ Ruby
- ▶ Scala
- ▶ C#
- ▶ JavaScript
- ▶ Objective-C
- ▶ Shell Scripting
ls -la ~/toolchain/
- drwxr-xr-x
- ▶ Typo3
- ▶ Akka
- ▶ Capistrano
- ▶ Git
- ▶ MAMP
- ▶ Adobe Illustrator
- ▶ NSTrackingArea (Cocoa)
uname -a
- 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
| Key | Value |
|---|---|
| editor | Terminal-first workflow |
| os | Mac OS X / Unix |
| vcs | Git, distributed version control |
| deploy | Capistrano, cron automation |
| graphics | SVG, Adobe Illustrator troubleshooting |
| networking | IP validation, SSH, VPN |
git log --oneline --reverse
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.
Solving NDK build issues on OS X
Troubleshooting native development kit compilation problems on Mac OS X.
Programmatically adding PHP generated TypoScript to the backend configuration
Integrating dynamically generated TypoScript into Typo3 backend setups using PHP.
ArgumentError: Could not parse PKey: no start line
Debugging an SSH key parsing error encountered during deployment.
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.
Cocoa: Using NSTrackingArea
A short tutorial on using Cocoa's NSTrackingArea to capture mouseEntered and mouseExited events.
cat ~/contact.txt