Add android.mojo application.

This application exposes android specific capabilities.

R=ppi@chromium.org
BUG=Fixes https://github.com/domokit/mojo/issues/557, https://github.com/domokit/mojo/issues/502, https://github.com/domokit/mojo/issues/503

Review URL: https://codereview.chromium.org/1468913003 .
diff --git a/mojo/dart/packages/mojo_services/lib/activity/activity.mojom.dart b/mojo/dart/packages/mojo_services/lib/activity/activity.mojom.dart
new file mode 100644
index 0000000..ef2fc79
--- /dev/null
+++ b/mojo/dart/packages/mojo_services/lib/activity/activity.mojom.dart
@@ -0,0 +1,2324 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library activity_mojom;
+
+import 'dart:async';
+
+import 'package:mojo/bindings.dart' as bindings;
+import 'package:mojo/core.dart' as core;
+class SystemUiVisibility extends bindings.MojoEnum {
+  static const STANDARD = const SystemUiVisibility._(0);
+  static const FULLSCREEN = const SystemUiVisibility._(1);
+  static const IMMERSIVE = const SystemUiVisibility._(2);
+
+  const SystemUiVisibility._(int v) : super(v);
+
+  static const Map<String, SystemUiVisibility> valuesMap = const {
+    "STANDARD": STANDARD,
+    "FULLSCREEN": FULLSCREEN,
+    "IMMERSIVE": IMMERSIVE,
+  };
+  static const List<SystemUiVisibility> values = const [
+    STANDARD,
+    FULLSCREEN,
+    IMMERSIVE,
+  ];
+
+  static SystemUiVisibility valueOf(String name) => valuesMap[name];
+
+  factory SystemUiVisibility(int v) {
+    switch (v) {
+      case 0:
+        return STANDARD;
+      case 1:
+        return FULLSCREEN;
+      case 2:
+        return IMMERSIVE;
+      default:
+        return null;
+    }
+  }
+
+  static SystemUiVisibility decode(bindings.Decoder decoder0, int offset) {
+    int v = decoder0.decodeUint32(offset);
+    SystemUiVisibility result = new SystemUiVisibility(v);
+    if (result == null) {
+      throw new bindings.MojoCodecError(
+          'Bad value $v for enum SystemUiVisibility.');
+    }
+    return result;
+  }
+
+  String toString() {
+    switch(this) {
+      case STANDARD:
+        return 'SystemUiVisibility.STANDARD';
+      case FULLSCREEN:
+        return 'SystemUiVisibility.FULLSCREEN';
+      case IMMERSIVE:
+        return 'SystemUiVisibility.IMMERSIVE';
+    }
+  }
+
+  int toJson() => value;
+}
+class ScreenOrientation extends bindings.MojoEnum {
+  static const UNSPECIFIED = const ScreenOrientation._(0);
+  static const LANDSCAPE = const ScreenOrientation._(1);
+  static const PORTRAIT = const ScreenOrientation._(2);
+  static const NOSENSOR = const ScreenOrientation._(3);
+
+  const ScreenOrientation._(int v) : super(v);
+
+  static const Map<String, ScreenOrientation> valuesMap = const {
+    "UNSPECIFIED": UNSPECIFIED,
+    "LANDSCAPE": LANDSCAPE,
+    "PORTRAIT": PORTRAIT,
+    "NOSENSOR": NOSENSOR,
+  };
+  static const List<ScreenOrientation> values = const [
+    UNSPECIFIED,
+    LANDSCAPE,
+    PORTRAIT,
+    NOSENSOR,
+  ];
+
+  static ScreenOrientation valueOf(String name) => valuesMap[name];
+
+  factory ScreenOrientation(int v) {
+    switch (v) {
+      case 0:
+        return UNSPECIFIED;
+      case 1:
+        return LANDSCAPE;
+      case 2:
+        return PORTRAIT;
+      case 3:
+        return NOSENSOR;
+      default:
+        return null;
+    }
+  }
+
+  static ScreenOrientation decode(bindings.Decoder decoder0, int offset) {
+    int v = decoder0.decodeUint32(offset);
+    ScreenOrientation result = new ScreenOrientation(v);
+    if (result == null) {
+      throw new bindings.MojoCodecError(
+          'Bad value $v for enum ScreenOrientation.');
+    }
+    return result;
+  }
+
+  String toString() {
+    switch(this) {
+      case UNSPECIFIED:
+        return 'ScreenOrientation.UNSPECIFIED';
+      case LANDSCAPE:
+        return 'ScreenOrientation.LANDSCAPE';
+      case PORTRAIT:
+        return 'ScreenOrientation.PORTRAIT';
+      case NOSENSOR:
+        return 'ScreenOrientation.NOSENSOR';
+    }
+  }
+
+  int toJson() => value;
+}
+class HapticFeedbackType extends bindings.MojoEnum {
+  static const LONG_PRESS = const HapticFeedbackType._(0);
+  static const VIRTUAL_KEY = const HapticFeedbackType._(1);
+  static const KEYBOARD_TAP = const HapticFeedbackType._(2);
+  static const CLOCK_TICK = const HapticFeedbackType._(3);
+
+  const HapticFeedbackType._(int v) : super(v);
+
+  static const Map<String, HapticFeedbackType> valuesMap = const {
+    "LONG_PRESS": LONG_PRESS,
+    "VIRTUAL_KEY": VIRTUAL_KEY,
+    "KEYBOARD_TAP": KEYBOARD_TAP,
+    "CLOCK_TICK": CLOCK_TICK,
+  };
+  static const List<HapticFeedbackType> values = const [
+    LONG_PRESS,
+    VIRTUAL_KEY,
+    KEYBOARD_TAP,
+    CLOCK_TICK,
+  ];
+
+  static HapticFeedbackType valueOf(String name) => valuesMap[name];
+
+  factory HapticFeedbackType(int v) {
+    switch (v) {
+      case 0:
+        return LONG_PRESS;
+      case 1:
+        return VIRTUAL_KEY;
+      case 2:
+        return KEYBOARD_TAP;
+      case 3:
+        return CLOCK_TICK;
+      default:
+        return null;
+    }
+  }
+
+  static HapticFeedbackType decode(bindings.Decoder decoder0, int offset) {
+    int v = decoder0.decodeUint32(offset);
+    HapticFeedbackType result = new HapticFeedbackType(v);
+    if (result == null) {
+      throw new bindings.MojoCodecError(
+          'Bad value $v for enum HapticFeedbackType.');
+    }
+    return result;
+  }
+
+  String toString() {
+    switch(this) {
+      case LONG_PRESS:
+        return 'HapticFeedbackType.LONG_PRESS';
+      case VIRTUAL_KEY:
+        return 'HapticFeedbackType.VIRTUAL_KEY';
+      case KEYBOARD_TAP:
+        return 'HapticFeedbackType.KEYBOARD_TAP';
+      case CLOCK_TICK:
+        return 'HapticFeedbackType.CLOCK_TICK';
+    }
+  }
+
+  int toJson() => value;
+}
+class AuralFeedbackType extends bindings.MojoEnum {
+  static const CLICK = const AuralFeedbackType._(0);
+  static const NAVIGATION_LEFT = const AuralFeedbackType._(1);
+  static const NAVIGATION_UP = const AuralFeedbackType._(2);
+  static const NAVIGATION_RIGHT = const AuralFeedbackType._(3);
+  static const NAVIGATION_DOWN = const AuralFeedbackType._(4);
+
+  const AuralFeedbackType._(int v) : super(v);
+
+  static const Map<String, AuralFeedbackType> valuesMap = const {
+    "CLICK": CLICK,
+    "NAVIGATION_LEFT": NAVIGATION_LEFT,
+    "NAVIGATION_UP": NAVIGATION_UP,
+    "NAVIGATION_RIGHT": NAVIGATION_RIGHT,
+    "NAVIGATION_DOWN": NAVIGATION_DOWN,
+  };
+  static const List<AuralFeedbackType> values = const [
+    CLICK,
+    NAVIGATION_LEFT,
+    NAVIGATION_UP,
+    NAVIGATION_RIGHT,
+    NAVIGATION_DOWN,
+  ];
+
+  static AuralFeedbackType valueOf(String name) => valuesMap[name];
+
+  factory AuralFeedbackType(int v) {
+    switch (v) {
+      case 0:
+        return CLICK;
+      case 1:
+        return NAVIGATION_LEFT;
+      case 2:
+        return NAVIGATION_UP;
+      case 3:
+        return NAVIGATION_RIGHT;
+      case 4:
+        return NAVIGATION_DOWN;
+      default:
+        return null;
+    }
+  }
+
+  static AuralFeedbackType decode(bindings.Decoder decoder0, int offset) {
+    int v = decoder0.decodeUint32(offset);
+    AuralFeedbackType result = new AuralFeedbackType(v);
+    if (result == null) {
+      throw new bindings.MojoCodecError(
+          'Bad value $v for enum AuralFeedbackType.');
+    }
+    return result;
+  }
+
+  String toString() {
+    switch(this) {
+      case CLICK:
+        return 'AuralFeedbackType.CLICK';
+      case NAVIGATION_LEFT:
+        return 'AuralFeedbackType.NAVIGATION_LEFT';
+      case NAVIGATION_UP:
+        return 'AuralFeedbackType.NAVIGATION_UP';
+      case NAVIGATION_RIGHT:
+        return 'AuralFeedbackType.NAVIGATION_RIGHT';
+      case NAVIGATION_DOWN:
+        return 'AuralFeedbackType.NAVIGATION_DOWN';
+    }
+  }
+
+  int toJson() => value;
+}
+
+
+
+class StringExtra extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(24, 0)
+  ];
+  String name = null;
+  String value = null;
+
+  StringExtra() : super(kVersions.last.size);
+
+  static StringExtra deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static StringExtra decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    StringExtra result = new StringExtra();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.name = decoder0.decodeString(8, false);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.value = decoder0.decodeString(16, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(name, 8, false);
+    
+    encoder0.encodeString(value, 16, false);
+  }
+
+  String toString() {
+    return "StringExtra("
+           "name: $name" ", "
+           "value: $value" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["name"] = name;
+    map["value"] = value;
+    return map;
+  }
+}
+
+
+class ComponentName extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(24, 0)
+  ];
+  String packageName = null;
+  String className = null;
+
+  ComponentName() : super(kVersions.last.size);
+
+  static ComponentName deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ComponentName decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ComponentName result = new ComponentName();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.packageName = decoder0.decodeString(8, false);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.className = decoder0.decodeString(16, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(packageName, 8, false);
+    
+    encoder0.encodeString(className, 16, false);
+  }
+
+  String toString() {
+    return "ComponentName("
+           "packageName: $packageName" ", "
+           "className: $className" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["packageName"] = packageName;
+    map["className"] = className;
+    return map;
+  }
+}
+
+
+class Intent extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(56, 0)
+  ];
+  String action = null;
+  String url = null;
+  int flags = 0;
+  ComponentName component = null;
+  List<StringExtra> stringExtras = null;
+  String type = null;
+
+  Intent() : super(kVersions.last.size);
+
+  static Intent deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static Intent decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    Intent result = new Intent();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.action = decoder0.decodeString(8, false);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.url = decoder0.decodeString(16, false);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.flags = decoder0.decodeUint32(24);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      var decoder1 = decoder0.decodePointer(32, true);
+      result.component = ComponentName.decode(decoder1);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      var decoder1 = decoder0.decodePointer(40, true);
+      if (decoder1 == null) {
+        result.stringExtras = null;
+      } else {
+        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
+        result.stringExtras = new List<StringExtra>(si1.numElements);
+        for (int i1 = 0; i1 < si1.numElements; ++i1) {
+          
+          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
+          result.stringExtras[i1] = StringExtra.decode(decoder2);
+        }
+      }
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.type = decoder0.decodeString(48, true);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(action, 8, false);
+    
+    encoder0.encodeString(url, 16, false);
+    
+    encoder0.encodeUint32(flags, 24);
+    
+    encoder0.encodeStruct(component, 32, true);
+    
+    if (stringExtras == null) {
+      encoder0.encodeNullPointer(40, true);
+    } else {
+      var encoder1 = encoder0.encodePointerArray(stringExtras.length, 40, bindings.kUnspecifiedArrayLength);
+      for (int i0 = 0; i0 < stringExtras.length; ++i0) {
+        
+        encoder1.encodeStruct(stringExtras[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
+      }
+    }
+    
+    encoder0.encodeString(type, 48, true);
+  }
+
+  String toString() {
+    return "Intent("
+           "action: $action" ", "
+           "url: $url" ", "
+           "flags: $flags" ", "
+           "component: $component" ", "
+           "stringExtras: $stringExtras" ", "
+           "type: $type" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["action"] = action;
+    map["url"] = url;
+    map["flags"] = flags;
+    map["component"] = component;
+    map["stringExtras"] = stringExtras;
+    map["type"] = type;
+    return map;
+  }
+}
+
+
+class TaskDescription extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(24, 0)
+  ];
+  String label = null;
+  int primaryColor = 0;
+
+  TaskDescription() : super(kVersions.last.size);
+
+  static TaskDescription deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static TaskDescription decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    TaskDescription result = new TaskDescription();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.label = decoder0.decodeString(8, true);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.primaryColor = decoder0.decodeUint32(16);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(label, 8, true);
+    
+    encoder0.encodeUint32(primaryColor, 16);
+  }
+
+  String toString() {
+    return "TaskDescription("
+           "label: $label" ", "
+           "primaryColor: $primaryColor" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["label"] = label;
+    map["primaryColor"] = primaryColor;
+    return map;
+  }
+}
+
+
+class ActivityGetUserFeedbackParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  Object userFeedback = null;
+
+  ActivityGetUserFeedbackParams() : super(kVersions.last.size);
+
+  static ActivityGetUserFeedbackParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ActivityGetUserFeedbackParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ActivityGetUserFeedbackParams result = new ActivityGetUserFeedbackParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.userFeedback = decoder0.decodeInterfaceRequest(8, false, UserFeedbackStub.newFromEndpoint);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeInterfaceRequest(userFeedback, 8, false);
+  }
+
+  String toString() {
+    return "ActivityGetUserFeedbackParams("
+           "userFeedback: $userFeedback" ")";
+  }
+
+  Map toJson() {
+    throw new bindings.MojoCodecError(
+        'Object containing handles cannot be encoded to JSON.');
+  }
+}
+
+
+class ActivityStartActivityParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  Intent intent = null;
+
+  ActivityStartActivityParams() : super(kVersions.last.size);
+
+  static ActivityStartActivityParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ActivityStartActivityParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ActivityStartActivityParams result = new ActivityStartActivityParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      var decoder1 = decoder0.decodePointer(8, false);
+      result.intent = Intent.decode(decoder1);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeStruct(intent, 8, false);
+  }
+
+  String toString() {
+    return "ActivityStartActivityParams("
+           "intent: $intent" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["intent"] = intent;
+    return map;
+  }
+}
+
+
+class ActivityFinishCurrentActivityParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  ActivityFinishCurrentActivityParams() : super(kVersions.last.size);
+
+  static ActivityFinishCurrentActivityParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ActivityFinishCurrentActivityParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ActivityFinishCurrentActivityParams result = new ActivityFinishCurrentActivityParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "ActivityFinishCurrentActivityParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+class ActivitySetTaskDescriptionParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  TaskDescription description = null;
+
+  ActivitySetTaskDescriptionParams() : super(kVersions.last.size);
+
+  static ActivitySetTaskDescriptionParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ActivitySetTaskDescriptionParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ActivitySetTaskDescriptionParams result = new ActivitySetTaskDescriptionParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      var decoder1 = decoder0.decodePointer(8, false);
+      result.description = TaskDescription.decode(decoder1);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeStruct(description, 8, false);
+  }
+
+  String toString() {
+    return "ActivitySetTaskDescriptionParams("
+           "description: $description" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["description"] = description;
+    return map;
+  }
+}
+
+
+class ActivitySetSystemUiVisibilityParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  SystemUiVisibility visibility = null;
+
+  ActivitySetSystemUiVisibilityParams() : super(kVersions.last.size);
+
+  static ActivitySetSystemUiVisibilityParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ActivitySetSystemUiVisibilityParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ActivitySetSystemUiVisibilityParams result = new ActivitySetSystemUiVisibilityParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+        result.visibility = SystemUiVisibility.decode(decoder0, 8);
+        if (result.visibility == null) {
+          throw new bindings.MojoCodecError(
+            'Trying to decode null union for non-nullable SystemUiVisibility.');
+        }
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeEnum(visibility, 8);
+  }
+
+  String toString() {
+    return "ActivitySetSystemUiVisibilityParams("
+           "visibility: $visibility" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["visibility"] = visibility;
+    return map;
+  }
+}
+
+
+class ActivitySetRequestedOrientationParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  ScreenOrientation orientation = null;
+
+  ActivitySetRequestedOrientationParams() : super(kVersions.last.size);
+
+  static ActivitySetRequestedOrientationParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static ActivitySetRequestedOrientationParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    ActivitySetRequestedOrientationParams result = new ActivitySetRequestedOrientationParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+        result.orientation = ScreenOrientation.decode(decoder0, 8);
+        if (result.orientation == null) {
+          throw new bindings.MojoCodecError(
+            'Trying to decode null union for non-nullable ScreenOrientation.');
+        }
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeEnum(orientation, 8);
+  }
+
+  String toString() {
+    return "ActivitySetRequestedOrientationParams("
+           "orientation: $orientation" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["orientation"] = orientation;
+    return map;
+  }
+}
+
+
+class PathServiceGetAppDataDirParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  PathServiceGetAppDataDirParams() : super(kVersions.last.size);
+
+  static PathServiceGetAppDataDirParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static PathServiceGetAppDataDirParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    PathServiceGetAppDataDirParams result = new PathServiceGetAppDataDirParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "PathServiceGetAppDataDirParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+class PathServiceGetAppDataDirResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String path = null;
+
+  PathServiceGetAppDataDirResponseParams() : super(kVersions.last.size);
+
+  static PathServiceGetAppDataDirResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static PathServiceGetAppDataDirResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    PathServiceGetAppDataDirResponseParams result = new PathServiceGetAppDataDirResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.path = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(path, 8, false);
+  }
+
+  String toString() {
+    return "PathServiceGetAppDataDirResponseParams("
+           "path: $path" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["path"] = path;
+    return map;
+  }
+}
+
+
+class PathServiceGetFilesDirParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  PathServiceGetFilesDirParams() : super(kVersions.last.size);
+
+  static PathServiceGetFilesDirParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static PathServiceGetFilesDirParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    PathServiceGetFilesDirParams result = new PathServiceGetFilesDirParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "PathServiceGetFilesDirParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+class PathServiceGetFilesDirResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String path = null;
+
+  PathServiceGetFilesDirResponseParams() : super(kVersions.last.size);
+
+  static PathServiceGetFilesDirResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static PathServiceGetFilesDirResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    PathServiceGetFilesDirResponseParams result = new PathServiceGetFilesDirResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.path = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(path, 8, false);
+  }
+
+  String toString() {
+    return "PathServiceGetFilesDirResponseParams("
+           "path: $path" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["path"] = path;
+    return map;
+  }
+}
+
+
+class PathServiceGetCacheDirParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  PathServiceGetCacheDirParams() : super(kVersions.last.size);
+
+  static PathServiceGetCacheDirParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static PathServiceGetCacheDirParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    PathServiceGetCacheDirParams result = new PathServiceGetCacheDirParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "PathServiceGetCacheDirParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+class PathServiceGetCacheDirResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String path = null;
+
+  PathServiceGetCacheDirResponseParams() : super(kVersions.last.size);
+
+  static PathServiceGetCacheDirResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static PathServiceGetCacheDirResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    PathServiceGetCacheDirResponseParams result = new PathServiceGetCacheDirResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.path = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(path, 8, false);
+  }
+
+  String toString() {
+    return "PathServiceGetCacheDirResponseParams("
+           "path: $path" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["path"] = path;
+    return map;
+  }
+}
+
+
+class UserFeedbackPerformHapticFeedbackParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  HapticFeedbackType type = null;
+
+  UserFeedbackPerformHapticFeedbackParams() : super(kVersions.last.size);
+
+  static UserFeedbackPerformHapticFeedbackParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UserFeedbackPerformHapticFeedbackParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UserFeedbackPerformHapticFeedbackParams result = new UserFeedbackPerformHapticFeedbackParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+        result.type = HapticFeedbackType.decode(decoder0, 8);
+        if (result.type == null) {
+          throw new bindings.MojoCodecError(
+            'Trying to decode null union for non-nullable HapticFeedbackType.');
+        }
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeEnum(type, 8);
+  }
+
+  String toString() {
+    return "UserFeedbackPerformHapticFeedbackParams("
+           "type: $type" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["type"] = type;
+    return map;
+  }
+}
+
+
+class UserFeedbackPerformAuralFeedbackParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  AuralFeedbackType type = null;
+
+  UserFeedbackPerformAuralFeedbackParams() : super(kVersions.last.size);
+
+  static UserFeedbackPerformAuralFeedbackParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UserFeedbackPerformAuralFeedbackParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UserFeedbackPerformAuralFeedbackParams result = new UserFeedbackPerformAuralFeedbackParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+        result.type = AuralFeedbackType.decode(decoder0, 8);
+        if (result.type == null) {
+          throw new bindings.MojoCodecError(
+            'Trying to decode null union for non-nullable AuralFeedbackType.');
+        }
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeEnum(type, 8);
+  }
+
+  String toString() {
+    return "UserFeedbackPerformAuralFeedbackParams("
+           "type: $type" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["type"] = type;
+    return map;
+  }
+}
+
+const int kActivity_getUserFeedback_name = 0;
+const int kActivity_startActivity_name = 1;
+const int kActivity_finishCurrentActivity_name = 2;
+const int kActivity_setTaskDescription_name = 3;
+const int kActivity_setSystemUiVisibility_name = 4;
+const int kActivity_setRequestedOrientation_name = 5;
+
+const String ActivityName =
+      'activity::Activity';
+
+abstract class Activity {
+  void getUserFeedback(Object userFeedback);
+  void startActivity(Intent intent);
+  void finishCurrentActivity();
+  void setTaskDescription(TaskDescription description);
+  void setSystemUiVisibility(SystemUiVisibility visibility);
+  void setRequestedOrientation(ScreenOrientation orientation);
+
+}
+
+
+class ActivityProxyImpl extends bindings.Proxy {
+  ActivityProxyImpl.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
+
+  ActivityProxyImpl.fromHandle(core.MojoHandle handle) :
+      super.fromHandle(handle);
+
+  ActivityProxyImpl.unbound() : super.unbound();
+
+  static ActivityProxyImpl newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For ActivityProxyImpl"));
+    return new ActivityProxyImpl.fromEndpoint(endpoint);
+  }
+
+  String get name => ActivityName;
+
+  void handleResponse(bindings.ServiceMessage message) {
+    switch (message.header.type) {
+      default:
+        proxyError("Unexpected message type: ${message.header.type}");
+        close(immediate: true);
+        break;
+    }
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "ActivityProxyImpl($superString)";
+  }
+}
+
+
+class _ActivityProxyCalls implements Activity {
+  ActivityProxyImpl _proxyImpl;
+
+  _ActivityProxyCalls(this._proxyImpl);
+    void getUserFeedback(Object userFeedback) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new ActivityGetUserFeedbackParams();
+      params.userFeedback = userFeedback;
+      _proxyImpl.sendMessage(params, kActivity_getUserFeedback_name);
+    }
+  
+    void startActivity(Intent intent) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new ActivityStartActivityParams();
+      params.intent = intent;
+      _proxyImpl.sendMessage(params, kActivity_startActivity_name);
+    }
+  
+    void finishCurrentActivity() {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new ActivityFinishCurrentActivityParams();
+      _proxyImpl.sendMessage(params, kActivity_finishCurrentActivity_name);
+    }
+  
+    void setTaskDescription(TaskDescription description) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new ActivitySetTaskDescriptionParams();
+      params.description = description;
+      _proxyImpl.sendMessage(params, kActivity_setTaskDescription_name);
+    }
+  
+    void setSystemUiVisibility(SystemUiVisibility visibility) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new ActivitySetSystemUiVisibilityParams();
+      params.visibility = visibility;
+      _proxyImpl.sendMessage(params, kActivity_setSystemUiVisibility_name);
+    }
+  
+    void setRequestedOrientation(ScreenOrientation orientation) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new ActivitySetRequestedOrientationParams();
+      params.orientation = orientation;
+      _proxyImpl.sendMessage(params, kActivity_setRequestedOrientation_name);
+    }
+  
+}
+
+
+class ActivityProxy implements bindings.ProxyBase {
+  final bindings.Proxy impl;
+  Activity ptr;
+  final String name = ActivityName;
+
+  ActivityProxy(ActivityProxyImpl proxyImpl) :
+      impl = proxyImpl,
+      ptr = new _ActivityProxyCalls(proxyImpl);
+
+  ActivityProxy.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) :
+      impl = new ActivityProxyImpl.fromEndpoint(endpoint) {
+    ptr = new _ActivityProxyCalls(impl);
+  }
+
+  ActivityProxy.fromHandle(core.MojoHandle handle) :
+      impl = new ActivityProxyImpl.fromHandle(handle) {
+    ptr = new _ActivityProxyCalls(impl);
+  }
+
+  ActivityProxy.unbound() :
+      impl = new ActivityProxyImpl.unbound() {
+    ptr = new _ActivityProxyCalls(impl);
+  }
+
+  factory ActivityProxy.connectToService(
+      bindings.ServiceConnector s, String url) {
+    ActivityProxy p = new ActivityProxy.unbound();
+    s.connectToService(url, p);
+    return p;
+  }
+
+  static ActivityProxy newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For ActivityProxy"));
+    return new ActivityProxy.fromEndpoint(endpoint);
+  }
+
+  Future close({bool immediate: false}) => impl.close(immediate: immediate);
+
+  Future responseOrError(Future f) => impl.responseOrError(f);
+
+  Future get errorFuture => impl.errorFuture;
+
+  int get version => impl.version;
+
+  Future<int> queryVersion() => impl.queryVersion();
+
+  void requireVersion(int requiredVersion) {
+    impl.requireVersion(requiredVersion);
+  }
+
+  String toString() {
+    return "ActivityProxy($impl)";
+  }
+}
+
+
+class ActivityStub extends bindings.Stub {
+  Activity _impl = null;
+
+  ActivityStub.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint, [this._impl])
+      : super.fromEndpoint(endpoint);
+
+  ActivityStub.fromHandle(core.MojoHandle handle, [this._impl])
+      : super.fromHandle(handle);
+
+  ActivityStub.unbound() : super.unbound();
+
+  static ActivityStub newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For ActivityStub"));
+    return new ActivityStub.fromEndpoint(endpoint);
+  }
+
+  static const String name = ActivityName;
+
+
+
+  dynamic handleMessage(bindings.ServiceMessage message) {
+    if (bindings.ControlMessageHandler.isControlMessage(message)) {
+      return bindings.ControlMessageHandler.handleMessage(this,
+                                                          0,
+                                                          message);
+    }
+    assert(_impl != null);
+    switch (message.header.type) {
+      case kActivity_getUserFeedback_name:
+        var params = ActivityGetUserFeedbackParams.deserialize(
+            message.payload);
+        _impl.getUserFeedback(params.userFeedback);
+        break;
+      case kActivity_startActivity_name:
+        var params = ActivityStartActivityParams.deserialize(
+            message.payload);
+        _impl.startActivity(params.intent);
+        break;
+      case kActivity_finishCurrentActivity_name:
+        var params = ActivityFinishCurrentActivityParams.deserialize(
+            message.payload);
+        _impl.finishCurrentActivity();
+        break;
+      case kActivity_setTaskDescription_name:
+        var params = ActivitySetTaskDescriptionParams.deserialize(
+            message.payload);
+        _impl.setTaskDescription(params.description);
+        break;
+      case kActivity_setSystemUiVisibility_name:
+        var params = ActivitySetSystemUiVisibilityParams.deserialize(
+            message.payload);
+        _impl.setSystemUiVisibility(params.visibility);
+        break;
+      case kActivity_setRequestedOrientation_name:
+        var params = ActivitySetRequestedOrientationParams.deserialize(
+            message.payload);
+        _impl.setRequestedOrientation(params.orientation);
+        break;
+      default:
+        throw new bindings.MojoCodecError("Unexpected message name");
+        break;
+    }
+    return null;
+  }
+
+  Activity get impl => _impl;
+  set impl(Activity d) {
+    assert(_impl == null);
+    _impl = d;
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "ActivityStub($superString)";
+  }
+
+  int get version => 0;
+}
+
+const int kPathService_getAppDataDir_name = 0;
+const int kPathService_getFilesDir_name = 1;
+const int kPathService_getCacheDir_name = 2;
+
+const String PathServiceName =
+      'activity::PathService';
+
+abstract class PathService {
+  dynamic getAppDataDir([Function responseFactory = null]);
+  dynamic getFilesDir([Function responseFactory = null]);
+  dynamic getCacheDir([Function responseFactory = null]);
+
+}
+
+
+class PathServiceProxyImpl extends bindings.Proxy {
+  PathServiceProxyImpl.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
+
+  PathServiceProxyImpl.fromHandle(core.MojoHandle handle) :
+      super.fromHandle(handle);
+
+  PathServiceProxyImpl.unbound() : super.unbound();
+
+  static PathServiceProxyImpl newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For PathServiceProxyImpl"));
+    return new PathServiceProxyImpl.fromEndpoint(endpoint);
+  }
+
+  String get name => PathServiceName;
+
+  void handleResponse(bindings.ServiceMessage message) {
+    switch (message.header.type) {
+      case kPathService_getAppDataDir_name:
+        var r = PathServiceGetAppDataDirResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case kPathService_getFilesDir_name:
+        var r = PathServiceGetFilesDirResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case kPathService_getCacheDir_name:
+        var r = PathServiceGetCacheDirResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      default:
+        proxyError("Unexpected message type: ${message.header.type}");
+        close(immediate: true);
+        break;
+    }
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "PathServiceProxyImpl($superString)";
+  }
+}
+
+
+class _PathServiceProxyCalls implements PathService {
+  PathServiceProxyImpl _proxyImpl;
+
+  _PathServiceProxyCalls(this._proxyImpl);
+    dynamic getAppDataDir([Function responseFactory = null]) {
+      var params = new PathServiceGetAppDataDirParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          kPathService_getAppDataDir_name,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getFilesDir([Function responseFactory = null]) {
+      var params = new PathServiceGetFilesDirParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          kPathService_getFilesDir_name,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getCacheDir([Function responseFactory = null]) {
+      var params = new PathServiceGetCacheDirParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          kPathService_getCacheDir_name,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+}
+
+
+class PathServiceProxy implements bindings.ProxyBase {
+  final bindings.Proxy impl;
+  PathService ptr;
+  final String name = PathServiceName;
+
+  PathServiceProxy(PathServiceProxyImpl proxyImpl) :
+      impl = proxyImpl,
+      ptr = new _PathServiceProxyCalls(proxyImpl);
+
+  PathServiceProxy.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) :
+      impl = new PathServiceProxyImpl.fromEndpoint(endpoint) {
+    ptr = new _PathServiceProxyCalls(impl);
+  }
+
+  PathServiceProxy.fromHandle(core.MojoHandle handle) :
+      impl = new PathServiceProxyImpl.fromHandle(handle) {
+    ptr = new _PathServiceProxyCalls(impl);
+  }
+
+  PathServiceProxy.unbound() :
+      impl = new PathServiceProxyImpl.unbound() {
+    ptr = new _PathServiceProxyCalls(impl);
+  }
+
+  factory PathServiceProxy.connectToService(
+      bindings.ServiceConnector s, String url) {
+    PathServiceProxy p = new PathServiceProxy.unbound();
+    s.connectToService(url, p);
+    return p;
+  }
+
+  static PathServiceProxy newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For PathServiceProxy"));
+    return new PathServiceProxy.fromEndpoint(endpoint);
+  }
+
+  Future close({bool immediate: false}) => impl.close(immediate: immediate);
+
+  Future responseOrError(Future f) => impl.responseOrError(f);
+
+  Future get errorFuture => impl.errorFuture;
+
+  int get version => impl.version;
+
+  Future<int> queryVersion() => impl.queryVersion();
+
+  void requireVersion(int requiredVersion) {
+    impl.requireVersion(requiredVersion);
+  }
+
+  String toString() {
+    return "PathServiceProxy($impl)";
+  }
+}
+
+
+class PathServiceStub extends bindings.Stub {
+  PathService _impl = null;
+
+  PathServiceStub.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint, [this._impl])
+      : super.fromEndpoint(endpoint);
+
+  PathServiceStub.fromHandle(core.MojoHandle handle, [this._impl])
+      : super.fromHandle(handle);
+
+  PathServiceStub.unbound() : super.unbound();
+
+  static PathServiceStub newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For PathServiceStub"));
+    return new PathServiceStub.fromEndpoint(endpoint);
+  }
+
+  static const String name = PathServiceName;
+
+
+  PathServiceGetAppDataDirResponseParams _PathServiceGetAppDataDirResponseParamsFactory(String path) {
+    var mojo_factory_result = new PathServiceGetAppDataDirResponseParams();
+    mojo_factory_result.path = path;
+    return mojo_factory_result;
+  }
+  PathServiceGetFilesDirResponseParams _PathServiceGetFilesDirResponseParamsFactory(String path) {
+    var mojo_factory_result = new PathServiceGetFilesDirResponseParams();
+    mojo_factory_result.path = path;
+    return mojo_factory_result;
+  }
+  PathServiceGetCacheDirResponseParams _PathServiceGetCacheDirResponseParamsFactory(String path) {
+    var mojo_factory_result = new PathServiceGetCacheDirResponseParams();
+    mojo_factory_result.path = path;
+    return mojo_factory_result;
+  }
+
+  dynamic handleMessage(bindings.ServiceMessage message) {
+    if (bindings.ControlMessageHandler.isControlMessage(message)) {
+      return bindings.ControlMessageHandler.handleMessage(this,
+                                                          0,
+                                                          message);
+    }
+    assert(_impl != null);
+    switch (message.header.type) {
+      case kPathService_getAppDataDir_name:
+        var params = PathServiceGetAppDataDirParams.deserialize(
+            message.payload);
+        var response = _impl.getAppDataDir(_PathServiceGetAppDataDirResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  kPathService_getAppDataDir_name,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              kPathService_getAppDataDir_name,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case kPathService_getFilesDir_name:
+        var params = PathServiceGetFilesDirParams.deserialize(
+            message.payload);
+        var response = _impl.getFilesDir(_PathServiceGetFilesDirResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  kPathService_getFilesDir_name,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              kPathService_getFilesDir_name,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case kPathService_getCacheDir_name:
+        var params = PathServiceGetCacheDirParams.deserialize(
+            message.payload);
+        var response = _impl.getCacheDir(_PathServiceGetCacheDirResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  kPathService_getCacheDir_name,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              kPathService_getCacheDir_name,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      default:
+        throw new bindings.MojoCodecError("Unexpected message name");
+        break;
+    }
+    return null;
+  }
+
+  PathService get impl => _impl;
+  set impl(PathService d) {
+    assert(_impl == null);
+    _impl = d;
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "PathServiceStub($superString)";
+  }
+
+  int get version => 0;
+}
+
+const int kUserFeedback_performHapticFeedback_name = 0;
+const int kUserFeedback_performAuralFeedback_name = 1;
+
+const String UserFeedbackName =
+      'activity::UserFeedback';
+
+abstract class UserFeedback {
+  void performHapticFeedback(HapticFeedbackType type);
+  void performAuralFeedback(AuralFeedbackType type);
+
+}
+
+
+class UserFeedbackProxyImpl extends bindings.Proxy {
+  UserFeedbackProxyImpl.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
+
+  UserFeedbackProxyImpl.fromHandle(core.MojoHandle handle) :
+      super.fromHandle(handle);
+
+  UserFeedbackProxyImpl.unbound() : super.unbound();
+
+  static UserFeedbackProxyImpl newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For UserFeedbackProxyImpl"));
+    return new UserFeedbackProxyImpl.fromEndpoint(endpoint);
+  }
+
+  String get name => UserFeedbackName;
+
+  void handleResponse(bindings.ServiceMessage message) {
+    switch (message.header.type) {
+      default:
+        proxyError("Unexpected message type: ${message.header.type}");
+        close(immediate: true);
+        break;
+    }
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "UserFeedbackProxyImpl($superString)";
+  }
+}
+
+
+class _UserFeedbackProxyCalls implements UserFeedback {
+  UserFeedbackProxyImpl _proxyImpl;
+
+  _UserFeedbackProxyCalls(this._proxyImpl);
+    void performHapticFeedback(HapticFeedbackType type) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new UserFeedbackPerformHapticFeedbackParams();
+      params.type = type;
+      _proxyImpl.sendMessage(params, kUserFeedback_performHapticFeedback_name);
+    }
+  
+    void performAuralFeedback(AuralFeedbackType type) {
+      if (!_proxyImpl.isBound) {
+        _proxyImpl.proxyError("The Proxy is closed.");
+        return;
+      }
+      var params = new UserFeedbackPerformAuralFeedbackParams();
+      params.type = type;
+      _proxyImpl.sendMessage(params, kUserFeedback_performAuralFeedback_name);
+    }
+  
+}
+
+
+class UserFeedbackProxy implements bindings.ProxyBase {
+  final bindings.Proxy impl;
+  UserFeedback ptr;
+  final String name = UserFeedbackName;
+
+  UserFeedbackProxy(UserFeedbackProxyImpl proxyImpl) :
+      impl = proxyImpl,
+      ptr = new _UserFeedbackProxyCalls(proxyImpl);
+
+  UserFeedbackProxy.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) :
+      impl = new UserFeedbackProxyImpl.fromEndpoint(endpoint) {
+    ptr = new _UserFeedbackProxyCalls(impl);
+  }
+
+  UserFeedbackProxy.fromHandle(core.MojoHandle handle) :
+      impl = new UserFeedbackProxyImpl.fromHandle(handle) {
+    ptr = new _UserFeedbackProxyCalls(impl);
+  }
+
+  UserFeedbackProxy.unbound() :
+      impl = new UserFeedbackProxyImpl.unbound() {
+    ptr = new _UserFeedbackProxyCalls(impl);
+  }
+
+  factory UserFeedbackProxy.connectToService(
+      bindings.ServiceConnector s, String url) {
+    UserFeedbackProxy p = new UserFeedbackProxy.unbound();
+    s.connectToService(url, p);
+    return p;
+  }
+
+  static UserFeedbackProxy newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For UserFeedbackProxy"));
+    return new UserFeedbackProxy.fromEndpoint(endpoint);
+  }
+
+  Future close({bool immediate: false}) => impl.close(immediate: immediate);
+
+  Future responseOrError(Future f) => impl.responseOrError(f);
+
+  Future get errorFuture => impl.errorFuture;
+
+  int get version => impl.version;
+
+  Future<int> queryVersion() => impl.queryVersion();
+
+  void requireVersion(int requiredVersion) {
+    impl.requireVersion(requiredVersion);
+  }
+
+  String toString() {
+    return "UserFeedbackProxy($impl)";
+  }
+}
+
+
+class UserFeedbackStub extends bindings.Stub {
+  UserFeedback _impl = null;
+
+  UserFeedbackStub.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint, [this._impl])
+      : super.fromEndpoint(endpoint);
+
+  UserFeedbackStub.fromHandle(core.MojoHandle handle, [this._impl])
+      : super.fromHandle(handle);
+
+  UserFeedbackStub.unbound() : super.unbound();
+
+  static UserFeedbackStub newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For UserFeedbackStub"));
+    return new UserFeedbackStub.fromEndpoint(endpoint);
+  }
+
+  static const String name = UserFeedbackName;
+
+
+
+  dynamic handleMessage(bindings.ServiceMessage message) {
+    if (bindings.ControlMessageHandler.isControlMessage(message)) {
+      return bindings.ControlMessageHandler.handleMessage(this,
+                                                          0,
+                                                          message);
+    }
+    assert(_impl != null);
+    switch (message.header.type) {
+      case kUserFeedback_performHapticFeedback_name:
+        var params = UserFeedbackPerformHapticFeedbackParams.deserialize(
+            message.payload);
+        _impl.performHapticFeedback(params.type);
+        break;
+      case kUserFeedback_performAuralFeedback_name:
+        var params = UserFeedbackPerformAuralFeedbackParams.deserialize(
+            message.payload);
+        _impl.performAuralFeedback(params.type);
+        break;
+      default:
+        throw new bindings.MojoCodecError("Unexpected message name");
+        break;
+    }
+    return null;
+  }
+
+  UserFeedback get impl => _impl;
+  set impl(UserFeedback d) {
+    assert(_impl == null);
+    _impl = d;
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "UserFeedbackStub($superString)";
+  }
+
+  int get version => 0;
+}
+
+
diff --git a/mojo/services/android/interfaces/BUILD.gn b/mojo/services/android/interfaces/BUILD.gn
new file mode 100644
index 0000000..ea84063
--- /dev/null
+++ b/mojo/services/android/interfaces/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/module_args/mojo.gni")
+import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni")
+
+mojom("interfaces") {
+  sources = [
+    "activity.mojom",
+  ]
+}
diff --git a/mojo/services/android/interfaces/activity.mojom b/mojo/services/android/interfaces/activity.mojom
new file mode 100644
index 0000000..370cfe0
--- /dev/null
+++ b/mojo/services/android/interfaces/activity.mojom
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been imported from
+// https://github.com/flutter/engine/blob/master/sky/services/activity/activity.mojom
+[DartPackage="mojo_services"]
+module activity;
+
+struct StringExtra {
+  string name;
+  string value;
+};
+
+struct ComponentName {
+  string package_name;
+  string class_name;
+};
+
+struct Intent {
+  string action;
+  string url;
+  uint32 flags;
+  ComponentName? component;
+  array<StringExtra>? string_extras;
+  string? type;
+};
+
+struct TaskDescription {
+  string? label;
+  uint32 primaryColor;
+};
+
+enum SystemUIVisibility {
+  STANDARD,
+  FULLSCREEN,
+  IMMERSIVE,
+};
+
+// See http://developer.android.com/intl/es/reference/android/R.attr.html#screenOrientation
+enum ScreenOrientation {
+  UNSPECIFIED,
+  LANDSCAPE,
+  PORTRAIT,
+  NOSENSOR,
+};
+
+// TODO(abarth): This interface seems very specific to Android. Do we want to
+//               have a higher-level abstraction here? Do we want a collection
+//               of services that only work on specific platforms? We need to
+//               figure out how to rationalize this interface across platforms.
+[ServiceName="activity::Activity"]
+interface Activity {
+  GetUserFeedback(UserFeedback& user_feedback);
+
+  StartActivity(Intent intent);
+  FinishCurrentActivity();
+  SetTaskDescription(TaskDescription description);
+  SetSystemUIVisibility(SystemUIVisibility visibility);
+  SetRequestedOrientation(ScreenOrientation orientation);
+};
+
+[ServiceName="activity::PathService"]
+interface PathService {
+  // Where the application files are.
+  GetAppDataDir() => (string path);
+
+  // Where to store long-term files.
+  GetFilesDir() => (string path);
+
+  // Where to store short-term files.
+  GetCacheDir() => (string path);
+};
+
+enum HapticFeedbackType {
+  LONG_PRESS,
+  VIRTUAL_KEY,
+  KEYBOARD_TAP,
+  CLOCK_TICK,
+};
+
+enum AuralFeedbackType {
+  CLICK,
+  NAVIGATION_LEFT,
+  NAVIGATION_UP,
+  NAVIGATION_RIGHT,
+  NAVIGATION_DOWN,
+};
+
+interface UserFeedback {
+  PerformHapticFeedback(HapticFeedbackType type);
+  PerformAuralFeedback(AuralFeedbackType type);
+};
diff --git a/mojo/services/mojo_services.gni b/mojo/services/mojo_services.gni
index 3b6d8f9..2ec90e7 100644
--- a/mojo/services/mojo_services.gni
+++ b/mojo/services/mojo_services.gni
@@ -8,6 +8,7 @@
 # //mojo/services/X/public/interfaces to this list.
 
 mojo_services = [
+  "//mojo/services/android/interfaces",
   "//mojo/services/asset_bundle/interfaces",
   "//mojo/services/authenticating_url_loader_interceptor/interfaces",
   "//mojo/services/authentication/interfaces",
diff --git a/services/android/BUILD.gn b/services/android/BUILD.gn
new file mode 100644
index 0000000..453db8a
--- /dev/null
+++ b/services/android/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/config.gni")
+import("//build/config/android/rules.gni")
+
+# Application regrouping all android specific services.
+android_library("android") {
+  java_files = [ "src/org/chromium/mojo/android/ActivityImpl.java" ]
+
+  deps = [
+    "//mojo/public/java:bindings",
+    "//mojo/public/java:system",
+    "//mojo/services/android/interfaces:interfaces_java",
+  ]
+}
diff --git a/services/android/src/org/chromium/mojo/android/ActivityImpl.java b/services/android/src/org/chromium/mojo/android/ActivityImpl.java
new file mode 100644
index 0000000..961c7dd
--- /dev/null
+++ b/services/android/src/org/chromium/mojo/android/ActivityImpl.java
@@ -0,0 +1,283 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.mojo.android;
+
+import android.app.Application.ActivityLifecycleCallbacks;
+import android.content.ActivityNotFoundException;
+import android.content.pm.ActivityInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.SoundEffectConstants;
+import android.view.View;
+
+import org.chromium.mojo.bindings.InterfaceRequest;
+import org.chromium.mojo.system.MojoException;
+import org.chromium.mojom.activity.Activity;
+import org.chromium.mojom.activity.AuralFeedbackType;
+import org.chromium.mojom.activity.ComponentName;
+import org.chromium.mojom.activity.HapticFeedbackType;
+import org.chromium.mojom.activity.Intent;
+import org.chromium.mojom.activity.ScreenOrientation;
+import org.chromium.mojom.activity.StringExtra;
+import org.chromium.mojom.activity.SystemUiVisibility;
+import org.chromium.mojom.activity.TaskDescription;
+import org.chromium.mojom.activity.UserFeedback;
+
+/**
+ * Android implementation of Activity.
+ *
+ * This is a port of
+ * https://github.com/flutter/engine/blob/master/sky/services/activity/src/org/domokit/activity/ActivityImpl.java
+ */
+public class ActivityImpl implements Activity {
+    private static final String TAG = "AndroidImpl";
+
+    private final android.app.Activity mActivity;
+    private int mVisibility = SystemUiVisibility.STANDARD;
+
+    private static class UserFeedBackImpl implements UserFeedback {
+        private final View mView;
+
+        public UserFeedBackImpl(View view) {
+            mView = view;
+        }
+
+        @Override
+        public void close() {}
+
+        @Override
+        public void onConnectionError(MojoException e) {}
+
+        /**
+         * @see UserFeedback#performHapticFeedback(int)
+         */
+        @Override
+        public void performHapticFeedback(int type) {
+            int androidType = 0;
+            switch (type) {
+                case HapticFeedbackType.LONG_PRESS:
+                    androidType = HapticFeedbackConstants.LONG_PRESS;
+                    break;
+                case HapticFeedbackType.VIRTUAL_KEY:
+                    androidType = HapticFeedbackConstants.VIRTUAL_KEY;
+                    break;
+                case HapticFeedbackType.KEYBOARD_TAP:
+                    androidType = HapticFeedbackConstants.KEYBOARD_TAP;
+                    break;
+                case HapticFeedbackType.CLOCK_TICK:
+                    androidType = HapticFeedbackConstants.CLOCK_TICK;
+                    break;
+                default:
+                    Log.e(TAG, "Unknown HapticFeedbackType " + type);
+                    return;
+            }
+            mView.performHapticFeedback(
+                    androidType, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+        }
+
+        /**
+         * @see UserFeedback#performAuralFeedback(int)
+         */
+        @Override
+        public void performAuralFeedback(int type) {
+            int androidType = 0;
+            switch (type) {
+                case AuralFeedbackType.CLICK:
+                    androidType = SoundEffectConstants.CLICK;
+                    break;
+                case AuralFeedbackType.NAVIGATION_LEFT:
+                    androidType = SoundEffectConstants.NAVIGATION_LEFT;
+                    break;
+                case AuralFeedbackType.NAVIGATION_UP:
+                    androidType = SoundEffectConstants.NAVIGATION_UP;
+                    break;
+                case AuralFeedbackType.NAVIGATION_RIGHT:
+                    androidType = SoundEffectConstants.NAVIGATION_RIGHT;
+                    break;
+                case AuralFeedbackType.NAVIGATION_DOWN:
+                    androidType = SoundEffectConstants.NAVIGATION_DOWN;
+                    break;
+                default:
+                    Log.e(TAG, "Unknown AuralFeedbackType " + type);
+                    return;
+            }
+            mView.playSoundEffect(androidType);
+        }
+    }
+
+    /**
+     * Constructor.
+     */
+    public ActivityImpl(android.app.Activity activity) {
+        mActivity = activity;
+        activity.getApplication().registerActivityLifecycleCallbacks(
+                new ActivityLifecycleCallbacks() {
+
+                    @Override
+                    public void onActivityStopped(android.app.Activity activity) {}
+
+                    @Override
+                    public void onActivityStarted(android.app.Activity activity) {}
+
+                    @Override
+                    public void onActivitySaveInstanceState(
+                            android.app.Activity activity, Bundle bundle) {}
+
+                    @Override
+                    public void onActivityResumed(android.app.Activity activity) {
+                        if (activity == mActivity) {
+                            updateSystemUiVisibility();
+                        }
+                    }
+
+                    @Override
+                    public void onActivityPaused(android.app.Activity activity) {}
+
+                    @Override
+                    public void onActivityDestroyed(android.app.Activity activity) {}
+
+                    @Override
+                    public void onActivityCreated(android.app.Activity activity, Bundle bundle) {}
+                });
+    }
+
+    @Override
+    public void close() {}
+
+    @Override
+    public void onConnectionError(MojoException e) {}
+
+    /**
+     * @see Activity#getUserFeedback(InterfaceRequest)
+     */
+    @Override
+    public void getUserFeedback(final InterfaceRequest<UserFeedback> userFeedback) {
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                UserFeedback.MANAGER.bind(
+                        new UserFeedBackImpl(mActivity.getWindow().getDecorView()), userFeedback);
+            }
+        });
+    }
+
+    /**
+     * @see Activity#startActivity(Intent)
+     */
+    @Override
+    public void startActivity(Intent intent) {
+        final android.content.Intent androidIntent =
+                new android.content.Intent(intent.action, Uri.parse(intent.url));
+
+        if (intent.component != null) {
+            ComponentName component = intent.component;
+            android.content.ComponentName androidComponent =
+                    new android.content.ComponentName(component.packageName, component.className);
+            androidIntent.setComponent(androidComponent);
+        }
+
+        if (intent.stringExtras != null) {
+            for (StringExtra extra : intent.stringExtras) {
+                androidIntent.putExtra(extra.name, extra.value);
+            }
+        }
+
+        if (intent.flags != 0) {
+            androidIntent.setFlags(intent.flags);
+        }
+
+        if (intent.type != null) {
+            androidIntent.setType(intent.type);
+        }
+
+        try {
+            mActivity.startActivity(androidIntent);
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "Unable to startActivity", e);
+        }
+    }
+
+    /**
+     * @see Activity#finishCurrentActivity()
+     */
+    @Override
+    public void finishCurrentActivity() {
+        Log.e(TAG, "finishCurrentActivity() is not implemented.");
+    }
+
+    /**
+     * @see Activity#setTaskDescription(TaskDescription)
+     */
+    @Override
+    public void setTaskDescription(TaskDescription description) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            return;
+        }
+        mActivity.setTaskDescription(new android.app.ActivityManager.TaskDescription(
+                description.label, null, description.primaryColor));
+    }
+
+    /**
+     * @see Activity#setSystemUiVisibility(int)
+     */
+    @Override
+    public void setSystemUiVisibility(int visibility) {
+        mVisibility = visibility;
+        updateSystemUiVisibility();
+    }
+
+    /**
+     * @see Activity#setRequestedOrientation(int)
+     */
+    @Override
+    public void setRequestedOrientation(int orientation) {
+        int androidOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+        switch (orientation) {
+            case ScreenOrientation.UNSPECIFIED:
+                androidOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+                break;
+            case ScreenOrientation.LANDSCAPE:
+                androidOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+                break;
+            case ScreenOrientation.PORTRAIT:
+                androidOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+                break;
+            case ScreenOrientation.NOSENSOR:
+                androidOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+                break;
+            default:
+                Log.w(TAG,
+                        "Unable to set the requested orientation. Unknown value: " + orientation);
+                break;
+        }
+
+        mActivity.setRequestedOrientation(androidOrientation);
+    }
+
+    private void updateSystemUiVisibility() {
+        int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
+        if (mVisibility >= SystemUiVisibility.FULLSCREEN) {
+            flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
+        }
+
+        if (mVisibility >= SystemUiVisibility.IMMERSIVE) {
+            flags |= View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+        }
+
+        final int finalFlags = flags;
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.getWindow().getDecorView().setSystemUiVisibility(finalFlags);
+            }
+        });
+    }
+}
diff --git a/shell/BUILD.gn b/shell/BUILD.gn
index 5a3a360..54d013f 100644
--- a/shell/BUILD.gn
+++ b/shell/BUILD.gn
@@ -336,6 +336,7 @@
 
   android_library("java") {
     java_files = [
+      "android/apk/src/org/chromium/mojo/shell/AndroidFactory.java",
       "android/apk/src/org/chromium/mojo/shell/AndroidHandler.java",
       "android/apk/src/org/chromium/mojo/shell/BaseActivity.java",
       "android/apk/src/org/chromium/mojo/shell/FileHelper.java",
@@ -368,10 +369,12 @@
       "//mojo/public/java:application",
       "//mojo/public/java:bindings",
       "//mojo/public/java:system",
+      "//mojo/services/android/interfaces:interfaces_java",
       "//mojo/services/input/interfaces:interfaces_java",
       "//mojo/services/keyboard/interfaces:interfaces_java",
       "//mojo/services/nfc/interfaces:interfaces_java",
       "//mojo/services/vsync/interfaces:interfaces_java",
+      "//services/android",
       "//services/authentication",
       "//services/input",
       "//services/intent_receiver:bindings_java",
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/AndroidFactory.java b/shell/android/apk/src/org/chromium/mojo/shell/AndroidFactory.java
new file mode 100644
index 0000000..f3a34c0
--- /dev/null
+++ b/shell/android/apk/src/org/chromium/mojo/shell/AndroidFactory.java
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.mojo.shell;
+
+import org.chromium.mojo.android.ActivityImpl;
+import org.chromium.mojo.application.ServiceFactoryBinder;
+import org.chromium.mojo.bindings.InterfaceRequest;
+import org.chromium.mojom.activity.Activity;
+
+/**
+ * A ServiceFactoryBinder for the android service.
+ */
+final class AndroidFactory implements ServiceFactoryBinder<Activity> {
+    @Override
+    public void bind(final InterfaceRequest<Activity> request) {
+        if (ViewportActivity.getCurrent() == null) {
+            request.close();
+            return;
+        }
+        Activity.MANAGER.bind(new ActivityImpl(ViewportActivity.getCurrent()), request);
+    }
+
+    @Override
+    public String getInterfaceName() {
+        return Activity.MANAGER.getName();
+    }
+}
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/JavaApplicationRegistry.java b/shell/android/apk/src/org/chromium/mojo/shell/JavaApplicationRegistry.java
index 49b5ff3..5a7ef8e 100644
--- a/shell/android/apk/src/org/chromium/mojo/shell/JavaApplicationRegistry.java
+++ b/shell/android/apk/src/org/chromium/mojo/shell/JavaApplicationRegistry.java
@@ -85,24 +85,26 @@
     private static JavaApplicationRegistry create() {
         JavaApplicationRegistry registry = new JavaApplicationRegistry();
         // Register services.
+        registry.registerApplicationDelegate("mojo:android",
+                new ServiceProviderFactoryApplicationDelegate(new AndroidFactory()));
         registry.registerApplicationDelegate("mojo:authentication",
                 new AuthenticationApplicationDelegate(ApplicationStatus.getApplicationContext(),
                                                      CoreImpl.getInstance()));
-        registry.registerApplicationDelegate(
-                "mojo:input", new ServiceProviderFactoryApplicationDelegate(new InputFactory()));
         registry.registerApplicationDelegate("mojo:keyboard",
                 new ServiceProviderFactoryApplicationDelegate(new KeyboardFactory()));
         registry.registerApplicationDelegate(
+                "mojo:input", new ServiceProviderFactoryApplicationDelegate(new InputFactory()));
+        registry.registerApplicationDelegate(
                 "mojo:intent_receiver", new ServiceProviderFactoryApplicationDelegate(
                                                 IntentReceiverRegistry.getInstance()));
         registry.registerApplicationDelegate("mojo:location_service",
                 new LocationApplicationDelegate(ApplicationStatus.getApplicationContext(),
                                                      CoreImpl.getInstance()));
 
-        registry.registerApplicationDelegate("mojo:nfc", new NfcApplicationDelegate());
-        registry.registerApplicationDelegate("mojo:sharing", new SharingApplicationDelegate());
         registry.registerApplicationDelegate(
                 "mojo:native_viewport_support", new NativeViewportSupportApplicationDelegate());
+        registry.registerApplicationDelegate("mojo:nfc", new NfcApplicationDelegate());
+        registry.registerApplicationDelegate("mojo:sharing", new SharingApplicationDelegate());
         registry.registerApplicationDelegate(
                 "mojo:vsync", new ServiceProviderFactoryApplicationDelegate(
                                       new VsyncFactory(registry.mHandlerThread.getLooper())));
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/ViewportActivity.java b/shell/android/apk/src/org/chromium/mojo/shell/ViewportActivity.java
index 29b69a7..b087cd0 100644
--- a/shell/android/apk/src/org/chromium/mojo/shell/ViewportActivity.java
+++ b/shell/android/apk/src/org/chromium/mojo/shell/ViewportActivity.java
@@ -19,6 +19,12 @@
  * Activity for displaying on the screen from the NativeViewportService.
  */
 public class ViewportActivity extends Activity {
+    private static Activity sCurrentActivity = null;
+
+    public static Activity getCurrent() {
+        return sCurrentActivity;
+    }
+
     /**
      * @see Activity#onKeyDown(int, KeyEvent)
      */
@@ -57,4 +63,22 @@
         super.onNewIntent(intent);
         new RuntimeException("This activity instance should only ever receive one intent.");
     }
+
+    /**
+     * @see Activity#onPause()
+     */
+    @Override
+    protected void onPause() {
+        if (sCurrentActivity == this) sCurrentActivity = null;
+        super.onPause();
+    }
+
+    /**
+     * @see Activity#onResume()
+     */
+    @Override
+    protected void onResume() {
+        super.onResume();
+        sCurrentActivity = this;
+    }
 }