Shush Ringer Restorer on MIUI

MIUI is a careful, fluid Android mod that's gaining popularity with Android hobbyists. Unfortunately, it has a misguided feature that breaks Shush! Ringer Restorer.

Follow these steps to disable that feature and fix Shush:


Go to the Settings app.


Select the Programs tab.


Select the Call Settings option.


Toggle Third party app access to off.


Further details are on the MIUI forums.

Shush! featured on Android Market

Shush was recently featured on the Android Market. Overall the added exposure was fantastic. It took me almost two years to reach 10,000 installs but just two weeks to hit 150,000:


Shush installs were flat until March 12, 2011

I make my email address available on the Shush! Market page. That yielded about 100 emails in a mix of good, bad and ugly:

Shush also received a lot of Android market reviews. Some favourites:
"Probably the best app ever, should come standard w/ every phone!"

"Amazing app. Recommend it to everyone."

"This ap is just too awesome to be free! It's perfect, and so simple a cave-man..... well, u get the picture. LOL"
I feel obliged to paste some constructive reviews to balance those:
Does yours turn off and on at random? Mine does. :-(

Didn't play well with my EVO. Uninstalled.
Some people are having genuine problems with Shush. I know there are interaction problems when some apps invisibly mute the ringer. It seems like some camera apps mute the ringer when they intend to mute only the shutter sound; I need to get in touch with the authors of those apps.

The torrent of feedback has motivated me to spend some time on some polish features. When I added status bar notifications, lots of folks complained that it was cluttering up their notification bar. No new feature goes unpunished! I made those optional and added color selection.

As is the case with software, every feature has its costs. With Shush targeting a wide variety of Android devices, this is absolutely the case. I've had many problems where graphics don't look right on some devices. For Eclair and Froyo I used a black status bar icon; this works on stock Android but disappears into the black status bar on HTC Sense. My current fire to fight is the welcome dialog no longer fits on-screen on some devices. Ugh!

I'm used to writing code for other programmers. Writing code for a less technical audience is a different game. I fear that my most celebrated feature will be that you can pick the app's color! A nice feature, but also a silly and unnecessary one.

Despite all of the extra work, having lots of users is great. Download Shush! from the Android Market.

GuiceCon

Today I participated in GuiceCon, a small get together of Guice developers and users. Here's a quick disorganized rundown of some observations and reactions...

Too much rope. Guice's circular-dependency proxies and just-in-time bindings save developers from boilerplate. But these features have complexity costs. Almost everyone agreed that the benefit wasn't worth the complexity.

PrivateModules fail. They're nice in theory but the poor interaction with just-in-time bindings prevent them from being nice in practice. It's too bad.

SPI win. Everyone is using the Guice SPI to improve their app. Many teams are using them to do extra analysis of their modules. Sonatype are even using TypeListeners to host other containers. I think the SPI benefits by staying out of your way when you aren't using it.

Too little rope. People want to inject the injection point. It's a scary cat to let out of the bag, but one that could be put to tasteful use in some situations. When it's used tastefully, it will save people from a lot of boilerplate. This issue will be under debate for the next rev of Guice.

Building bindings recursively is lame. Miniguice discovers required bindings using a queue. This approach was warmly received. This would be a nice - if risky - improvement for a future rev.

Multibindings SPI win. All aspects of the SPI are getting exercise, even seemingly exotic SPI features like the extensions SPI. These were added to scratch our own itches; I'm pleased to see they're general purpose.

JSR 330 win. Crazybob's dependency injection JSR is powerful and svelte. You'll soon be able to use it to inject plugins throughout your tool chain: Eclipse, Maven, and Hudson.

We also discussed some non-Guice stuff...

Xtext is very well done. This Eclipse.org project makes it very easy to create powerful Domain Specific Languages. They have an extremely powerful model for defining a language, navigating the corresponding AST, and building integration into the Eclipse editor. Very powerful stuff. Xtext uses Guice in its API.

Hudson lives. I can't say anything about Jenkins, but it's clear that Hudson is still progressing. The project's maintainers are working on stability and structure. Works for me.

Sonar for Hudson looks very good. Hudson's default test reporting is clumsy. Sonar is better. I'll be looking into this next time I'm working on my project's build.

OSCON Java is a Portland, Oregon conference that looks very good. Java folks need a conference that's focused on them; now we have one.

GuiceCon was fantastic. I'm thankful to Van, Dhanji and Jason for putting it on and to Sam and Fred for travelling cross-country to present.

Handling a byte order mark in Java

Occasionally you'll need to interact with text files that have a leading byte-order mark. This signals which charset should be used for converting bytes to characters.

Unfortunately, the standard library doesn't include any facility to do this automatically. Instead, cut & paste this code to convert any raw InputStream into a Reader of the appropriate type.
  public Reader inputStreamToReader(InputStream in) throws IOException {
    in.mark(3);
    int byte1 = in.read();
    int byte2 = in.read();
    if (byte1 == 0xFF && byte2 == 0xFE) {
      return new InputStreamReader(in, "UTF-16LE");
    } else if (byte1 == 0xFF && byte2 == 0xFF) {
      return new InputStreamReader(in, "UTF-16BE");
    } else {
      int byte3 = in.read();
      if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF) {
        return new InputStreamReader(in, "UTF-8");
      } else {
        in.reset();
        return new InputStreamReader(in);
      }
    }
  }

GWT devmode bookmarklet

I've been doing a lot of GWT work, and I find the Development Mode to be particularly productive. Unfortunately I frequently seem to lose the "?gwt.codesvr=127.0.0.1:9997" URL suffix that makes dev mode work.

My buddy Jeremy came up with a simple fix: a bookmarklet that adds the URL suffix to the current URL. Drag this bookmarklet to your GWT-devmode-enabled browser's toolbar:

devmode

Next time your devmode isn't working, just click the bookmarklet!

Caliper confirms reality: LinkedList vs ArrayList

I've been exercising Caliper, our new JUnit-like microbenchmarking framework. I'm using it to explore and to confirm my assumptions about the JVM and its libraries.

At what size is LinkedList faster than ArrayList for queue-like access?

What I want to measure is first-in-first-out: add elements at the end, and remove 'em from the front. First I recall how these data structures work...
  • ArrayList limits allocations. It's backed by a contiguous array so add-at-end is generally cheap: just assign a value to the nth cell. But remove-at-front is expensive: move the array's entire contents over by one cell.
  • LinkedList limits copies. It's backed by a sequence of nodes so add-at-end requires an allocation immediately and a deallocation later. But remove-at-front is cheap: change a few pointers to assign a new head node.

I'm assuming that ArrayList is faster for empty lists because neither a move nor an allocation is required. I'll also assume that ArrayList is slower for large lists since that'll require a large number of elements to be moved.

I ask Caliper to answer my question in the form of a benchmark:
public final class ListAsQueueBenchmark extends SimpleBenchmark {

  @Param({"0", "10", "100", "1000"}) int size;

  private final ArrayList<String> arrayList = new ArrayList<String>();
  private final LinkedList<String> linkedList = new LinkedList<String>();
  private final Deque<String> arrayDeque = new ArrayDeque<String>();

  @Override protected void setUp() throws Exception {
    for (int i = 0; i < size; i++) {
      arrayList.add("A");
      linkedList.add("A");
      arrayDeque.add("A");
    }
  }

  public void timeArrayList(int reps) {
    for (int i = 0; i < reps; i++) {
      arrayList.add("A");
      arrayList.remove(0);
    }
  }

  public void timeLinkedList(int reps) {
    for (int i = 0; i < reps; i++) {
      linkedList.add("A");
      linkedList.remove(0);
    }
  }

  public void timeArrayDeque(int reps) {
    for (int i = 0; i < reps; i++) {
      arrayDeque.addLast("A");
      arrayDeque.removeFirst();
    }
  }
}
I ran the benchmark and the results surprised me: HotSpot's allocator and concurrent GC are fast! It takes only 10 elements for the LinkedList to pay for its extra allocations. And at 1000 elements, LinkedList is 20x faster than ArrayList for queue-like access.

Of course, ArrayDeque is really the champion in this case. It performs neither allocations nor moves and beats both ArrayList and LinkedList for all inputs.


Kevin Bourrillion and I will be presenting Caliper at JavaOne 2010 on Thursday, September 23.

glASS HOuses

Using an operating system, programming language, or API for the first time is frustrating. Things don't work the way you'd expect! But stick with it long enough and you grow familiar. Rough edges seem smoother because you're aware of them.

Jack Shedd was frustrated with Android for the first time. He even called it an asshole!
... I discovered software I could find no way to uninstall; programs which hung around after I was done with them with no way to quit I could find; interfaces which featured tiny poorly placed buttons near impossible to click without concentration; inconsistent search functionality where the “it’s right there on the phone” search button worked or didn’t work or did work but not as you’d think it’d work.
These are legitimate problems that should be addressed in Android. But this isn't some damning, intractable systematic problem. It's a handful of papercuts.

Papercuts like these exist in all shipping operating systems; mobile and otherwise. Android users react similarly when they use iPhones. "Holy fuck! There's no back button!" was my own first reaction.

When fanboys like Jack suggest that problems like these don't exist on Apple devices, it's because he's acclimatized to his favourite device's flaws...
  • To Jack, it's obvious that iPhone Mail cannot be uninstalled, but shockingly bad UI that Android Mail has the same behavior.
  • He knows that clicking the close button on Mac OS X will dismiss the window without quitting the app. But when Android behaves similarly, he's outraged!
  • When a Mac shows the same search icon in both Spotlight (local disk) and Safari (Internet), that's elegant. On a Droid, this wasn't expected!

Software is complex. Running unfamiliar programs can be frustrating. But if you condemn a program because it doesn't work just as you expect, you're being an asshole.

Shush! Ringer Restorer update

I just posted the first major update to Shush! Ringer Restorer.

I was unhappy with how the first release used a ListView to pick a duration. The scrollable control wanted fewer options, but users wanted more options. My goal was to make Shush feel fast & simple, but scrolling interfered.

This release replaces the ListView with something new: a circular slider that operates like the hour hand of a clock. It's fun, compact, and pink! Using Android's view and canvas APIs to implement ClockSlider.java was straightforward, despite the necessary trigonometry!

One potentially controversial design decision I made to limit duration granularity: they must be multiples of 30 minutes. I was afraid users would be frustrated trying to select exactly 45 minutes when touch resolution that difficult. Instead, I'm hoping users will just say, "An hour is close enough!"

Scan this to get Shush from the Android Market!

For me, this was a fun Saturday project. Have you written an Android app yet?

Vogar (beta)

Today we open sourced Vogar. It starts out as a simple little tool: you give it a .java file, and it runs it:
$ cat Foo.java 
package foo;

public class Foo {
  public static void main(String[] args) {
    System.out.println("potato");
  }
}

$ ./vogar --stream Foo.java 
Actions: 1
Action foo.Foo
    potato
  OK (SUCCESS)
Outcomes: 1. All successful.

What else?

Vogar also understands JUnit, jtreg, and Caliper benchmarks. It runs code from source or from jar files. It can run code locally, or on an attached Android device. Complete instructions on getting vogar to do your work for you are on the project wiki.

Why bother?

The Dalvik core libraries team wanted to speed up our edit-run-debug development cycle. It's quite satisfying to write a quick test or benchmark and immediately see how it works on a target and reference VM.

Going forward

It's still early days for vogar, but we have ambitious plans! It's already a fine test runner and the best way to run microbenchmarks on Android.

Performance & correctness is the end; vogar is the means!

JSON, JavaScript, and numeric types

One gap in the JSON spec is its coverage of numeric types. Aside from forbidding NaN and infinity, the RFC doesn't limits the range or precision of numeric values:
The representation of numbers is similar to that used in most programming languages. A number contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part.

Octal and hex forms are not allowed. Leading zeros are not allowed.

A fraction part is a decimal point followed by one or more digits.

An exponent part begins with the letter E in upper or lowercase, which may be followed by a plus or minus sign. The E and optional sign are followed by one or more digits.

Numeric values that cannot be represented as sequences of digits (such as Infinity and NaN) are not permitted.

Despite the spec claiming the opposite, this is unlike most programming languages. Formal languages specify ranges for values or defer to standards like IEEE 754.

One workaround is to assume JavaScript semantics: every number is a double. With these semantics, round-tripping a JSON document through JavaScript is lossless.

The alternative, as implemented by Java JSON libraries like Crockford's, Jackson and JSON.simple is to support several numeric types: integer, floating point, and arbitrary precision. In general, documents created with these libraries cannot be roundtripped through JavaScript. Large values like 9007199254740993 need to rounded to a nearby double.

Paste that value into this JavaScript interpreter for an example. (Won't work in feed readers!)



For measurements and counts, the numbers have to be extremely big for rounding to occur. It won't impact epoch dates in the next 285,000 years.

If you're using numbers for identifiers, you have 15 safe digits to work with. Current Twitter tweet IDs are only 11 digits. But if you encode a Java UUID to JSON as two longs, browser roundtrips will corrupt data.

Like every data interchange format, JSON has its gaps and it helps to be mindful of them when mapping between systems.

Feeling Lucky Haiku

Cute little search ads
bring customers to sellers.
Hooray for Google!

Main is varargsable

It's cute, although I admit there isn't much utility in it:
public class Hello {
    public static void main(String... args) {
        System.out.println("yippee!");
    }
}

Java objects: back from the dead

Challenge: can you write code that invokes foo()?
class Impossible {
  public Impossible() {
    throw new AssertionError("you cannot instantiate me");
  }

  public void foo() {
    System.out.println("The impossible is possible!");
  }
}

The solution is in the comments...

Codegen vs. Reflection!

Laurence Gonsalves prefers compile-time code generation over runtime reflection. He writes,
I think all-in-one toolchains (eg: IDEs) are actually part of the reason Java has both not enough magic (like Rob says) and also the wrong kind of magic (runtime reflection). If there was a standard way to plug code generators into Java (or better yet: a Common Lisp-like macro system) then the vast majority of places where people use runtime-magic (reflection) today could be replaced by compile-time magic, and your static analysis tools (ie: compile-time type checking, code navigation tools, refactoring tools, etc.) would actually still work.
Java has a standard way to generate code: the annotation processing tool. Laurence acknowledges APT, but claims it it's useless for his purposes:
[...] I have to say that annotation processors are like lobotomized macros. I did some experiments wit them a few years ago (when Java 5 first came out), and it was pretty difficult to do any useful metaprogramming with them without doing really nasty things.
Among others, one core claim Laurence makes is that refactoring still works if there's a standard way to generate code. I disagree.

Code Generation

Suppose I'm using code generation to do JSON-Java object mapping. One hypothetical code generator takes a JSON text:
{
    "name": "Jesse Wilson",
    "age": 28,
    "favorite taco flavors": [ "fish", "steak" ]
}
...and generates a Java class:
/* GENERATED FILE! DO NOT EDIT */

public class TacoCustomer {
    private final String name;
    private final double age;
    private final ImmutableList<String> favoriteTacoFlavors;
    
    public String getName() {
        return this.name;
    }
    public double getAge() {
        return age;
    }
    public ImmutableList<String> getFavoriteTacoFlavors() {
        return favoriteTacoFlavors;
    }
    public static TacoCustomer parseJson(String jsonText) {
        ...
    }
}
This looks fine enough, almost like code a human would write. But when I exercise my refactoring tool to rename getFavoriteTacoFlavors to getFavoriteTacos, I face one of two ugly situations:
  • It appears to work. But later when I regenerate the code, my edits are clobbered and my application no longer builds. Yuck.
  • It doesn't work, because the generator made the file non-writable file. Now I need to figure out the code generator, use its name mapping to rename accessors, regenerate, and manually fix the callers.
Code generation is bad because you cannot edit your code directly. You need to edit something upstream.

Runtime Reflection

To contrast, here's how the equivalent runtime-reflection solution might look. We manually write an interface that describes our JSON schema, plus some pretty annotations to define the mapping:
public interface TacoCustomer {
    @JsonProperty("name");
    String getName();

    @JsonProperty("age");
    double getAge();

    @JsonProperty("favorite taco flavors");
    ImmutableList<String> getFavoriteTacoFlavors();
}
Exercise the runtime-generated code with a shared, type-safe entry point. It might be invoked like this:
        String jsonText = ...
        TacoCustomer jesse = new JsonToJava().parse(TacoCustomer.class, jsonText);
Refactoring this interface just works, and I can even attach meaningful Javadoc to its methods. The interface can be an inner-interface of another class. And it can host a manually-coded inner classes.

Runtime reflection is good because it lets you put your code wherever you want it, and edit it directly.

Type safety is a means, not an end

Java's type system isn't expressive enough to model everything exactly. But it's expressive enough to be productive!

Our type-unsafety-is-okay precedent is Collection.clear(), JJB's infamous optional method. Type safety advocates see @throws UnsupportedOperationException and claim that it's damning of either the collections framework or the type system. But I claim that each new type (or type parameter!) has a complexity cost and that it may occasionally be better to have fewer types than a perfectly typesafe API.

The tricky bit is deciding where to draw the line. Dynamic language folks ("liberals") think that type safety is overpriced and will prefer fewer types and more possibility for runtime errors. Type safety junkies ("conservatives") want to model the universe as it truly is and must accept a world with type variables, covariance, and wildcards.

What isn't productive is going against the grain of the type system. If you find yourself copying & pasting class declarations to work around a language limitation, you may be trying to use more type safety than the language will bear. Type safety can be unintrusive like a seatbelt. But using APIs with more than two type parameters feels like driving to work in Lancelot's armor.

The opposite end of the spectrum is also quite terrible. An old billing system I worked on used Map<String, Object> as its preferred datatype. We'd live in fear that using an equals() where equalsIgnoreCase() was necessary would cause the next million dollar bug. To use this API was to vomit null checks and casts until simple business logic became complex.

Our jobs as software engineers is to make tasteful decisions about how much type safety is appropriate.