Auto-detect whether to use the long-press UI.

Change-Id: Ie77a5584e301467c6a5e164d2c62d6f036b2c0c0
diff --git a/README.md b/README.md
index c0833f2..bab7e87 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,9 @@
 Quick turn-around testing
 -------------------------
 
-    mm -j
-    m ramdisk-nodeps
-    m recoveryimage-nodeps
-    adb reboot bootloader
+    mm -j && m ramdisk-nodeps && m recoveryimage-nodeps
 
     # To boot into the new recovery image
     # without flashing the recovery partition:
+    adb reboot bootloader
     fastboot boot $ANDROID_PRODUCT_OUT/recovery.img
diff --git a/default_device.cpp b/default_device.cpp
index d7dd452..a971866 100644
--- a/default_device.cpp
+++ b/default_device.cpp
@@ -17,33 +17,6 @@
 #include "device.h"
 #include "screen_ui.h"
 
-class DefaultDevice : public Device {
- public:
-  DefaultDevice() : Device(new ScreenRecoveryUI) {
-  }
-
-  // TODO: make this handle more cases, and move the default implementation into Device too.
-  int HandleMenuKey(int key, int visible) {
-    if (visible) {
-      switch (key) {
-        case KEY_DOWN:
-        case KEY_VOLUMEDOWN:
-          return kHighlightDown;
-
-        case KEY_UP:
-        case KEY_VOLUMEUP:
-          return kHighlightUp;
-
-        case KEY_ENTER:
-        case KEY_POWER:
-          return kInvokeItem;
-      }
-    }
-
-    return kNoAction;
-  }
-};
-
 Device* make_device() {
-  return new DefaultDevice;
+  return new Device(new ScreenRecoveryUI);
 }
diff --git a/device.cpp b/device.cpp
index af92b15..024fc34 100644
--- a/device.cpp
+++ b/device.cpp
@@ -16,15 +16,21 @@
 
 #include "device.h"
 
-// TODO: this is a lie for, say, fugu.
-static const char* HEADERS[] = {
-    "Volume up/down to move highlight.",
-    "Power button to select.",
+static const char* REGULAR_HEADERS[] = {
+    "Volume up/down move highlight.",
+    "Power button activates.",
     "",
     NULL
 };
 
-static const char* ITEMS[] = {
+static const char* LONG_PRESS_HEADERS[] = {
+    "Any button cycles highlight.",
+    "Long-press activates.",
+    "",
+    NULL
+};
+
+static const char* MENU_ITEMS[] = {
     "Reboot system now",
     "Reboot to bootloader",
     "Apply update from ADB",
@@ -37,8 +43,13 @@
     NULL
 };
 
-const char* const* Device::GetMenuHeaders() { return HEADERS; }
-const char* const* Device::GetMenuItems() { return ITEMS; }
+const char* const* Device::GetMenuHeaders() {
+  return ui_->HasThreeButtons() ? REGULAR_HEADERS : LONG_PRESS_HEADERS;
+}
+
+const char* const* Device::GetMenuItems() {
+  return MENU_ITEMS;
+}
 
 Device::BuiltinAction Device::InvokeMenuItem(int menu_position) {
   switch (menu_position) {
@@ -54,3 +65,28 @@
     default: return NO_ACTION;
   }
 }
+
+int Device::HandleMenuKey(int key, int visible) {
+  if (!visible) {
+    return kNoAction;
+  }
+
+  switch (key) {
+    case KEY_DOWN:
+    case KEY_VOLUMEDOWN:
+      return kHighlightDown;
+
+    case KEY_UP:
+    case KEY_VOLUMEUP:
+      return kHighlightUp;
+
+    case KEY_ENTER:
+    case KEY_POWER:
+      return kInvokeItem;
+
+    default:
+      // If you have all of the above buttons, any other buttons
+      // are ignored. Otherwise, any button cycles the highlight.
+      return ui_->HasThreeButtons() ? kNoAction : kHighlightDown;
+  }
+}
diff --git a/device.h b/device.h
index 3d9101b..1507183 100644
--- a/device.h
+++ b/device.h
@@ -54,7 +54,7 @@
     //   - invoke the highlighted item (kInvokeItem)
     //   - do nothing (kNoAction)
     //   - invoke a specific action (a menu position: any non-negative number)
-    virtual int HandleMenuKey(int key, int visible) = 0;
+    virtual int HandleMenuKey(int key, int visible);
 
     enum BuiltinAction {
         NO_ACTION = 0,
diff --git a/ui.cpp b/ui.cpp
index 064890e..dbe5c51 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -278,6 +278,10 @@
     return result;
 }
 
+bool RecoveryUI::HasThreeButtons() {
+    return has_power_key && has_up_key && has_down_key;
+}
+
 void RecoveryUI::FlushKeys() {
     pthread_mutex_lock(&key_queue_mutex);
     key_queue_len = 0;
@@ -290,7 +294,7 @@
     pthread_mutex_unlock(&key_queue_mutex);
 
     // If we have power and volume up keys, that chord is the signal to toggle the text display.
-    if (has_power_key && has_up_key) {
+    if (HasThreeButtons()) {
         if (key == KEY_VOLUMEUP && IsKeyPressed(KEY_POWER)) {
             return TOGGLE;
         }
diff --git a/ui.h b/ui.h
index 0d5ab55..c5c65c2 100644
--- a/ui.h
+++ b/ui.h
@@ -75,6 +75,10 @@
     virtual bool IsKeyPressed(int key);
     virtual bool IsLongPress();
 
+    // Returns true if you have the volume up/down and power trio typical
+    // of phones and tablets, false otherwise.
+    virtual bool HasThreeButtons();
+
     // Erase any queued-up keys.
     virtual void FlushKeys();