A comment on the Whirlpool N900 forums piqued my interest recently. The author was asking about the possibility of switching phone profiles based on the orientation of the phone – more specifically turning the phone to “silent” mode when placed face-down on a desk (or other flat surface). Apparently this is available already on the HTC Desire, and it seemed like the sort of thing the N900 should be able to handle with ease.
I started with a simple proof of concept shell script. It was pretty untidy, but demonstrated that it was certainly feasible to detect the orientation of the phone and change profiles accordingly. Perhaps I should have done some Googling first, but I later spotted some neat Python code by Great Gonzo which did the job so much better than my shell script. With his permission, I’ve borrowed most of his work here.
How does the script work? In simple terms it polls the N900′s accelerometer every now and then to determine the device’s spatial orientation. If the accelerometer reports that it is face down, we also check the phone’s proximity sensor to ensure that it’s lying flat on a surface, and not (for whatever reason) just being held directly overhead.
The have been some comments that polling the accelerometer is a bit of a battery drain. In an ideal world, we’d receive event notifications for when the phone is face down, and in fact the N900 does provide those orientation notifications to interested applications. Unfortunately, we can’t use them because:
- The notifications aren’t sent when the screen is locked
- Try as I might, I couldn’t get the sample Python code to work in a console application
My gut feeling was that since we’re checking the sensor pretty infrequently (currently once every 3 seconds), that it wouldn’t be a significant power drain, but in the spirit of actually knowing, I decided to run some tests. I initially tried to use BatteryGraph to determine the power drain of the Python script. I set the script running and left the phone alone for 2 hours. Unfortunately seemed to log data at pretty random intervals, and inspecting the SQLite database it populates didn’t provide enough data to form any sort of valid conclusion.
Plan B: I wrote the following simple Python code to log the battery charge level every minute:
#!/usr/bin/python
import dbus, time
from datetime import datetime
class BatteryLevel():
def StoreBatteryLevel(self, level):
f = open("/home/user/battery-level", "a")
f.write("%s,%s\n" % (datetime.now(), level))
f.close()
def Loop(self):
bus = dbus.SystemBus()
hal_obj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
hal = dbus.Interface(hal_obj, 'org.freedesktop.Hal.Manager')
uids = hal.FindDeviceByCapability('battery')
dev_obj = bus.get_object('org.freedesktop.Hal', uids[0])
while True:
level = dev_obj.GetProperty('battery.charge_level.percentage')
self.StoreBatteryLevel(level)
time.sleep(60);
level = BatteryLevel()
level.Loop();
With this logging script running, I switched off all running N900 applications, locked the screen and left it alone for an hour. The log file it produced looked like this:
time,battery %
2010-11-03 17:30:45.756291,74
...
2010-11-03 18:27:53.257001,74
So… the battery level hadn’t changed significantly over this time (as you’d expect with nothing running and the screen locked).
Leaving the battery logging running, I then started the “facedown” python script. After another hour, the log file looked like this:
time,battery %
2010-11-03 18:29:53.410619,74
...
2010-11-03 19:34:02.163335,74
This surprised me. I expected to see a slight drop in the battery charge level, but nope… no change whatsoever (I may re-run these tests over a longer period later on, but a little bit of luck is required: any received phone calls, SMS’s or other scheduled tasks that might be running on the phone will interfere with the results). With no discernible difference in battery usage over that 60 minute period, I’m confident that I won’t notice any major changes over a 24 hour period either.
Since the battery drain appears to be fairly minimal, I decided to abandon the QBW idea, and just have the script running all the time. To start the script when the phone boots, we need to add a file to UpStart’s /etc/event.d/ directory. I found this quite confusing – and I think I’m not the only one that’s been baffled by UpStart’s stubborn refusal to run my scripts. However, I eventually got it working using:
description "Facedown Daemon"
author "Rob Poyntz"
service
console none
start on started hildon-desktop
stop on stopping shutdown
exec /usr/bin/run-standalone.sh exec /usr/bin/python /opt/Facedown/facedown.py start
So what’s left? Well I guess the code. You can download it from here.
At some point I need to learn how to package this up into a easy to install Debian package, but in the meantime, drop me a line if you’d like a hand getting it running.