Coderspiel

Mobile multitasking for dummiesMobile multitasking for dummies

At our last New York Scala Enthusiasts Meetup I presented on Android. I started the talk with a series of 1980s magazine ads that extolled Apple personal computers as world-changing tools for creative expression and invention. Android is a platform for hand-held computers in this proud tradition.

adams-apple
We’re looking for the most original use of an Apple since Adam.

After that ironic stroll down memory lane and after I presented Snapup a simple photo-snapping application I wrote to post Meetup photos, we had one of those conversations that are, ultimately, the reason we gather in public. I hadn’t gone there to talk about multitasking and didn’t have anything prepared for the subject. I didn’t hide the fact thatI knew little about the greater Android platform; I had only learned enough of its API to make my app workie.

But I had shown a number of internal background image-loading threads being created as Scala actors, and someone who did know the Android platform wanted to know if those were still chewing through valuable mobile cycles. So we opened the Dalvik Debug Monitor—my first time!—and quickly discovered (in front of forty people) that my app was stealing some cycles when it should have been idle, and actors were part of the theft.

Was this the greatest actors crime since the Lincoln assassination? Well no. I should have been telling the actors to exit after they were done. I wasn’t even really using actors, just somewhat idiomatically using an actor for a simple background thread (mentioned in the last post, actually). I assumed that the zombie activity there was negligible, but, in the Android model there is no such thing. Any wasteful polling picks the battery’s pocket all day long.

So after the Meetup I pushed ahead my plans to implement non-blocking interfaces in Dispatch using java.util.concurrent as a foundation. Once Snapup was refactored to use this higher level HTTP interface, ddms showed no activity at all from my background threads. But, there was still a significant amount of CPU burn when the app should have been idle. What was it?

It was a stupid indeterminate progress dialog animating itself off-screen. See, Android replaces the desktop concept of windows with a new concept of activities, better suited to small (or large?) touchscreen interfaces. Snapup has one activity that does nothing but OAuth token exchange, and the only face it shows to the user is a Please wait… dialog. Once it has the tokens it starts the another activity but it doesn’t stop itself. Neither, apparently, does its animation.

After stopping that nonsense, Snapup’s idle activity went down to zero where it belonged. Whether on-screen or off the process is voluntarily cryogenically frozen, the same as if the operating system had forced it to pause. Problem solved!

Yo mama

But oh my god, doesn’t this mean that your ‘mom’ or ‘wife’ is going to have a hard time using an Android contraption because of bad apps like version 0.1 of mine? First of all, That’s sexist. Secondly, No. This story means the Android human-interface to multitasking needs work.

Sure, I’m a dummy for not profiling the application before releasing it. I like making things and it worked so I jumped the gun. And there’s a lot of dummies in the world. One option is to cut us off from users and require bureaucratic approval of all software binaries before anyone can run them. Another option is to solve the problem, with design.

The old desktop software model puts users in charge of starting and quitting applications. A bit of sloppy processor use was expected, and generally harmless. When computers began to run on batteries, the task fell on users to be vigilant. Road warriors that depended on battery life learned to quit any app that they didn’t immediately need.

In the new model that’s been adopted by all successful mobile platforms, you don’t quit applications: you leave them. On platforms that support multitasking this shifts responsibility to application programmers: they are the ones that need to be vigilant. If they do their part things work great: Android’s technical implementation of multitasking is excellent. It’s up to applications to be good, or bad.

The design problem is that users (and casual programmers) aren’t exposed to this new dimension of bad. Normally you can judge software just by using it. The user interface is good, bad, or ugly. The app is fast or slow, it crashes or it doesn’t. But for battery waste the feedback loop is broken.

Android tries to address the problem with a kind of shit-list for applications. It’s is offered up when your battery runs low: Dang, who’s been using up my battery? The shortcomings of this measure are obvious. For one thing, batteries are meant to run out. Reaching the end of a cycle is not a sign that any app has been misbehaving. To find any bad apps you have to mentally subtract your historical use of each one listed. And who wants to start that investigation with an uncertain few minutes of battery life remaining?

Battery waste information, which all users now require to judge applications, is just not adequately exposed in Android.

All Activities on Deck

Where does application activity information belong? The place you go to switch running apps, at the very least. And as it happens, that place is a dump in Android right now anyway, an alt-tab popup lifted from Windows 95. In this problem domain the Palm Pre’s card metaphor is so far the only effort worthy of the touchscreen medium. There’s plenty to be inspired by there, so much as the lawyers will allow it.

Because Android doesn’t have an activity switcher worth talking about anyway, it can kill two birds with one interface and bake battery usage deep into whatever does emerge. It should be as obvious which applications are using the battery as it is which ones are running at all. This is critical information to anyone using the platform. Especially your ‘mom’ needs to know which applications are wasteful!

The Android people at Google, they’re no fools. The current lame task switcher is a sign, if anything, that there is a big fat real-task-switcher branch that their work is going into. It needs to land soon. This is the year that people are picking up and trying Android. They need to be able to say, “hey, I’m not using that app right now and it’s using my battery for no good reason.” DELETE. Otherwise, their experience will be bad.

The difference between this and the old model is simple: you don’t quit applications that might be wasting resources, you remove applications that you know are. You aren’t managing tasks, you’re firing applications. It raises the awareness of programmers making the apps too, and the incentives to write a well behaved app. By filling that information gap, we can finally reach a level of abstraction that many of us have been anticipating for decades: applications that are just there. Your trusty software is always available, right where you left it and doing only what you told it to do.

Apple thinks they can guide us into that future with an army of bureaucrats, who are surely enrolled in profiler training courses at this moment. It’s surprising how long that is taking, actually; it has made their cherished new product unveiling the butt of resonant jokes. And when they finally start to white-list ‘background’ apps it will at least be one helpful purpose of their degrading software approval exercise. But even so, a platform that enlists informed masses to collectively rank software will run circles around one administered by, well, your dad.

Just ask the first company that tried to fight off Google with an army of classifiers.

Building blocks for Android interactionBuilding blocks for Android interaction

All interactive software should relegate lengthy processes to background threads. In mobile applications this is crucial, as they commonly invoke network operations that can be anything from slow to god-awfully slow. Further, users that are accustomed to momentary freezes in computers are a little less tolerant of apps that do this to their friggin’ phones.

Fortunately multitasking is built into Android at all levels, from long-running services that eventually post user notifications to threads that perform one-second, one-off jobs within a single activity (roughly analogous to a window). This post is concerned with the second, most basic and simple case. And guess what? It’s even more basic and simple in Scala.

While the Android API seems to have approached the problem of modeling graphical interaction with a clean slate—and thank heavens for that—it doesn’t invent things without cause. So to do work in a new thread, you do it however you normally would. In Java this might in involve creating and running a Thread; it Scala it can be abstracted like this:

import scala.actors.Actor._
actor {
  // upload a file or something
}

The interesting part is what happens when the work is done. The background thread can’t interact directly with interface objects in the main thread, so, Android gives us a message queue to communicate with the main thread. It is not so different from what we have in Scala’s actors library! An Android message includes an integer message code, to be compatible with Java’s famously lame switch statement perhaps, but in Scala we can ignore that and use pattern matching to branch on and extract the data, like with actors:

case class Dismiss(dialog: AlertDialog)
val handler = new Handler(new Handler.Callback {
  def handleMessage(message: Message) = message.obj match {
    case Dismiss(dialog) => 
      dialog.dismiss()
      true
      [...]
  }
}
def upload_file {
  val loading = [...indefinite progress dialog]
  actor {
    [upload it and such]
    handler.sendMessage(Message.obtain(handler, 0, Dismiss(loading)))
  }
}

Which is not at all shabby! You could easily factor out more boilerplate, make sendMessage more actor-like by aliasing it to !, and maybe even bridge the queues between Scala actors and Android messages. But now, let’s check out another way that Android lets you beam back from a background thread: posting a Runnable object to the handler queue.

In this case the message that goes into the main thread’s queue is program code, sort of like a block. In Scala we can easily factor out some cruft and pat ourselves on the back for using immutable references that we know will not have been altered before the background thread is done and the main thread gets around to processing the Runnable:

val handler = new Handler
def post(block: => Unit) { 
  handler.post(new Runnable{
    def run { block }
  })
}
def upload_file {
  val loading = [...indefinite progress dialog]
  actor {
    [upload it and such]
    post { loading.dismiss() }
  }
}

The case classes that seemed so smart a hundred words ago are now revealed to be first-class cruft and generally unsavory characters! To use that scheme for every interaction from a background thread you would have to describe most of the Android API in cases classes, which might impress your school mates but not this crowd of elite Coderspiel readers. If we were talking across applications or even activities, instead of dealing with local references, then it would be a different story.

And that concludes this teaser for Androids Dream of Monadic Sheep, the next New York Scala Enthusiasts Meetup.

Avoiding the iNannyAvoiding the iNanny

princess

Just cold floating over your App Store approval process

Has it been a long Apple-decade or what, you guys? We spent the first few years waiting for a meaningful upgrade of System 7 to be released, and then, for OS X to be usable on regular hardware. We waited for an LCD all-in-one that didn’t emit smoke. We waited for Apple TV, and then wondered why. We still wait on ‘tablets’. But mostly, we waited for the iPhone. I know a guy that wouldn’t sign any cellular contract from 2005 on, just to be ready when the inevitable awesomeness arrived.

What’s that, you were waiting on your iPhone starting with the January 2007 announcement? Cute.

Listen, I haven’t been suckered into a cell phone contract for many years, but after an hour’s reflection last weekend I went and committed to pay $1320 to Verizon over the next two years (the secret $55/month data-only plan) to finally get my iPhone, which is a Motorola Droid.

I just couldn’t do the Apple iPhone. As a programmer, I couldn’t buy computing hardware that had been given a consumer electronics lobotomy. As a consumer, I couldn’t pay $70 a month (+ unknowable tax) for a mobile web browser when I sit in front of a stationary web browser all day.

But my exclusion from the world of wireless applications itself became unsustainable. I can live without map applications; I like to know where I am without looking down. And I can generally assemble information I need from the web before I go places. But then along came friggin’ Foursquare, which basically isn’t workable without a mobile app. (T-Mobile prepay actually blocks their shortcode—smart move, guys!) And Foursquare is just the beginning of a new category of software that can have no counterpart on traditional computers. You’re in or you’re out.

So as soon as I heard the internet whispering that the Droid was the phone I’d been waiting for, I grabbed it. I didn’t do any research; I’m not sure what this thing’s clock rate is, for example. AND I AM SO PLEASED WITH MY DROID.

I have used iPhones a fair bit and I know exactly what I’m missing. That is, I’m aware just how much my Droid is clunkier than an iPhone. I know that polish is important, that these things matter, etc. I was of the fifteen people using Macs back when they were significantly slower than PCs, because the interaction was that much better. But on the usability continuum, the Droid is close enough to pistol whip the iPhone.

People have made analogies to different desktop operating systems, Windows 95 or whatever, and I have one of my own: the interface design gap between the iPhone and the Droid is like that between System 7 and Mac OS 10.6. The modern Apple OS trades consistency and thoughtfulness for capability. Some of that trade is justified and some is not, but it’s there. The iPhone, as a new creation and also apparently where all the people that really care about interface design at Apple have ended up, is a jewel much like their desktop systems of old. The Droid on the other hand does more—for both engineering and political reasons—with less panache.

Now, raise your hand if you are using System 7 today because you value the last 10% of interface design over the ability to run an unlimited array of modern software.

Appleytes

Let’s take a moment to look back at the past two and a half years. The iPhone, when it was finally announced, was an ideological disappointment. Many of us were hoping for a product that changed—ended, actually—the cell phone control structure. A phone that would be sold like a computer, with no particular obligations, bringing power and choice to its users and healthy profits to Apple and the companies that customers picked for their service. We were disappointed from the very beginning that the iPhone would be AT&T-only, contract-only, and ‘locked’. It’s not the particular service company, T-Mobile or Verizon or Lunesta or whatever. The problems that people started to complain about later—prices ratcheted up for an inadequate and overloaded 3G network—were inevitable the moment any exclusive service provider was named.

The second big disappointment was the App Store, when it was finally announced. Apple implemented unprecedented software restrictions for a device that was otherwise designed to be a computer. Again, the downsides were evident from the moment we knew the ground rules, that Apple would approve or reject every binary of every application installed. The idea that any centrally controlled (software) market could be fair and efficient was a fairy tale. History, you guys?

AND YET those of us that protested this terrible system were dismissed by the mob that came to Apple by way of iPod. It was that we just didn’t understand business. Our possession of basic principles, and especially any kind of rational philosophy of software, made us irrelevant perfectionists that should just accept the iPhone’s popularity as a proof of correctness. And most amusingly, there are great deal of people that consider it immature to question any kind of authority. God love the rabble!

Now the great, naive concern is whether Apple will discover these systematic flaws in App Store and correct them, a framing that mistakes features for bugs. The App Store was designed for arbitrary control, to do stupid things like hamstring apps that Apple doesn’t like so much. There is no real news this month or this year about the process—least of all news to Apple. Everything is going according to their design. If the system is substantially reorganized it will not be from a sudden discovery of its flaws or respect for iPhone programmers: it will be a competitive public relations maneuver.

Which is fine. Who cares! I don’t care. Year by year Apple has shorn away the warm and fuzzy that used make it special. I mean, dang, remember the Gandhi ads? That was over the top even at the time but now it feels like the ad campaign existed in an alternate reality. Today Apple is a just another Google or Microsoft, with a focus on design. I could take it or leave it and, at least for this round, I’ve left it.

Practical philosophy

People objected to abstract reasoning about the App Store’s flaws, but the only reason we humans have that faculty is to predict reality. I didn’t have to pore over a list of apps in the Android Market to know it would have great things that you couldn’t get through Apple’s sieve. Game machine emulators, for example, never occurred to me, but then I was flipping through popular Android apps and was like OF COURSE.

Emulators are banned from the App Store in about a million ways, starting with a ban on compiling or interpreting code; essentially, a ban on programming. On top of that game emulators in general are of dubious legality because they require game images of dubious legality. The one I have links out from the app to a Google search for “NES ROMs download.” Can you imagine the idiotic back and forth that would spawn with the App Store administration? To be honest, I was a little surprised to not have to use the Droid’s ability to run “software from unknown sources” here, but of course that very ability creates pressure on the Market’s administrators not to be stupid. If they reject apps for silly reasons, people will make their own market.

Game emulators illustrate so much of what is right with a normal software environment, and what is wrong with the App Store. It’s up to me to decide if I think that running an emulated 20 year old game is ethical. I appreciate the creative genius that went into it back in the day, and I do value software and think that its production should be compensated. In fact, I paid for the emulator. But I think the possibilities for meaningful compensation of NES software have pretty much expired. I want to support people that work in software today, not corporations holding copyrights that they have manipulated governments to extend. So, I will play my Super Mario Bros. 2 and I’ll be happy to pay for original new games that are worth playing, too. The main reason to bury the old games, naturally, is to prevent them from competing with uncreative new games.

So I’ve developed my own opinion about game emulation, and I’m sure some people would disagree or see it as rationalization. But in the end I decide what software to run on my phone, which makes it a computer, which makes it worth the up front cost and monthly service contract. Outside its software the system is not as open as I’d like it to be, but the runtime makes it worth the the telco-statism it’s encased in.

Here’s to the crazy ones?