Friday, 10 July 2015

Using an aging Android phone

I can't help it: I love Android. It has quirks. It has rough edges. It has a million versions and many of them are dead-end forks by vendors who just don't care. It also has Linux at it's heart, and, with a little nudging, it can act like it too...

I use a Samsung Galaxy S3 (i9300). This is quite blatantly "old tech" -- the S3 is well over 4 years old and Samsung, like most vendors, has long ago spurned it when it comes to the concept of OS updates. For a long time, CyanogenMod was the answer, until the fateful day that the i9300 maintainer decided he had a life and wanted to spend more time doing that.

Phooey. But, srsly, good for him and his family.

Still, that leaves the i9300 user in a pickle. CyanogenMod has quite a strict rule about what devices are supported: basically, there has to be a sanctioned maintainer for that device who is willing to take responsibility for it. With no maintainer, the i9300, one of the most popular handsets ever sold, started fading into obsolescence.

There were (still are) some rather hearty movements to revive CM on the i9300. I have followed at least two of them for a while, updating from them. Alas, they all appear to fizzle out over some time.

One supporting ROM which doesn't seem to be willing to let go of this dog just yet is Resurrection Remix. Yay for me. Unfortunately, RR is a conglomerate built from a number of sources including CM. I say "unfortunately", because this means that when something breaks, trying to get someone to care about it enough to fix it is not a trivial exercise. Don't get me wrong: I appreciate all the work the devs involved do (for free), so I can avoid paying for another device (and adding my iota to the e-waste that abounds -- whilst my phone lives, it shall work for me!).

But there are still some issues (including, but perhaps not limited to):
  1. The flashlight function works whilst the screen is on, but switches off when the screen is off );' This is common on most ROMs which support the i9300 and appears to come down to a philosophical choice on the part of CyanogenMod to flip the bird an i9300 users.
  2. The vibration intensity by default is so low that it's pointless. Again, I'm quite sure someone, somewhere is giggling about how absurd this is for i9300 users and muttering something along the lines of "just upgrade to a new device already". Fuck 'em.
As far as (1) goes, this is just accepted as a broken feature of the phone. I've seen quite a few people just throw their arms in the air and say "so what do you expect me to do about it?". For most people, it's probably insignificant -- but I use my phone every night as a flashlight and having to keep the screen on during use is, well, sub-optimal.
As for (2), many ROMs provide a mechanism to set this. RR has one -- but it has often crashed the Settings UI when I try to use it (depending on the build). So I got tired of that. I want updates, but I also want my phone's vibration to shake the very foundations of the universe when someone whatsapp's me an nsfw image.

So here's my little useless collection of shell scripts to fix this:

So far, in there, you can find:
  1., which toggles the flash as a flashlight.
  2. which "set vibration to 11", ala Spinal Tap. This sets your i9300 vibration to max (100%)
Both of these require root as they mess with stuff under /sys. Both are easier to run via $cripter. To use, clone somewhere and copy the scripts into the folder you've configured $cripter to use as a scripts home.

To use, I bind to a double-tap on my home screen, via Nova Launcher (but I'm sure you can do this with other launchers or in other ways) and I set to run at boot via Llama.

I hope this can help someone else with an i9300, especially if they are holding back on upgrades for the same reasons I am:
  1. Damn the man: I refuse to pay just to get a newer, shinier toy.
  2. The world has enough e-waste as it is. I'd like to be able to say to my boy someday that I did what I could to slow down the destructive nature of man, no matter how inconsequential my actions were.
 Any other useful hax that I contrive for this phone will end up there. Licensing is BSD ("if it breaks, you can keep both pieces"). You're welcome to use, distribute and mock. I don't care if you don't like it. I do care (a lot) if you do (:

Thursday, 9 July 2015

Callbacks suck

Problem: Javascript is essentially run on one thread and some things take time, blocking other requests.
Solution: make everything asynchronous and provide a callback mechanism.
Problem: I now have plenty of asynchronous calls which come back to a callback which does another async call and so on and so forth. Since I didn't really think this through to start with (!!), I now have something like:

This code is an unmaintainable mess and something has to be done about it.

There are a few ways to slay this beast:

#1 Refactor
You could refactor your code to pull out methods and reference those. Chances are you end up with something a little spaghetti-like: now you have all these neat little functions but actually determining the call order is an exercise in using your IDE's "go to definition" function, or at the very least, VIM's * and # commands. Not ideal, at least not from where I stand. Refactoring is a good process but I don't think it's the right tool to fix this.

#2 Node async module
You could alter your programming pattern and make use of the (rather cool) async node module. Off the top, it looks like it has some interesting solutions to some of the most common logic patterns, but I'm still not 100% sold. There's nothing intrinsically wrong with the module -- it just doesn't seem like the best fit (to me).

#3 Promises (to the rescue, again)
Promises have been around for a while and they're not going away. Indeed, ES6 brings promises right into the core language. If you aren't using them, it's at least time to start looking at them. And if you do, and you happen to stumble across one of the grandfathers of the promise library offering, Q, then you will be pleased to find that Q has support baked in to provide a promise-based wrapper around the typical NodeJS async callback: Q.nfbind, or, as I prefer, the alias: Q.denodeify.

You can just do something like:

var promiseBasedFunction = Q.denodeify(someAsyncFunction);
promiseBasedFunction('arg1.level0', 'arg2.level0').then(function(result) {
// first call succeeds, let's carry on
  return promiseBasedFunction('arg1.level1', 'arg2.level1');
}).then(function(result) {
// second call succeeds, let's forge on forward
  return promiseBasedFunction('arg1.level2', 'arg2.level2');
}).catch(function(error) {
// handle errors
  console.log('FAIL: ' + error);
}).done(function() {
// this is always run
  console.log('Exiting now...');

Some wins you get out of this:
  1. No deep nesting. There is a nice follow-on of functionality, something you can read top-down and which someone else could probably get into a little quicker. Code readability consistently ranks highly when programmers are asked to list aspects of quality code. Remember that the code you expertly write today will be visited by a complete stranger some time in the future. That stranger may even be you.
  2. No need to handle errors at every asynchronous turn. The first one that fails ends up in the catch area and you can deal with it there
  3. A defined end-point that is easy to deal with (the done handler)
But wait, there's more!
The async node module has some interesting techniques for dealing with simultaneous async calls (think: I need to get data from three web services and provide a consolidated answer -- I'd prefer to make those calls in parallel and consolidate once) -- but so does Q, with Q.all(). Q offers a lot, and one of the main benefits it offers is helping to wean you off of the callback tit. As I've shown in my promises tutorial, different promise libraries play together fairly well, so even if you decide to switch to another (or the ES6 built-in Promise), you have to freedom to do so.

Not that I suspect Q is going anywhere any time soon.

Footnote: this journey started when I had the brainfart that it would be great if there were a node module that provided functionality to wrap existing async calls in the promise lingo. I was about to embark on writing one when a friend suggested that I check out some of the functionality in Q that I wasn't already using. That's a reminder to check if a problem has already been solved before running off to write code -- though the process (like the process of writing my own promises implementation) would have probably been enlightening. It's also probably a reminder that it can be quite beneficial to skim over the full documentation for a library to discover useful gems.

NExpect level 3: you are the key component

In previous posts, I've examined how to do simple and collection-based assertions with NExpect . These have enabled two of the desig...