Update from https://crrev.com/327068

This rolls in //base, //build and //sandbox/linux and updates other
things to match, in particular:

*) Update build_v8.patch
*) Add junit, mockito and roboelectric to DEPS for android test rules
*) Update DEPS for grit
*) Fix up various GN files for os->target_os rename
*) Fix up a few places that were using //base/float_util to use std::isnan
*) Fix up a few places using ApiCompatibilityUtil to use Android SDK directly

as well as a few miscellaneous fixes.

Many portions based on ncbray's work in
https://codereview.chromium.org/1108173002/

R=ncbray@chromium.org
TBR=ncbray@chromium.org

Review URL: https://codereview.chromium.org/1124763003
diff --git a/build/PRESUBMIT.py b/build/PRESUBMIT.py
index 3c70193..fca962f 100644
--- a/build/PRESUBMIT.py
+++ b/build/PRESUBMIT.py
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-WHITELIST = [ r'.+_test.py$' ]
-
 
 def _RunTests(input_api, output_api):
   return (input_api.canned_checks.RunUnitTestsInDirectory(
diff --git a/build/all.gyp b/build/all.gyp
index 2813ca2..255a35c 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -74,12 +74,6 @@
             '../content/content_shell_and_tests.gyp:content_shell_apk',
             '<@(android_app_targets)',
             'android_builder_tests',
-            '../android_webview/android_webview.gyp:android_webview_apk',
-            '../android_webview/android_webview.gyp:system_webview_apk',
-            '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk',
-            '../chrome/chrome.gyp:chrome_shell_apk',
-            '../chrome/chrome.gyp:chrome_sync_shell_apk',
-            '../remoting/remoting.gyp:remoting_apk',
             '../tools/telemetry/telemetry.gyp:*#host',
             # TODO(nyquist) This should instead by a target for sync when all of
             # the sync-related code for Android has been upstreamed.
@@ -87,6 +81,17 @@
             '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib',
           ],
           'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:android_webview_apk',
+                '../android_webview/android_webview.gyp:system_webview_apk',
+                '../android_webview/android_webview_shell.gyp:android_webview_shell_apk',
+                '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk',
+                '../chrome/chrome.gyp:chrome_shell_apk',
+                '../chrome/chrome.gyp:chrome_sync_shell_apk',
+                '../remoting/remoting.gyp:remoting_apk',
+              ],
+            }],
             ['target_arch == "arm" or target_arch == "arm64"', {
               'dependencies': [
                 # The relocation packer only works on ARM or ARM64.
@@ -101,16 +106,16 @@
             '../sync/sync.gyp:*',
           ],
         }],
-        ['OS!="ios" and OS!="android"', {
+        ['OS!="ios" and OS!="android" and chromecast==0', {
           'dependencies': [
             '../third_party/re2/re2.gyp:re2',
             '../chrome/chrome.gyp:*',
             '../chrome/tools/profile_reset/jtl_compiler.gyp:*',
             '../cc/blink/cc_blink_tests.gyp:*',
             '../cc/cc_tests.gyp:*',
-            '../device/bluetooth/bluetooth.gyp:*',
-            '../device/device_tests.gyp:*',
             '../device/usb/usb.gyp:*',
+            '../extensions/extensions.gyp:*',
+            '../extensions/extensions_tests.gyp:*',
             '../gin/gin.gyp:*',
             '../gpu/gpu.gyp:*',
             '../gpu/tools/tools.gyp:*',
@@ -150,6 +155,12 @@
             '<(libjpeg_gyp_path):*',
           ],
         }],
+        ['OS!="ios"', {
+          'dependencies': [
+            '../device/bluetooth/bluetooth.gyp:*',
+            '../device/device_tests.gyp:*',
+          ],
+        }],
         ['use_openssl==0 and (OS=="mac" or OS=="ios" or OS=="win")', {
           'dependencies': [
             '../third_party/nss/nss.gyp:*',
@@ -170,7 +181,6 @@
         ['OS=="linux"', {
           'dependencies': [
             '../courgette/courgette.gyp:*',
-            '../dbus/dbus.gyp:*',
             '../sandbox/sandbox.gyp:*',
           ],
           'conditions': [
@@ -184,6 +194,11 @@
                 '../tools/ipc_fuzzer/ipc_fuzzer.gyp:*',
               ],
             }],
+            ['use_dbus==1', {
+              'dependencies': [
+                '../dbus/dbus.gyp:*',
+              ],
+            }],
           ],
         }],
         ['chromecast==1', {
@@ -263,7 +278,7 @@
             '../google_apis/gcm/gcm.gyp:*',
           ],
         }],
-        ['chromeos==1 or OS=="linux" or OS=="win" or OS=="mac"', {
+        ['(chromeos==1 or OS=="linux" or OS=="win" or OS=="mac") and chromecast==0', {
           'dependencies': [
             '../extensions/shell/app_shell.gyp:*',
           ],
@@ -315,19 +330,11 @@
           'dependencies': [
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
             '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:chromedriver_tests',
-            '../chrome/chrome.gyp:chromedriver_unittests',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:sync_integration_tests',
-            '../chrome/chrome.gyp:unit_tests',
             '../cloud_print/cloud_print.gyp:cloud_print_unittests',
             '../content/content_shell_and_tests.gyp:content_browsertests',
             '../content/content_shell_and_tests.gyp:content_shell',
             '../content/content_shell_and_tests.gyp:content_unittests',
             '../device/device_tests.gyp:device_unittests',
-            '../extensions/extensions_tests.gyp:extensions_browsertests',
-            '../extensions/extensions_tests.gyp:extensions_unittests',
             '../gin/gin.gyp:gin_unittests',
             '../google_apis/google_apis.gyp:google_apis_unittests',
             '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
@@ -348,6 +355,18 @@
             '../tools/telemetry/telemetry.gyp:*',
           ],
         }],
+        ['OS!="ios" and OS!="android" and chromecast==0', {
+          'dependencies': [
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:chromedriver_tests',
+            '../chrome/chrome.gyp:chromedriver_unittests',
+            '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../extensions/extensions_tests.gyp:extensions_browsertests',
+            '../extensions/extensions_tests.gyp:extensions_unittests',
+          ],
+        }],
         ['OS=="win"', {
           'dependencies': [
             '../chrome/chrome.gyp:app_installer',
@@ -406,10 +425,14 @@
         }],
         ['OS=="linux"', {
           'dependencies': [
-            '../dbus/dbus.gyp:dbus_unittests',
             '../sandbox/sandbox.gyp:sandbox_linux_unittests',
           ],
         }],
+        ['OS=="linux" and use_dbus==1', {
+          'dependencies': [
+            '../dbus/dbus.gyp:dbus_unittests',
+          ],
+        }],
         ['OS=="mac"', {
           'dependencies': [
             '../ui/app_list/app_list.gyp:app_list_unittests',
@@ -436,6 +459,10 @@
             '../ui/app_list/app_list.gyp:app_list_unittests',
             '../ui/aura/aura.gyp:aura_unittests',
             '../ui/compositor/compositor.gyp:compositor_unittests',
+          ],
+        }],
+        ['use_aura==1 and chromecast==0', {
+          'dependencies': [
             '../ui/keyboard/keyboard.gyp:keyboard_unittests',
             '../ui/views/views.gyp:views_unittests',
           ],
@@ -468,7 +495,7 @@
   ],
   'conditions': [
     # TODO(GYP): make gn_migration.gypi work unconditionally.
-    ['OS=="linux" and target_arch=="x64" and chromeos==0 and chromecast==0 and disable_nacl==0', {
+    ['OS=="mac" or OS=="win" or (OS=="linux" and target_arch=="x64" and chromecast==0)', {
       'includes': [
         'gn_migration.gypi',
       ],
@@ -512,14 +539,14 @@
             }],
             ['OS=="linux"', {
               'dependencies': [
-                '../breakpad/breakpad.gyp:dump_syms',
+                '../breakpad/breakpad.gyp:dump_syms#host',
               ],
             }],
           ],
         }, # target_name: blink_tests
       ],
     }], # OS!=ios
-    ['OS!="ios" and OS!="android"', {
+    ['OS!="ios" and OS!="android" and chromecast==0', {
       'targets': [
         {
           'target_name': 'chromium_builder_nacl_win_integration',
@@ -557,6 +584,7 @@
             ['OS=="win"', {
               'dependencies': [
                 '../chrome/chrome.gyp:crash_service',
+                '../gpu/gpu.gyp:angle_perftests',
               ],
             }],
             ['OS=="win" and target_arch=="ia32"', {
@@ -759,7 +787,6 @@
           'target_name': 'android_builder_tests',
           'type': 'none',
           'dependencies': [
-            '../android_webview/android_webview.gyp:android_webview_unittests',
             '../base/android/jni_generator/jni_generator.gyp:jni_generator_tests',
             '../base/base.gyp:base_unittests',
             '../breakpad/breakpad.gyp:breakpad_unittests_deps',
@@ -774,10 +801,10 @@
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
             '../cc/cc_tests.gyp:cc_perftests_apk',
             '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:unit_tests',
             '../components/components_tests.gyp:components_unittests',
             '../content/content_shell_and_tests.gyp:content_browsertests',
             '../content/content_shell_and_tests.gyp:content_gl_tests',
+            '../content/content_shell_and_tests.gyp:content_junit_tests',
             '../content/content_shell_and_tests.gyp:chromium_linker_test_apk',
             '../content/content_shell_and_tests.gyp:content_shell_test_apk',
             '../content/content_shell_and_tests.gyp:content_unittests',
@@ -803,16 +830,10 @@
             '../ui/events/events.gyp:events_unittests',
             '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
             # Unit test bundles packaged as an apk.
-            '../android_webview/android_webview.gyp:android_webview_test_apk',
-            '../android_webview/android_webview.gyp:android_webview_unittests_apk',
             '../base/base.gyp:base_unittests_apk',
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests_apk',
             '../cc/cc_tests.gyp:cc_unittests_apk',
-            '../chrome/chrome.gyp:chrome_shell_test_apk',
-            '../chrome/chrome.gyp:chrome_sync_shell_test_apk',
-            '../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
-            '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
-            '../chrome/chrome.gyp:unit_tests_apk',
+            '../components/components_tests.gyp:components_browsertests_apk',
             '../components/components_tests.gyp:components_unittests_apk',
             '../content/content_shell_and_tests.gyp:content_browsertests_apk',
             '../content/content_shell_and_tests.gyp:content_gl_tests_apk',
@@ -835,6 +856,21 @@
             '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_apk',
           ],
           'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:android_webview_unittests',
+                '../chrome/chrome.gyp:unit_tests',
+                # Unit test bundles packaged as an apk.
+                '../android_webview/android_webview.gyp:android_webview_test_apk',
+                '../android_webview/android_webview.gyp:android_webview_unittests_apk',
+                '../chrome/chrome.gyp:chrome_junit_tests',
+                '../chrome/chrome.gyp:chrome_shell_test_apk',
+                '../chrome/chrome.gyp:chrome_sync_shell_test_apk',
+                '../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
+                '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
+                '../chrome/chrome.gyp:unit_tests_apk',
+              ],
+            }],
             ['enable_webrtc==1 and "<(libpeer_target_type)"=="static_library"', {
               'dependencies': [
                 '../components/devtools_bridge.gyp:devtools_bridge_tests_apk',
@@ -1160,14 +1196,10 @@
         ['branding=="Chrome"', {
           'targets': [
             {
-              'target_name': 'chrome_official_builder',
+              'target_name': 'chrome_official_builder_no_unittests',
               'type': 'none',
               'dependencies': [
-                '../base/base.gyp:base_unittests',
                 '../chrome/chrome.gyp:app_installer',
-                '../chrome/chrome.gyp:app_installer_unittests',
-                '../chrome/chrome.gyp:browser_tests',
-                '../chrome/chrome.gyp:sync_integration_tests',
                 '../chrome/chrome.gyp:crash_service',
                 '../chrome/chrome.gyp:gcapi_dll',
                 '../chrome/chrome.gyp:pack_policy_templates',
@@ -1175,19 +1207,8 @@
                 '../cloud_print/cloud_print.gyp:cloud_print',
                 '../courgette/courgette.gyp:courgette',
                 '../courgette/courgette.gyp:courgette64',
-                '../ipc/ipc.gyp:ipc_tests',
-                '../media/media.gyp:media_unittests',
-                '../net/net.gyp:net_unittests_run',
-                '../printing/printing.gyp:printing_unittests',
                 '../remoting/remoting.gyp:remoting_webapp',
-                '../sql/sql.gyp:sql_unittests',
-                '../sync/sync.gyp:sync_unit_tests',
                 '../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
-                '../ui/base/ui_base_tests.gyp:ui_base_unittests',
-                '../ui/gfx/gfx_tests.gyp:gfx_unittests',
-                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
-                '../ui/views/views.gyp:views_unittests',
-                '../url/url.gyp:url_unittests',
               ],
               'conditions': [
                 ['target_arch=="ia32"', {
@@ -1202,6 +1223,27 @@
                   ],
                 }], # component != "shared_library"
               ]
+            }, {
+              'target_name': 'chrome_official_builder',
+              'type': 'none',
+              'dependencies': [
+	        'chrome_official_builder_no_unittests',
+                '../base/base.gyp:base_unittests',
+		'../chrome/chrome.gyp:app_installer_unittests',
+                '../chrome/chrome.gyp:browser_tests',
+                '../chrome/chrome.gyp:sync_integration_tests',
+                '../ipc/ipc.gyp:ipc_tests',
+                '../media/media.gyp:media_unittests',
+                '../net/net.gyp:net_unittests_run',
+                '../printing/printing.gyp:printing_unittests',
+                '../sql/sql.gyp:sql_unittests',
+                '../sync/sync.gyp:sync_unit_tests',
+                '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+                '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+                '../ui/views/views.gyp:views_unittests',
+                '../url/url.gyp:url_unittests',
+              ],
             },
           ], # targets
         }], # branding=="Chrome"
@@ -1215,10 +1257,6 @@
           'dependencies': [
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
             '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:chrome',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:unit_tests',
             '../components/components_tests.gyp:components_unittests',
             '../content/content_shell_and_tests.gyp:content_browsertests',
             '../content/content_shell_and_tests.gyp:content_unittests',
@@ -1236,12 +1274,8 @@
             '../ui/events/events.gyp:*',
             '../ui/gfx/gfx_tests.gyp:gfx_unittests',
             '../ui/keyboard/keyboard.gyp:*',
-            '../ui/message_center/message_center.gyp:*',
             '../ui/snapshot/snapshot.gyp:snapshot_unittests',
             '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
-            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
-            '../ui/views/views.gyp:views',
-            '../ui/views/views.gyp:views_unittests',
             '../ui/wm/wm.gyp:*',
             'blink_tests',
           ],
@@ -1283,6 +1317,18 @@
                 '../ui/ozone/demo/ozone_demos.gyp:*',
               ],
             }],
+            ['chromecast==0', {
+              'dependencies': [
+                '../chrome/chrome.gyp:browser_tests',
+                '../chrome/chrome.gyp:chrome',
+                '../chrome/chrome.gyp:interactive_ui_tests',
+                '../chrome/chrome.gyp:unit_tests',
+                '../ui/message_center/message_center.gyp:*',
+                '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
+                '../ui/views/views.gyp:views',
+                '../ui/views/views.gyp:views_unittests',
+              ],
+            }],
           ],
         },
       ],  # targets
@@ -1294,14 +1340,20 @@
           'type': 'none',
           'dependencies': [
             '../base/base.gyp:base_unittests_run',
-            '../chrome/chrome.gyp:browser_tests_run',
-            '../chrome/chrome.gyp:interactive_ui_tests_run',
-            '../chrome/chrome.gyp:sync_integration_tests_run',
-            '../chrome/chrome.gyp:unit_tests_run',
             '../content/content_shell_and_tests.gyp:content_browsertests_run',
             '../content/content_shell_and_tests.gyp:content_unittests_run',
             '../net/net.gyp:net_unittests_run',
           ],
+          'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../chrome/chrome.gyp:browser_tests_run',
+                '../chrome/chrome.gyp:interactive_ui_tests_run',
+                '../chrome/chrome.gyp:sync_integration_tests_run',
+                '../chrome/chrome.gyp:unit_tests_run',
+              ],
+            }],
+          ],
         }, # target_name: chromium_swarm_tests
       ],
     }],
diff --git a/build/android/AndroidManifest.xml b/build/android/AndroidManifest.xml
index 25e1db0..f27872e 100644
--- a/build/android/AndroidManifest.xml
+++ b/build/android/AndroidManifest.xml
@@ -15,6 +15,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="dummy.package">
 
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
 
 </manifest>
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index d1daaf2..92095be 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -8,25 +8,6 @@
 details on the presubmit API built into depot_tools.
 """
 
-_DELETIONS_ONLY_FILES = (
-    'build/android/findbugs_filter/findbugs_known_bugs.txt',
-)
-
-
-def _CheckDeletionsOnlyFiles(input_api, output_api):
-  """Check that a certain listed files only have deletions.
-  """
-  warnings = []
-  for f in input_api.AffectedFiles():
-    if f.LocalPath() in _DELETIONS_ONLY_FILES:
-      if f.ChangedContents():
-        warnings.append(f.LocalPath())
-  results = []
-  if warnings:
-    results.append(output_api.PresubmitPromptWarning(
-        'Following files should only contain deletions.', warnings))
-  return results
-
 
 def CommonChecks(input_api, output_api):
   output = []
@@ -61,6 +42,7 @@
       input_api,
       output_api,
       unit_tests=[
+          J('pylib', 'device', 'battery_utils_test.py'),
           J('pylib', 'device', 'device_utils_test.py'),
           J('pylib', 'device', 'logcat_monitor_test.py'),
           J('pylib', 'gtest', 'gtest_test_instance_test.py'),
@@ -70,8 +52,6 @@
           J('pylib', 'utils', 'md5sum_test.py'),
       ],
       env=pylib_test_env))
-  # TODO(jbudorick): Reenable this check once upstreaming is finished.
-  # output.extend(_CheckDeletionsOnlyFiles(input_api, output_api))
   return output
 
 
diff --git a/build/android/adb_install_apk.py b/build/android/adb_install_apk.py
index 5d0fd17..7bc634c 100755
--- a/build/android/adb_install_apk.py
+++ b/build/android/adb_install_apk.py
@@ -10,7 +10,6 @@
 import os
 import sys
 
-from pylib import android_commands
 from pylib import constants
 from pylib.device import device_utils
 
@@ -71,12 +70,13 @@
   constants.SetBuildType(options.build_type)
   ValidateInstallAPKOption(parser, options, args)
 
-  devices = android_commands.GetAttachedDevices()
+  devices = device_utils.DeviceUtils.HealthyDevices()
 
   if options.device:
-    if options.device not in devices:
+    device_serials = [d.adb.GetDeviceSerial() for d in devices]
+    if options.device not in device_serials:
       raise Exception('Error: %s not in attached devices %s' % (options.device,
-                      ','.join(devices)))
+                      ','.join(device_serials)))
     devices = [options.device]
 
   if not devices:
diff --git a/build/android/adb_reverse_forwarder.py b/build/android/adb_reverse_forwarder.py
index 1958fdd..6cae0cf 100755
--- a/build/android/adb_reverse_forwarder.py
+++ b/build/android/adb_reverse_forwarder.py
@@ -11,12 +11,14 @@
 to be built.
 """
 
+import logging
 import optparse
 import sys
 import time
 
-from pylib import android_commands
-from pylib import constants, forwarder
+from pylib import constants
+from pylib import forwarder
+from pylib.device import adb_wrapper
 from pylib.device import device_utils
 from pylib.utils import run_tests_helper
 
@@ -51,19 +53,19 @@
     parser.error('Bad port number')
     sys.exit(1)
 
-  devices = android_commands.GetAttachedDevices()
+  devices = device_utils.DeviceUtils.HealthyDevices()
 
   if options.device:
-    if options.device not in devices:
+    if options.device not in [str(d) for d in devices]:
       raise Exception('Error: %s not in attached devices %s' % (options.device,
                       ','.join(devices)))
     devices = [options.device]
   else:
     if not devices:
       raise Exception('Error: no connected devices')
-    print "No device specified. Defaulting to " + devices[0]
+    logging.info('No device specified. Defaulting to %s', devices[0])
 
-  device = device_utils.DeviceUtils(devices[0])
+  device = devices[0]
   constants.SetBuildType(options.build_type)
   try:
     forwarder.Forwarder.Map(port_pairs, device)
diff --git a/build/android/android_exports.gyp b/build/android/android_exports.gyp
deleted file mode 100644
index bf3424d..0000000
--- a/build/android/android_exports.gyp
+++ /dev/null
@@ -1,43 +0,0 @@
-# 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.
-
-# This target is only used when android_webview_build==1 - it implements a
-# whitelist for exported symbols to minimise the binary size and prevent us
-# accidentally exposing things we don't mean to expose.
-
-{
-  'variables': {
-    'android_linker_script%': '<(SHARED_INTERMEDIATE_DIR)/android_webview_export_whitelist.lst',
-  },
-  'targets': [
-    {
-      'target_name': 'android_exports',
-      'type': 'none',
-      'inputs': [
-        '<(DEPTH)/build/android/android_webview_export_whitelist.lst',
-      ],
-      'outputs': [
-        '<(android_linker_script)',
-      ],
-      'copies': [
-        {
-          'destination': '<(SHARED_INTERMEDIATE_DIR)',
-          'files': [
-            '<@(_inputs)',
-         ],
-        },
-      ],
-      'conditions': [
-        ['component=="static_library"', {
-          'link_settings': {
-            'ldflags': [
-              # Only export symbols that are specified in version script.
-              '-Wl,--version-script=<(android_linker_script)',
-            ],
-          },
-        }],
-      ],
-    },
-  ],
-}
diff --git a/build/android/android_webview_export_whitelist.lst b/build/android/android_webview_export_whitelist.lst
deleted file mode 100644
index 2a56a75..0000000
--- a/build/android/android_webview_export_whitelist.lst
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-# Exports specification for android_webview_build==1, which uses a whitelist to
-# enforce only specific symbols being exported.
-# Check ld version script manual:
-# https://sourceware.org/binutils/docs-2.24/ld/VERSION.html#VERSION
-
-{
-  global:
-    Java_*_native*;
-    JNI_OnLoad;
-    __gcov_*;
-  local: *;
-};
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index 8561c01..8690a60 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -30,9 +30,14 @@
 from pylib import android_commands
 from pylib import constants
 from pylib.cmd_helper import GetCmdOutput
+from pylib.device import battery_utils
 from pylib.device import device_blacklist
+from pylib.device import device_errors
 from pylib.device import device_list
 from pylib.device import device_utils
+from pylib.utils import run_tests_helper
+
+_RE_DEVICE_ID = re.compile('Device ID = (\d+)')
 
 def DeviceInfo(serial, options):
   """Gathers info on a device via various adb calls.
@@ -44,73 +49,62 @@
     Tuple of device type, build id, report as a string, error messages, and
     boolean indicating whether or not device can be used for testing.
   """
+  device = device_utils.DeviceUtils(serial)
+  battery = battery_utils.BatteryUtils(device)
 
-  device_adb = device_utils.DeviceUtils(serial)
-  device_type = device_adb.build_product
-  device_build = device_adb.build_id
-  device_build_type = device_adb.build_type
-  device_product_name = device_adb.product_name
-
-  try:
-    battery_info = device_adb.old_interface.GetBatteryInfo()
-  except Exception as e:
-    battery_info = {}
-    logging.error('Unable to obtain battery info for %s, %s', serial, e)
-
-  def _GetData(re_expression, line, lambda_function=lambda x: x):
-    if not line:
-      return 'Unknown'
-    found = re.findall(re_expression, line)
-    if found and len(found):
-      return lambda_function(found[0])
-    return 'Unknown'
-
-  battery_level = int(battery_info.get('level', 100))
-  imei_slice = _GetData(r'Device ID = (\d+)',
-                        device_adb.old_interface.GetSubscriberInfo(),
-                        lambda x: x[-6:])
-  json_data = {
-    'serial': serial,
-    'type': device_type,
-    'build': device_build,
-    'build_detail': device_adb.GetProp('ro.build.fingerprint'),
-    'battery': battery_info,
-    'imei_slice': imei_slice,
-    'wifi_ip': device_adb.GetProp('dhcp.wlan0.ipaddress'),
-  }
-  report = ['Device %s (%s)' % (serial, device_type),
-            '  Build: %s (%s)' %
-              (device_build, json_data['build_detail']),
-            '  Current Battery Service state: ',
-            '\n'.join(['    %s: %s' % (k, v)
-                       for k, v in battery_info.iteritems()]),
-            '  IMEI slice: %s' % imei_slice,
-            '  Wifi IP: %s' % json_data['wifi_ip'],
-            '']
-
+  battery_info = {}
+  battery_level = 100
   errors = []
   dev_good = True
-  if battery_level < 15:
-    errors += ['Device critically low in battery. Will add to blacklist.']
+  json_data = {
+    'serial': serial,
+    'type': device.build_product,
+    'build': device.build_id,
+    'build_detail': device.GetProp('ro.build.fingerprint'),
+    'battery': {},
+    'imei_slice': 'Unknown',
+    'wifi_ip': device.GetProp('dhcp.wlan0.ipaddress'),
+  }
+
+  try:
+    try:
+      battery_info = battery.GetBatteryInfo(timeout=5)
+      battery_level = int(battery_info.get('level', battery_level))
+      json_data['battery'] = battery_info
+    except device_errors.CommandFailedError:
+      logging.exception('Failed to get battery information for %s', serial)
+
+    try:
+      for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'],
+                                      check_return=True, timeout=5):
+        m = _RE_DEVICE_ID.match(l)
+        if m:
+          json_data['imei_slice'] = m.group(1)[-6:]
+    except device_errors.CommandFailedError:
+      logging.exception('Failed to get IMEI slice for %s', serial)
+
+    if battery_level < 15:
+      errors += ['Device critically low in battery.']
+      dev_good = False
+      if not battery.GetCharging():
+        battery.SetCharging(True)
+    if not options.no_provisioning_check:
+      setup_wizard_disabled = (
+          device.GetProp('ro.setupwizard.mode') == 'DISABLED')
+      if not setup_wizard_disabled and device.build_type != 'user':
+        errors += ['Setup wizard not disabled. Was it provisioned correctly?']
+    if (device.product_name == 'mantaray' and
+        battery_info.get('AC powered', None) != 'true'):
+      errors += ['Mantaray device not connected to AC power.']
+  except device_errors.CommandFailedError:
+    logging.exception('Failure while getting device status.')
     dev_good = False
-    if not device_adb.old_interface.IsDeviceCharging():
-      if device_adb.old_interface.CanControlUsbCharging():
-        device_adb.old_interface.EnableUsbCharging()
-      else:
-        logging.error('Device %s is not charging' % serial)
-  if not options.no_provisioning_check:
-    setup_wizard_disabled = (
-        device_adb.GetProp('ro.setupwizard.mode') == 'DISABLED')
-    if not setup_wizard_disabled and device_build_type != 'user':
-      errors += ['Setup wizard not disabled. Was it provisioned correctly?']
-  if (device_product_name == 'mantaray' and
-      battery_info.get('AC powered', None) != 'true'):
-    errors += ['Mantaray device not connected to AC power.']
+  except device_errors.CommandTimeoutError:
+    logging.exception('Timeout while getting device status.')
+    dev_good = False
 
-  full_report = '\n'.join(report)
-
-  return (device_type, device_build, battery_level, full_report, errors,
-    dev_good, json_data)
+  return (device.build_product, device.build_id, battery_level, errors,
+          dev_good, json_data)
 
 
 def CheckForMissingDevices(options, adb_online_devs):
@@ -122,11 +116,6 @@
     adb_online_devs: A list of serial numbers of the currently visible
                      and online attached devices.
   """
-  # TODO(navabi): remove this once the bug that causes different number
-  # of devices to be detected between calls is fixed.
-  logger = logging.getLogger()
-  logger.setLevel(logging.INFO)
-
   out_dir = os.path.abspath(options.out_dir)
 
   # last_devices denotes all known devices prior to this run
@@ -189,10 +178,10 @@
                                  os.environ.get('BUILDBOT_SLAVENAME'),
                                  os.environ.get('BUILDBOT_BUILDNUMBER')))))
     return ['Current online devices: %s' % adb_online_devs,
-            '%s are no longer visible. Were they removed?\n' % missing_devs,
-            'SHERIFF:\n',
-            '@@@STEP_LINK@Click here to file a bug@%s@@@\n' % crbug_link,
-            'Cache file: %s\n\n' % last_devices_path,
+            '%s are no longer visible. Were they removed?' % missing_devs,
+            'SHERIFF:',
+            '@@@STEP_LINK@Click here to file a bug@%s@@@' % crbug_link,
+            'Cache file: %s' % last_devices_path,
             'adb devices: %s' % GetCmdOutput(['adb', 'devices']),
             'adb devices(GetAttachedDevices): %s' % adb_online_devs]
   else:
@@ -201,8 +190,9 @@
       bb_annotations.PrintWarning()
       bb_annotations.PrintSummaryText(
           '%d new devices detected' % len(new_devs))
-      print ('New devices detected %s. And now back to your '
-             'regularly scheduled program.' % list(new_devs))
+      logging.info('New devices detected:')
+      for d in new_devs:
+        logging.info('  %s', d)
 
 
 def SendEmail(from_address, to_addresses, cc_addresses, subject, msg):
@@ -214,20 +204,20 @@
     server = smtplib.SMTP('localhost')
     server.sendmail(from_address, to_addresses, msg_body)
     server.quit()
-  except Exception as e:
-    print 'Failed to send alert email. Error: %s' % e
+  except Exception:
+    logging.exception('Failed to send alert email.')
 
 
 def RestartUsb():
   if not os.path.isfile('/usr/bin/restart_usb'):
-    print ('ERROR: Could not restart usb. /usr/bin/restart_usb not installed '
-           'on host (see BUG=305769).')
+    logging.error('Could not restart usb. ''/usr/bin/restart_usb not '
+                  'installed on host (see BUG=305769).')
     return False
 
   lsusb_proc = bb_utils.SpawnCmd(['lsusb'], stdout=subprocess.PIPE)
   lsusb_output, _ = lsusb_proc.communicate()
   if lsusb_proc.returncode:
-    print 'Error: Could not get list of USB ports (i.e. lsusb).'
+    logging.error('Could not get list of USB ports (i.e. lsusb).')
     return lsusb_proc.returncode
 
   usb_devices = [re.findall(r'Bus (\d\d\d) Device (\d\d\d)', lsusb_line)[0]
@@ -243,10 +233,11 @@
     if dev != '001':
       return_code = bb_utils.RunCmd(['/usr/bin/restart_usb', bus, dev])
       if return_code:
-        print 'Error restarting USB device /dev/bus/usb/%s/%s' % (bus, dev)
+        logging.error('Error restarting USB device /dev/bus/usb/%s/%s',
+                      bus, dev)
         all_restarted = False
       else:
-        print 'Restarted USB device /dev/bus/usb/%s/%s' % (bus, dev)
+        logging.info('Restarted USB device /dev/bus/usb/%s/%s', bus, dev)
 
   return all_restarted
 
@@ -263,14 +254,15 @@
   for sig in [signal.SIGTERM, signal.SIGQUIT, signal.SIGKILL]:
     for p in GetAllAdb():
       try:
-        print 'kill %d %d (%s [%s])' % (sig, p.pid, p.name,
-            ' '.join(p.cmdline))
+        logging.info('kill %d %d (%s [%s])', sig, p.pid, p.name,
+                     ' '.join(p.cmdline))
         p.send_signal(sig)
       except (psutil.NoSuchProcess, psutil.AccessDenied):
         pass
   for p in GetAllAdb():
     try:
-      print 'Unable to kill %d (%s [%s])' % (p.pid, p.name, ' '.join(p.cmdline))
+      logging.error('Unable to kill %d (%s [%s])', p.pid, p.name,
+                    ' '.join(p.cmdline))
     except (psutil.NoSuchProcess, psutil.AccessDenied):
       pass
 
@@ -288,11 +280,15 @@
                     help='Restart USB ports before running device check.')
   parser.add_option('--json-output',
                     help='Output JSON information into a specified file.')
+  parser.add_option('-v', '--verbose', action='count', default=1,
+                    help='Log more information.')
 
   options, args = parser.parse_args()
   if args:
     parser.error('Unknown options %s' % args)
 
+  run_tests_helper.SetLogLevel(options.verbose)
+
   # Remove the last build's "bad devices" before checking device statuses.
   device_blacklist.ResetBlacklist()
 
@@ -304,7 +300,8 @@
   devices = android_commands.GetAttachedDevices()
   # Only restart usb if devices are missing.
   if set(expected_devices) != set(devices):
-    print 'expected_devices: %s, devices: %s' % (expected_devices, devices)
+    logging.warning('expected_devices: %s', expected_devices)
+    logging.warning('devices: %s', devices)
     KillAllAdb()
     retries = 5
     usb_restarted = True
@@ -312,9 +309,10 @@
       if not RestartUsb():
         usb_restarted = False
         bb_annotations.PrintWarning()
-        print 'USB reset stage failed, wait for any device to come back.'
+        logging.error('USB reset stage failed, '
+                      'wait for any device to come back.')
     while retries:
-      print 'retry adb devices...'
+      logging.info('retry adb devices...')
       time.sleep(1)
       devices = android_commands.GetAttachedDevices()
       if set(expected_devices) == set(devices):
@@ -330,10 +328,10 @@
   offline_devices = android_commands.GetAttachedDevices(
       hardware=False, emulator=False, offline=True)
 
-  types, builds, batteries, reports, errors, json_data = [], [], [], [], [], []
-  fail_step_lst = []
+  types, builds, batteries, errors, devices_ok, json_data = (
+      [], [], [], [], [], [])
   if devices:
-    types, builds, batteries, reports, errors, fail_step_lst, json_data = (
+    types, builds, batteries, errors, devices_ok, json_data = (
         zip(*[DeviceInfo(dev, options) for dev in devices]))
 
   # Write device info to file for buildbot info display.
@@ -354,7 +352,16 @@
 
   bb_annotations.PrintMsg('Online devices: %d. Device types %s, builds %s'
                            % (len(devices), unique_types, unique_builds))
-  print '\n'.join(reports)
+
+  for j in json_data:
+    logging.info('Device %s (%s)', j.get('serial'), j.get('type'))
+    logging.info('  Build: %s (%s)', j.get('build'), j.get('build_detail'))
+    logging.info('  Current Battery Service state:')
+    for k, v in j.get('battery', {}).iteritems():
+      logging.info('    %s: %s', k, v)
+    logging.info('  IMEI slice: %s', j.get('imei_slice'))
+    logging.info('  WiFi IP: %s', j.get('wifi_ip'))
+
 
   for serial, dev_errors in zip(devices, errors):
     if dev_errors:
@@ -363,14 +370,14 @@
 
   if err_msg:
     bb_annotations.PrintWarning()
-    msg = '\n'.join(err_msg)
-    print msg
+    for e in err_msg:
+      logging.error(e)
     from_address = 'buildbot@chromium.org'
     to_addresses = ['chromium-android-device-alerts@google.com']
     bot_name = os.environ.get('BUILDBOT_BUILDERNAME')
     slave_name = os.environ.get('BUILDBOT_SLAVENAME')
     subject = 'Device status check errors on %s, %s.' % (slave_name, bot_name)
-    SendEmail(from_address, to_addresses, [], subject, msg)
+    SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg))
 
   if options.device_status_dashboard:
     perf_tests_results_helper.PrintPerfResult('BotDevices', 'OnlineDevices',
@@ -388,8 +395,9 @@
       f.write(json.dumps(json_data, indent=4))
 
   num_failed_devs = 0
-  for fail_status, device in zip(fail_step_lst, devices):
-    if not fail_status:
+  for device_ok, device in zip(devices_ok, devices):
+    if not device_ok:
+      logging.warning('Blacklisting %s', str(device))
       device_blacklist.ExtendBlacklist([str(device)])
       num_failed_devs += 1
 
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index c9be13a..e5df563 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -94,9 +94,10 @@
                         'ChromeDriverWebViewShell.apk',
                         'org.chromium.chromedriver_webview_shell')]))
 
-VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'gpu',
-                   'telemetry_unittests', 'telemetry_perf_unittests', 'ui',
-                   'unit', 'webkit', 'webkit_layout', 'python_unittests'])
+VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'components_browsertests',
+                   'gpu', 'python_unittests', 'telemetry_unittests',
+                   'telemetry_perf_unittests', 'ui', 'unit', 'webkit',
+                   'webkit_layout'])
 
 RunCmd = bb_utils.RunCmd
 
@@ -172,7 +173,7 @@
     bb_annotations.PrintNamedStep(suite)
     cmd = [suite] + args
     cmd += suites_options.get(suite, [])
-    if suite == 'content_browsertests':
+    if suite == 'content_browsertests' or suite == 'components_browsertests':
       cmd.append('--num_retries=1')
     _RunTest(options, cmd, suite)
 
@@ -315,7 +316,7 @@
       '--build-name', options.build_properties.get('buildername', ''),
       '--platform=android']
 
-  for flag in 'test_results_server', 'driver_name', 'additional_drt_flag':
+  for flag in 'test_results_server', 'driver_name', 'additional_driver_flag':
     if flag in options.factory_properties:
       cmd_args.extend(['--%s' % flag.replace('_', '-'),
                        options.factory_properties.get(flag)])
@@ -557,6 +558,8 @@
   return [
       ('chromedriver', RunChromeDriverTests),
       ('chrome_proxy', RunChromeProxyTests),
+      ('components_browsertests',
+          lambda options: RunTestSuites(options, ['components_browsertests'])),
       ('gpu', RunGPUTests),
       ('python_unittests', RunPythonUnitTests),
       ('telemetry_unittests', RunTelemetryUnitTests),
diff --git a/build/android/buildbot/bb_host_steps.py b/build/android/buildbot/bb_host_steps.py
index 4041ccd..1e927fb 100755
--- a/build/android/buildbot/bb_host_steps.py
+++ b/build/android/buildbot/bb_host_steps.py
@@ -4,6 +4,7 @@
 # found in the LICENSE file.
 
 import os
+import json
 import sys
 
 import bb_utils
@@ -14,7 +15,7 @@
 
 
 SLAVE_SCRIPTS_DIR = os.path.join(bb_utils.BB_BUILD_DIR, 'scripts', 'slave')
-VALID_HOST_TESTS = set(['check_webview_licenses', 'findbugs'])
+VALID_HOST_TESTS = set(['check_webview_licenses'])
 
 DIR_BUILD_ROOT = os.path.dirname(constants.DIR_SOURCE_ROOT)
 
@@ -78,17 +79,6 @@
          + bb_utils.EncodeProperties(options), cwd=DIR_BUILD_ROOT)
 
 
-def FindBugs(options):
-  bb_annotations.PrintNamedStep('findbugs')
-  build_type = []
-  if options.target == 'Release':
-    build_type = ['--release-build']
-  RunCmd([SrcPath('build', 'android', 'findbugs_diff.py')] + build_type)
-  RunCmd([SrcPath(
-      'tools', 'android', 'findbugs_plugin', 'test',
-      'run_findbugs_plugin_tests.py')] + build_type)
-
-
 def BisectPerfRegression(options):
   args = []
   if options.extra_src:
@@ -96,7 +86,9 @@
   RunCmd([SrcPath('tools', 'prepare-bisect-perf-regression.py'),
           '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir)])
   RunCmd([SrcPath('tools', 'run-bisect-perf-regression.py'),
-          '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir)] + args)
+          '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir),
+          '--build-properties=%s' % json.dumps(options.build_properties)] +
+          args)
 
 
 def GetHostStepCmds():
@@ -105,7 +97,6 @@
       ('extract_build', ExtractBuild),
       ('check_webview_licenses', CheckWebViewLicenses),
       ('bisect_perf_regression', BisectPerfRegression),
-      ('findbugs', FindBugs),
       ('zip_build', ZipBuild)
   ]
 
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 29cce1b..a6afb86 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -117,8 +117,7 @@
   compile_step = ['compile']
   chrome_proxy_tests = ['chrome_proxy']
   python_unittests = ['python_unittests']
-  std_host_tests = ['check_webview_licenses', 'findbugs']
-  emma_coverage_tests = [x for x in std_host_tests if x is not 'findbugs']
+  std_host_tests = ['check_webview_licenses']
   std_build_steps = ['compile', 'zip_build']
   std_test_steps = ['extract_build']
   std_tests = ['ui', 'unit']
@@ -164,7 +163,7 @@
       B('fyi-x86-builder-dbg',
         H(compile_step + std_host_tests, experimental, target_arch='ia32')),
       B('fyi-builder-dbg',
-        H(std_build_steps + emma_coverage_tests, experimental,
+        H(std_build_steps + std_host_tests, experimental,
           extra_gyp='emma_coverage=1')),
       B('x86-builder-dbg',
         H(compile_step + std_host_tests, target_arch='ia32')),
@@ -175,7 +174,7 @@
                       '--coverage-bucket', CHROMIUM_COVERAGE_BUCKET,
                       '--cleanup'])),
       B('user-build-fyi-tests-dbg', H(std_test_steps),
-        T(telemetry_tests_user_build)),
+        T(telemetry_tests_user_build + ['components_browsertests'])),
       B('fyi-component-builder-tests-dbg',
         H(compile_step, extra_gyp='component=shared_library'),
         T(std_tests, ['--experimental', flakiness_server])),
diff --git a/build/android/cpufeatures.gypi b/build/android/cpufeatures.gypi
index b7b0b53..672ff1f 100644
--- a/build/android/cpufeatures.gypi
+++ b/build/android/cpufeatures.gypi
@@ -2,30 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# Depend on the Android NDK's cpu feature detection. The WebView build is part
-# of the system and the library already exists; for the normal build there is a
-# gyp file in the checked-in NDK to build it.
+# Depend on the Android NDK's cpu feature detection. This additional level of
+# abstraction is no longer necessary and targets can depend directly on
+# build/android/ndk.gyp:cpu_features instead.
+# TODO(torne): delete this once all DEPS have been rolled to not use it.
+# http://crbug.com/440793
 {
-  'conditions': [
-    ['android_webview_build == 1', {
-      # This is specified twice intentionally: Android provides include paths
-      # to targets automatically if they depend on libraries, so we add this
-      # library to every target that includes this .gypi to make the headers
-      # available, then also add it to targets that link those targets via
-      # link_settings to ensure it ends up being linked even if the main target
-      # doesn't include this .gypi.
-      'libraries': [
-        'cpufeatures.a',
-      ],
-      'link_settings': {
-        'libraries': [
-          'cpufeatures.a',
-        ],
-      },
-    }, {
-      'dependencies': [
-        '<(DEPTH)/build/android/ndk.gyp:cpu_features',
-      ],
-    }],
+  'dependencies': [
+    '<(DEPTH)/build/android/ndk.gyp:cpu_features',
   ],
 }
diff --git a/build/android/enable_asserts.py b/build/android/enable_asserts.py
index 0e30bc2..8fb7dca 100755
--- a/build/android/enable_asserts.py
+++ b/build/android/enable_asserts.py
@@ -6,33 +6,37 @@
 
 """Enables dalvik vm asserts in the android device."""
 
-from pylib import android_commands
-from pylib.device import device_utils
-import optparse
+import argparse
 import sys
 
+from pylib.device import device_utils
 
-def main(argv):
-  option_parser = optparse.OptionParser()
-  option_parser.add_option('--enable_asserts', dest='set_asserts',
-      action='store_true', default=None,
+
+def main():
+  parser = argparse.ArgumentParser()
+
+  set_asserts_group = parser.add_mutually_exclusive_group(required=True)
+  set_asserts_group.add_argument(
+      '--enable_asserts', dest='set_asserts', action='store_true',
       help='Sets the dalvik.vm.enableassertions property to "all"')
-  option_parser.add_option('--disable_asserts', dest='set_asserts',
-      action='store_false', default=None,
+  set_asserts_group.add_argument(
+      '--disable_asserts', dest='set_asserts', action='store_false',
       help='Removes the dalvik.vm.enableassertions property')
-  options, _ = option_parser.parse_args(argv)
+
+  args = parser.parse_args()
 
   # TODO(jbudorick): Accept optional serial number and run only for the
   # specified device when present.
-  devices = android_commands.GetAttachedDevices()
-  for device in [device_utils.DeviceUtils(serial) for serial in devices]:
-    if options.set_asserts != None:
-      if device.SetJavaAsserts(options.set_asserts):
-        # TODO(jbudorick) How to best do shell restarts after the
-        #                 android_commands refactor?
-        device.RunShellCommand('stop')
-        device.RunShellCommand('start')
+  devices = device_utils.DeviceUtils.parallel()
+
+  def set_java_asserts_and_restart(device):
+    if device.SetJavaAsserts(args.set_asserts):
+      device.RunShellCommand('stop')
+      device.RunShellCommand('start')
+
+  devices.pMap(set_java_asserts_and_restart)
+  return 0
 
 
 if __name__ == '__main__':
-  main(sys.argv)
+  sys.exit(main())
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 9934c1a..bdf9966 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -22,16 +22,8 @@
     'keystore_path%': '<(DEPTH)/build/android/ant/chromium-debug.keystore',
     'keystore_name%': 'chromiumdebugkey',
     'keystore_password%': 'chromium',
-    'conditions': [
-        # Webview doesn't use zipalign or rezip_apk_jar.
-        ['android_webview_build==0', {
-          'zipalign_path%': '<(android_sdk_tools)/zipalign',
-          'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar'
-        }, {
-          'zipalign_path%': "",
-          'rezip_apk_jar_path%': "",
-        }],
-    ],
+    'zipalign_path%': '<(android_sdk_tools)/zipalign',
+    'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar',
   },
   'inputs': [
     '<(DEPTH)/build/android/gyp/finalize_apk.py',
diff --git a/build/android/findbugs_action.gypi b/build/android/findbugs_action.gypi
new file mode 100644
index 0000000..e3b3d36
--- /dev/null
+++ b/build/android/findbugs_action.gypi
@@ -0,0 +1,22 @@
+
+{
+  'action_name': 'findbugs_<(_target_name)',
+  'message': 'Running findbugs on <(_target_name)',
+  'variables': {
+  },
+  'inputs': [
+    '<(DEPTH)/build/android/findbugs_diff.py',
+    '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+    '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+    '<(findbugs_target_jar_path)',
+  ],
+  'outputs': [
+    '<(stamp_path)',
+  ],
+  'action': [
+    'python', '<(DEPTH)/build/android/findbugs_diff.py',
+    '--auxclasspath-gyp', '>(auxclasspath)',
+    '--stamp', '<(stamp_path)',
+    '<(findbugs_target_jar_path)',
+  ],
+}
diff --git a/build/android/findbugs_diff.py b/build/android/findbugs_diff.py
index 28224f1..f55e462 100755
--- a/build/android/findbugs_diff.py
+++ b/build/android/findbugs_diff.py
@@ -5,14 +5,6 @@
 # found in the LICENSE file.
 
 """Runs findbugs, and returns an error code if there are new warnings.
-This runs findbugs with an additional flag to exclude known bugs.
-To update the list of known bugs, do this:
-
-   findbugs_diff.py --rebaseline
-
-Note that this is separate from findbugs_exclude.xml. The "exclude" file has
-false positives that we do not plan to fix. The "known bugs" file has real
-bugs that we *do* plan to fix (but haven't done so yet).
 
 Other options
   --only-analyze used to only analyze the class you are interested.
@@ -20,30 +12,99 @@
   --findbugs-args used to passin other findbugs's options.
 
 Run
-  $CHROM_SRC/third_party/findbugs/bin/findbugs -textui for details.
+  $CHROMIUM_SRC/third_party/findbugs/bin/findbugs -textui for details.
 
 """
 
+import argparse
 import os
 import sys
 
 from pylib import constants
 from pylib.utils import findbugs
 
+_DEFAULT_BASE_DIR = os.path.join(
+    constants.DIR_SOURCE_ROOT, 'build', 'android', 'findbugs_filter')
+
+sys.path.append(
+    os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 'gyp'))
+from util import build_utils
+
 
 def main():
-  parser = findbugs.GetCommonParser()
+  parser = argparse.ArgumentParser()
 
-  options, _ = parser.parse_args()
+  parser.add_argument(
+      '-a', '--auxclasspath', default=None, dest='auxclasspath',
+      help='Set aux classpath for analysis.')
+  parser.add_argument(
+      '--auxclasspath-gyp', dest='auxclasspath_gyp',
+      help='A gyp list containing the aux classpath for analysis')
+  parser.add_argument(
+      '-o', '--only-analyze', default=None,
+      dest='only_analyze', help='Only analyze the given classes and packages.')
+  parser.add_argument(
+      '-e', '--exclude', default=None, dest='exclude',
+      help='Exclude bugs matching given filter.')
+  parser.add_argument(
+      '-l', '--release-build', action='store_true', dest='release_build',
+      help='Analyze release build instead of debug.')
+  parser.add_argument(
+      '-f', '--findbug-args', default=None, dest='findbug_args',
+      help='Additional findbug arguments.')
+  parser.add_argument(
+      '-b', '--base-dir', default=_DEFAULT_BASE_DIR,
+      dest='base_dir', help='Base directory for configuration file.')
+  parser.add_argument(
+      '--output-file', dest='output_file',
+      help='Path to save the output to.')
+  parser.add_argument(
+      '--stamp', help='Path to touch on success.')
+  parser.add_argument(
+      '--depfile', help='Path to the depfile. This must be specified as the '
+                        "action's first output.")
 
-  if not options.base_dir:
-    options.base_dir = os.path.join(constants.DIR_SOURCE_ROOT, 'build',
-                                    'android', 'findbugs_filter')
-  if not options.only_analyze:
-    options.only_analyze = 'org.chromium.-'
+  parser.add_argument(
+      'jar_paths', metavar='JAR_PATH', nargs='+',
+      help='JAR file to analyze')
 
-  return findbugs.Run(options)
+  args = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:]))
+  if args.auxclasspath:
+    args.auxclasspath = args.auxclasspath.split(':')
+  elif args.auxclasspath_gyp:
+    args.auxclasspath = build_utils.ParseGypList(args.auxclasspath_gyp)
+
+  if args.base_dir:
+    if not args.exclude:
+      args.exclude = os.path.join(args.base_dir, 'findbugs_exclude.xml')
+
+  findbugs_command, findbugs_warnings = findbugs.Run(
+      args.exclude, args.only_analyze, args.auxclasspath,
+      args.output_file, args.findbug_args, args.jar_paths)
+
+  if findbugs_warnings:
+    print
+    print '*' * 80
+    print 'FindBugs run via:'
+    print findbugs_command
+    print
+    print 'FindBugs reported the following issues:'
+    for warning in sorted(findbugs_warnings):
+      print str(warning)
+    print '*' * 80
+    print
+  else:
+    if args.depfile:
+      build_utils.WriteDepfile(
+          args.depfile,
+          build_utils.GetPythonDependencies() + args.auxclasspath
+              + args.jar_paths)
+    if args.stamp:
+      build_utils.Touch(args.stamp)
+
+  return len(findbugs_warnings)
 
 
 if __name__ == '__main__':
   sys.exit(main())
+
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml
index 5060e47..dbff9d9 100644
--- a/build/android/findbugs_filter/findbugs_exclude.xml
+++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -12,40 +12,12 @@
 <FindBugsFilter>
   <!-- Skip the generated resource classes (including nested classes). -->
   <Match>
-    <Class name="~org\.chromium\..*\.R(\$\w+)?" />
+    <Class name="~.*\.R(\$\w+)?" />
   </Match>
   <Match>
     <Class name="~org\.chromium\..*\.Manifest(\$\w+)?" />
   </Match>
+  <Bug pattern="DM_STRING_CTOR" />
   <!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
-  <Match>
-    <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
-    <Method name="onCancel" />
-    <Bug code="Dm" />
-  </Match>
-  <Match>
-    <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
-    <Method name="onClick" />
-    <Bug code="Dm" />
-  </Match>
   <Bug pattern="DM_DEFAULT_ENCODING" />
-  <!-- Ignore bugs that are often false-positives in test code -->
-  <Match>
-    <Class name="~org\.chromium\..*Test(\$\w+)?" />
-    <Or>
-      <Bug code="DLS,UrF" />
-      <Bug pattern="DM_GC" />
-    </Or>
-  </Match>
-  <!--
-  crbug.com/449101
-  Ignore findbugs plugin test cases.
-  -->
-  <Match>
-    <Or>
-      <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedMethod" />
-      <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedStaticMethod" />
-      <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedThis" />
-    </Or>
-  </Match>
 </FindBugsFilter>
diff --git a/build/android/gyp/jarjar_resources.py b/build/android/gyp/jarjar_resources.py
deleted file mode 100755
index 67b510b..0000000
--- a/build/android/gyp/jarjar_resources.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Transforms direct Java class references in Android layout .xml files
-according to the specified JarJar rules."""
-
-import optparse
-import os
-import shutil
-import sys
-from xml.dom import minidom
-
-from util import build_utils
-
-
-class JarJarRules(object):
-  def __init__(self, jarjar_rules):
-    self._rules = []
-    for line in jarjar_rules.splitlines():
-      rule = line.split()
-      if rule[0] != 'rule':
-        continue
-      _, src, dest = rule
-      if src.endswith('**'):
-        src_real_name = src[:-2]
-      else:
-        assert not '*' in src
-        src_real_name = src
-
-      if dest.endswith('@0'):
-        self._rules.append((src, dest[:-2] + src_real_name))
-      elif dest.endswith('@1'):
-        assert '**' in src
-        self._rules.append((src, dest[:-2]))
-      else:
-        assert not '@' in dest
-        self._rules.append((src, dest))
-
-  def RenameClass(self, class_name):
-    for old, new in self._rules:
-      if old.endswith('**') and old[:-2] in class_name:
-        return class_name.replace(old[:-2], new, 1)
-      if '*' not in old and class_name.endswith(old):
-        return class_name.replace(old, new, 1)
-    return class_name
-
-
-def RenameNodes(node, rules):
-  if node.nodeType == node.ELEMENT_NODE:
-    if node.tagName.lower() == 'view' and  node.attributes.has_key('class'):
-      node.attributes['class'] = rules.RenameClass(node.attributes['class'])
-    else:
-      node.tagName = rules.RenameClass(node.tagName)
-  for child in node.childNodes:
-    RenameNodes(child, rules)
-
-
-def ProcessLayoutFile(path, rules):
-  xmldoc = minidom.parse(path)
-  RenameNodes(xmldoc.documentElement, rules)
-  with open(path, 'w') as f:
-    xmldoc.writexml(f)
-
-
-def LayoutFilesFilter(src, names):
-  if os.path.basename(src).lower() != 'layout':
-    return []
-  else:
-    return filter(lambda n: n.endswith('.xml'), names)
-
-
-def ProcessResources(options):
-  with open(options.rules_path) as f:
-    rules = JarJarRules(f.read())
-
-  build_utils.DeleteDirectory(options.output_dir)
-  for input_dir in options.input_dir:
-    shutil.copytree(input_dir, options.output_dir)
-
-  for root, _dirnames, filenames in os.walk(options.output_dir):
-    layout_files = LayoutFilesFilter(root, filenames)
-    for layout_file in layout_files:
-      ProcessLayoutFile(os.path.join(root, layout_file), rules)
-
-
-def ParseArgs():
-  parser = optparse.OptionParser()
-  parser.add_option('--input-dir', action='append',
-                    help='Path to the resources folder to process.')
-  parser.add_option('--output-dir',
-                    help=('Directory to hold processed resources. Note: the ' +
-                          'directory will be clobbered on every invocation.'))
-  parser.add_option('--rules-path',
-                    help='Path to the jarjar rules file.')
-  parser.add_option('--stamp', help='Path to touch on success.')
-
-  options, args = parser.parse_args()
-
-  if args:
-    parser.error('No positional arguments should be given.')
-
-  # Check that required options have been provided.
-  required_options = ('input_dir', 'output_dir', 'rules_path')
-  build_utils.CheckOptions(options, parser, required=required_options)
-
-  return options
-
-
-def main():
-  options = ParseArgs()
-
-  ProcessResources(options)
-
-  if options.stamp:
-    build_utils.Touch(options.stamp)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/build/android/gyp/jinja_template.py b/build/android/gyp/jinja_template.py
index 9e9705c..6653f21 100755
--- a/build/android/gyp/jinja_template.py
+++ b/build/android/gyp/jinja_template.py
@@ -34,15 +34,17 @@
     return list(self.loaded_templates)
 
 
-def ProcessFile(env, input_filename, output_filename, variables):
-  input_rel_path = os.path.relpath(input_filename, build_utils.CHROMIUM_SRC)
+def ProcessFile(env, input_filename, loader_base_dir, output_filename,
+                variables):
+  input_rel_path = os.path.relpath(input_filename, loader_base_dir)
   template = env.get_template(input_rel_path)
   output = template.render(variables)
   with codecs.open(output_filename, 'w', 'utf-8') as output_file:
     output_file.write(output)
 
 
-def ProcessFiles(env, input_filenames, inputs_base_dir, outputs_zip, variables):
+def ProcessFiles(env, input_filenames, loader_base_dir, inputs_base_dir,
+                 outputs_zip, variables):
   with build_utils.TempDir() as temp_dir:
     for input_filename in input_filenames:
       relpath = os.path.relpath(os.path.abspath(input_filename),
@@ -54,7 +56,8 @@
       output_filename = os.path.join(temp_dir, relpath)
       parent_dir = os.path.dirname(output_filename)
       build_utils.MakeDirectory(parent_dir)
-      ProcessFile(env, input_filename, output_filename, variables)
+      ProcessFile(env, input_filename, loader_base_dir, output_filename,
+                  variables)
 
     build_utils.ZipDir(outputs_zip, temp_dir)
 
@@ -71,6 +74,10 @@
                     'the inputs. Each output\'s path in the output zip will '
                     'match the relative path from INPUTS_BASE_DIR to the '
                     'input. Required if --output-zip is given.')
+  parser.add_option('--loader-base-dir', help='Base path used by the template '
+                    'loader. Must be a common ancestor directory of '
+                    'the inputs. Defaults to CHROMIUM_SRC.',
+                    default=build_utils.CHROMIUM_SRC)
   parser.add_option('--variables', help='Variables to be made available in the '
                     'template processing environment, as a GYP list (e.g. '
                     '--variables "channel=beta mstone=39")', default='')
@@ -95,14 +102,15 @@
     name, _, value = v.partition('=')
     variables[name] = value
 
-  loader = RecordingFileSystemLoader(build_utils.CHROMIUM_SRC)
+  loader = RecordingFileSystemLoader(options.loader_base_dir)
   env = jinja2.Environment(loader=loader, undefined=jinja2.StrictUndefined,
                            line_comment_prefix='##')
   if options.output:
-    ProcessFile(env, inputs[0], options.output, variables)
+    ProcessFile(env, inputs[0], options.loader_base_dir, options.output,
+                variables)
   else:
-    ProcessFiles(env, inputs, options.inputs_base_dir, options.outputs_zip,
-                 variables)
+    ProcessFiles(env, inputs, options.loader_base_dir, options.inputs_base_dir,
+                 options.outputs_zip, variables)
 
   if options.depfile:
     deps = loader.get_loaded_templates() + build_utils.GetPythonDependencies()
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index 52cf143..4e6c27d 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -10,6 +10,7 @@
 (see generate_v14_compatible_resources.py).
 """
 
+import codecs
 import optparse
 import os
 import re
@@ -112,14 +113,15 @@
   if len(java_files) != 1:
     return
   r_java_file = java_files[0]
-  r_java_contents = open(r_java_file).read()
+  r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()
 
   for package in extra_packages:
     package_r_java_dir = os.path.join(r_dir, *package.split('.'))
     build_utils.MakeDirectory(package_r_java_dir)
     package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
-    open(package_r_java_path, 'w').write(
-        re.sub(r'package [.\w]*;', 'package %s;' % package, r_java_contents))
+    new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
+                        r_java_contents)
+    codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
     # TODO(cjhopman): These extra package's R.java files should be filtered to
     # only contain the resources listed in their R.txt files. At this point, we
     # have already compiled those other libraries, so doing this would only
diff --git a/build/android/gyp/util/build_device.py b/build/android/gyp/util/build_device.py
index b153a15..7e0d57b 100644
--- a/build/android/gyp/util/build_device.py
+++ b/build/android/gyp/util/build_device.py
@@ -40,7 +40,7 @@
     return self.id
 
   def Install(self, *args, **kwargs):
-    return self.device.old_interface.Install(*args, **kwargs)
+    return self.device.Install(*args, **kwargs)
 
   def GetInstallMetadata(self, apk_package):
     """Gets the metadata on the device for the apk_package apk."""
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index a0cd7c1..65b1a64 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -24,7 +24,7 @@
                              'third_party', 'colorama', 'src')
 # aapt should ignore OWNERS files in addition the default ignore pattern.
 AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' +
-                       '!CVS:!thumbs.db:!picasa.ini:!*~')
+                       '!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp')
 
 
 @contextlib.contextmanager
@@ -236,6 +236,7 @@
 
 
 def MergeZips(output, inputs, exclude_patterns=None):
+  added_names = set()
   def Allow(name):
     if exclude_patterns is not None:
       for p in exclude_patterns:
@@ -247,8 +248,9 @@
     for in_file in inputs:
       with zipfile.ZipFile(in_file, 'r') as in_zip:
         for name in in_zip.namelist():
-          if Allow(name):
+          if name not in added_names and Allow(name):
             out_zip.writestr(name, in_zip.read(name))
+            added_names.add(name)
 
 
 def PrintWarning(message):
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 5fc8955..1b4379d 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -29,11 +29,43 @@
 import optparse
 import os
 import sys
+import xml.dom.minidom
 
 from util import build_utils
 
 import write_ordered_libraries
 
+class AndroidManifest(object):
+  def __init__(self, path):
+    self.path = path
+    dom = xml.dom.minidom.parse(path)
+    manifests = dom.getElementsByTagName('manifest')
+    assert len(manifests) == 1
+    self.manifest = manifests[0]
+
+  def GetInstrumentation(self):
+    instrumentation_els = self.manifest.getElementsByTagName('instrumentation')
+    if len(instrumentation_els) == 0:
+      return None
+    if len(instrumentation_els) != 1:
+      raise Exception(
+          'More than one <instrumentation> element found in %s' % self.path)
+    return instrumentation_els[0]
+
+  def CheckInstrumentation(self, expected_package):
+    instr = self.GetInstrumentation()
+    if not instr:
+      raise Exception('No <instrumentation> elements found in %s' % self.path)
+    instrumented_package = instr.getAttributeNS(
+        'http://schemas.android.com/apk/res/android', 'targetPackage')
+    if instrumented_package != expected_package:
+      raise Exception(
+          'Wrong instrumented package. Expected %s, got %s'
+          % (expected_package, instrumented_package))
+
+  def GetPackageName(self):
+    return self.manifest.getAttribute('package')
+
 
 dep_config_cache = {}
 def GetDepConfig(path):
@@ -88,6 +120,10 @@
   parser.add_option('--native-libs', help='List of top-level native libs.')
   parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.')
 
+  parser.add_option('--tested-apk-config',
+      help='Path to the build config of the tested apk (for an instrumentation '
+      'test apk).')
+
   options, args = parser.parse_args(argv)
 
   if args:
@@ -154,7 +190,6 @@
   }
   deps_info = config['deps_info']
 
-
   if options.type == 'java_library' and not options.bypass_platform_checks:
     deps_info['requires_android'] = options.requires_android
     deps_info['supports_android'] = options.supports_android
@@ -172,7 +207,6 @@
       raise Exception('Not all deps support the Android platform: ' +
           str(deps_not_support_android))
 
-
   if options.type in ['java_library', 'android_apk']:
     javac_classpath = [c['jar_path'] for c in direct_library_deps]
     java_full_classpath = [c['jar_path'] for c in all_library_deps]
@@ -216,14 +250,31 @@
     config['resources']['extra_package_names'] = [
         c['package_name'] for c in all_resources_deps if 'package_name' in c]
 
+  if options.type in ['android_apk', 'deps_dex']:
+    deps_dex_files = [c['dex_path'] for c in all_library_deps]
+
+  # An instrumentation test apk should exclude the dex files that are in the apk
+  # under test.
+  if options.type == 'android_apk' and options.tested_apk_config:
+    tested_apk_config_paths = GetAllDepsConfigsInOrder(
+        [options.tested_apk_config])
+    tested_apk_configs = [GetDepConfig(p) for p in tested_apk_config_paths]
+    tested_apk_library_deps = DepsOfType('java_library', tested_apk_configs)
+    tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps]
+    deps_dex_files = [
+        p for p in deps_dex_files if not p in tested_apk_deps_dex_files]
+
+    tested_apk_config = GetDepConfig(options.tested_apk_config)
+    expected_tested_package = tested_apk_config['package_name']
+    AndroidManifest(options.android_manifest).CheckInstrumentation(
+        expected_tested_package)
 
   # Dependencies for the final dex file of an apk or a 'deps_dex'.
   if options.type in ['android_apk', 'deps_dex']:
     config['final_dex'] = {}
     dex_config = config['final_dex']
     # TODO(cjhopman): proguard version
-    dex_deps_files = [c['dex_path'] for c in all_library_deps]
-    dex_config['dependency_dex_files'] = dex_deps_files
+    dex_config['dependency_dex_files'] = deps_dex_files
 
   if options.type == 'android_apk':
     config['dist_jar'] = {
@@ -231,6 +282,11 @@
         c['jar_path'] for c in all_library_deps
       ]
     }
+    manifest = AndroidManifest(options.android_manifest)
+    deps_info['package_name'] = manifest.GetPackageName()
+    if not options.tested_apk_config and manifest.GetInstrumentation():
+      # This must then have instrumentation only for itself.
+      manifest.CheckInstrumentation(manifest.GetPackageName())
 
     library_paths = []
     java_libraries_list = []
diff --git a/build/android/host_heartbeat.py b/build/android/host_heartbeat.py
index 429fca9..6a7cdd1 100755
--- a/build/android/host_heartbeat.py
+++ b/build/android/host_heartbeat.py
@@ -12,7 +12,6 @@
 import sys
 import time
 
-from pylib import android_commands
 from pylib.device import device_utils
 
 PULSE_PERIOD = 20
@@ -20,10 +19,10 @@
 def main():
   while True:
     try:
-      devices = android_commands.GetAttachedDevices()
-      for device_serial in devices:
-        device_utils.DeviceUtils(device_serial).RunShellCommand(
-            'touch /sdcard/host_heartbeat')
+      devices = device_utils.DeviceUtils.HealthyDevices()
+      for d in devices:
+        d.RunShellCommand(['touch', '/sdcard/host_heartbeat'],
+                          check_return=True)
     except:
       # Keep the heatbeat running bypassing all errors.
       pass
diff --git a/build/android/java_cpp_enum.gypi b/build/android/java_cpp_enum.gypi
index b51351b..d4abafa 100644
--- a/build/android/java_cpp_enum.gypi
+++ b/build/android/java_cpp_enum.gypi
@@ -33,6 +33,11 @@
       'generated_src_dirs': [
         '<(output_dir)/',
       ],
+      # Ensure that the targets depending on this one are rebuilt if the sources
+      # of this one are modified.
+      'additional_input_paths': [
+        '<(source_file)',
+      ],
     },
   },
   'actions': [
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 5f00b31..ee52c71 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -19,9 +19,9 @@
 import sys
 import time
 
-from pylib import android_commands
 from pylib import constants
 from pylib import device_settings
+from pylib.device import battery_utils
 from pylib.device import device_blacklist
 from pylib.device import device_errors
 from pylib.device import device_utils
@@ -41,54 +41,148 @@
   HELP_TEXT = '{}s on L, {}s on pre-L'.format(LOLLIPOP, PRE_LOLLIPOP)
 
 
-def KillHostHeartbeat():
-  ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
-  stdout, _ = ps.communicate()
-  matches = re.findall('\\n.*host_heartbeat.*', stdout)
-  for match in matches:
-    logging.info('An instance of host heart beart running... will kill')
-    pid = re.findall(r'(\S+)', match)[1]
-    subprocess.call(['kill', str(pid)])
+class _PHASES(object):
+  WIPE = 'wipe'
+  PROPERTIES = 'properties'
+  FINISH = 'finish'
+
+  ALL = [WIPE, PROPERTIES, FINISH]
 
 
-def LaunchHostHeartbeat():
-  # Kill if existing host_heartbeat
-  KillHostHeartbeat()
-  # Launch a new host_heartbeat
-  logging.info('Spawning host heartbeat...')
-  subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
-                                 'build/android/host_heartbeat.py')])
+def ProvisionDevices(options):
+  if options.device is not None:
+    devices = [options.device]
+  else:
+    devices = device_utils.DeviceUtils.HealthyDevices()
+
+  parallel_devices = device_utils.DeviceUtils.parallel(devices)
+  parallel_devices.pMap(ProvisionDevice, options)
+  if options.auto_reconnect:
+    _LaunchHostHeartbeat()
+  blacklist = device_blacklist.ReadBlacklist()
+  if all(d in blacklist for d in devices):
+    raise device_errors.NoDevicesError
+  return 0
 
 
-def PushAndLaunchAdbReboot(device, target):
-  """Pushes and launches the adb_reboot binary on the device.
+def ProvisionDevice(device, options):
+  if options.reboot_timeout:
+    reboot_timeout = options.reboot_timeout
+  elif (device.build_version_sdk >=
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+    reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
+  else:
+    reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
+
+  def should_run_phase(phase_name):
+    return not options.phases or phase_name in options.phases
+
+  def run_phase(phase_func, reboot=True):
+    device.WaitUntilFullyBooted(timeout=reboot_timeout)
+    phase_func(device, options)
+    if reboot:
+      device.Reboot(False, retries=0)
+      device.adb.WaitForDevice()
+
+  try:
+    if should_run_phase(_PHASES.WIPE):
+      run_phase(WipeDevice)
+
+    if should_run_phase(_PHASES.PROPERTIES):
+      run_phase(SetProperties)
+
+    if should_run_phase(_PHASES.FINISH):
+      run_phase(FinishProvisioning, reboot=False)
+
+  except (errors.WaitForResponseTimedOutError,
+          device_errors.CommandTimeoutError):
+    logging.exception('Timed out waiting for device %s. Adding to blacklist.',
+                      str(device))
+    device_blacklist.ExtendBlacklist([str(device)])
+
+  except device_errors.CommandFailedError:
+    logging.exception('Failed to provision device %s. Adding to blacklist.',
+                      str(device))
+    device_blacklist.ExtendBlacklist([str(device)])
+
+
+def WipeDevice(device, options):
+  """Wipes data from device, keeping only the adb_keys for authorization.
+
+  After wiping data on a device that has been authorized, adb can still
+  communicate with the device, but after reboot the device will need to be
+  re-authorized because the adb keys file is stored in /data/misc/adb/.
+  Thus, adb_keys file is rewritten so the device does not need to be
+  re-authorized.
 
   Arguments:
-    device: The DeviceUtils instance for the device to which the adb_reboot
-            binary should be pushed.
-    target: The build target (example, Debug or Release) which helps in
-            locating the adb_reboot binary.
+    device: the device to wipe
   """
-  logging.info('Will push and launch adb_reboot on %s' % str(device))
-  # Kill if adb_reboot is already running.
+  if options.skip_wipe:
+    return
+
   try:
-    # Don't try to kill adb_reboot more than once. We don't expect it to be
-    # running at all.
-    device.KillAll('adb_reboot', blocking=True, timeout=2, retries=0)
+    device.EnableRoot()
+    device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
+    if device_authorized:
+      adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
+                                 as_root=True).splitlines()
+    device.RunShellCommand(['wipe', 'data'],
+                           as_root=True, check_return=True)
+    device.adb.WaitForDevice()
+
+    if device_authorized:
+      adb_keys_set = set(adb_keys)
+      for adb_key_file in options.adb_key_files or []:
+        try:
+          with open(adb_key_file, 'r') as f:
+            adb_public_keys = f.readlines()
+          adb_keys_set.update(adb_public_keys)
+        except IOError:
+          logging.warning('Unable to find adb keys file %s.' % adb_key_file)
+      _WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
   except device_errors.CommandFailedError:
-    # We can safely ignore the exception because we don't expect adb_reboot
-    # to be running.
-    pass
-  # Push adb_reboot
-  logging.info('  Pushing adb_reboot ...')
-  adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
-                            'out/%s/adb_reboot' % target)
-  device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
-  # Launch adb_reboot
-  logging.info('  Launching adb_reboot ...')
-  device.RunShellCommand([
-      device.GetDevicePieWrapper(),
-      '/data/local/tmp/adb_reboot'])
+    logging.exception('Possible failure while wiping the device. '
+                      'Attempting to continue.')
+
+
+def _WriteAdbKeysFile(device, adb_keys_string):
+  dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
+  device.RunShellCommand(['mkdir', '-p', dir_path],
+                         as_root=True, check_return=True)
+  device.RunShellCommand(['restorecon', dir_path],
+                         as_root=True, check_return=True)
+  device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
+  device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE],
+                         as_root=True, check_return=True)
+
+
+def SetProperties(device, options):
+  try:
+    device.EnableRoot()
+  except device_errors.CommandFailedError as e:
+    logging.warning(str(e))
+
+  _ConfigureLocalProperties(device, options.enable_java_debug)
+  device_settings.ConfigureContentSettings(
+      device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
+  if options.disable_location:
+    device_settings.ConfigureContentSettings(
+        device, device_settings.DISABLE_LOCATION_SETTINGS)
+  else:
+    device_settings.ConfigureContentSettings(
+        device, device_settings.ENABLE_LOCATION_SETTINGS)
+  device_settings.SetLockScreenSettings(device)
+  if options.disable_network:
+    device_settings.ConfigureContentSettings(
+        device, device_settings.NETWORK_DISABLED_SETTINGS)
+
+  if options.min_battery_level is not None:
+    try:
+      battery = battery_utils.BatteryUtils(device)
+      battery.ChargeDeviceToLevel(options.min_battery_level)
+    except device_errors.CommandFailedError as e:
+      logging.exception('Unable to charge device to specified level.')
 
 
 def _ConfigureLocalProperties(device, java_debug=True):
@@ -101,7 +195,8 @@
       'ro.setupwizard.mode=DISABLED',
       ]
   if java_debug:
-    local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY)
+    local_props.append(
+        '%s=all' % device_utils.DeviceUtils.JAVA_ASSERT_PROPERTY)
     local_props.append('debug.checkjni=1')
   try:
     device.WriteFile(
@@ -110,153 +205,66 @@
     # Android will not respect the local props file if it is world writable.
     device.RunShellCommand(
         ['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH],
-        as_root=True)
-  except device_errors.CommandFailedError as e:
-    logging.warning(str(e))
-
-  # LOCAL_PROPERTIES_PATH = '/data/local.prop'
-
-def WriteAdbKeysFile(device, adb_keys_string):
-  dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
-  device.RunShellCommand('mkdir -p %s' % dir_path, as_root=True)
-  device.RunShellCommand('restorecon %s' % dir_path, as_root=True)
-  device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
-  device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE,
-                         as_root=True)
+        as_root=True, check_return=True)
+  except device_errors.CommandFailedError:
+    logging.exception('Failed to configure local properties.')
 
 
-def WipeDeviceData(device, options):
-  """Wipes data from device, keeping only the adb_keys for authorization.
+def FinishProvisioning(device, options):
+  device.RunShellCommand(
+      ['date', '-s', time.strftime('%Y%m%d.%H%M%S', time.gmtime())],
+      as_root=True, check_return=True)
+  props = device.RunShellCommand('getprop', check_return=True)
+  for prop in props:
+    logging.info('  %s' % prop)
+  if options.auto_reconnect:
+    _PushAndLaunchAdbReboot(device, options.target)
 
-  After wiping data on a device that has been authorized, adb can still
-  communicate with the device, but after reboot the device will need to be
-  re-authorized because the adb keys file is stored in /data/misc/adb/.
-  Thus, adb_keys file is rewritten so the device does not need to be
-  re-authorized.
+
+def _PushAndLaunchAdbReboot(device, target):
+  """Pushes and launches the adb_reboot binary on the device.
 
   Arguments:
-    device: the device to wipe
+    device: The DeviceUtils instance for the device to which the adb_reboot
+            binary should be pushed.
+    target: The build target (example, Debug or Release) which helps in
+            locating the adb_reboot binary.
   """
-  device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
-  if device_authorized:
-    adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
-                               as_root=True).splitlines()
-  device.RunShellCommand('wipe data', as_root=True)
-  if device_authorized:
-    adb_keys_set = set(adb_keys)
-    for adb_key_file in options.adb_key_files or []:
-      try:
-        with open(adb_key_file, 'r') as f:
-          adb_public_keys = f.readlines()
-        adb_keys_set.update(adb_public_keys)
-      except IOError:
-        logging.warning('Unable to find adb keys file %s.' % adb_key_file)
-    WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
+  logging.info('Will push and launch adb_reboot on %s' % str(device))
+  # Kill if adb_reboot is already running.
+  device.KillAll('adb_reboot', blocking=True, timeout=2, quiet=True)
+  # Push adb_reboot
+  logging.info('  Pushing adb_reboot ...')
+  adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
+                            'out/%s/adb_reboot' % target)
+  device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
+  # Launch adb_reboot
+  logging.info('  Launching adb_reboot ...')
+  device.RunShellCommand(
+      [device.GetDevicePieWrapper(), '/data/local/tmp/adb_reboot'],
+      check_return=True)
 
 
-def WipeDeviceIfPossible(device, timeout, options):
-  try:
-    device.EnableRoot()
-    WipeDeviceData(device, options)
-    device.Reboot(True, timeout=timeout, retries=0)
-  except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError):
-    pass
+def _LaunchHostHeartbeat():
+  # Kill if existing host_heartbeat
+  KillHostHeartbeat()
+  # Launch a new host_heartbeat
+  logging.info('Spawning host heartbeat...')
+  subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
+                                 'build/android/host_heartbeat.py')])
 
 
-def ChargeDeviceToLevel(device, level):
-  def device_charged():
-    battery_level = device.GetBatteryInfo().get('level')
-    if battery_level is None:
-      logging.warning('Unable to find current battery level.')
-      battery_level = 100
-    else:
-      logging.info('current battery level: %d', battery_level)
-      battery_level = int(battery_level)
-    return battery_level >= level
-
-  timeout_retry.WaitFor(device_charged, wait_period=60)
-
-
-def ProvisionDevice(device, options):
-  if options.reboot_timeout:
-    reboot_timeout = options.reboot_timeout
-  elif (device.build_version_sdk >=
-        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
-    reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
-  else:
-    reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
-
-  try:
-    if not options.skip_wipe:
-      WipeDeviceIfPossible(device, reboot_timeout, options)
-    try:
-      device.EnableRoot()
-    except device_errors.CommandFailedError as e:
-      logging.warning(str(e))
-    _ConfigureLocalProperties(device, options.enable_java_debug)
-    device_settings.ConfigureContentSettings(
-        device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
-    if options.disable_location:
-      device_settings.ConfigureContentSettings(
-          device, device_settings.DISABLE_LOCATION_SETTINGS)
-    else:
-      device_settings.ConfigureContentSettings(
-          device, device_settings.ENABLE_LOCATION_SETTINGS)
-    device_settings.SetLockScreenSettings(device)
-    if options.disable_network:
-      device_settings.ConfigureContentSettings(
-          device, device_settings.NETWORK_DISABLED_SETTINGS)
-    if options.min_battery_level is not None:
-      try:
-        device.SetCharging(True)
-        ChargeDeviceToLevel(device, options.min_battery_level)
-      except device_errors.CommandFailedError as e:
-        logging.exception('Unable to charge device to specified level.')
-
-    if not options.skip_wipe:
-      device.Reboot(True, timeout=reboot_timeout, retries=0)
-    device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S',
-                                                        time.gmtime()),
-                           as_root=True)
-    props = device.RunShellCommand('getprop')
-    for prop in props:
-      logging.info('  %s' % prop)
-    if options.auto_reconnect:
-      PushAndLaunchAdbReboot(device, options.target)
-  except (errors.WaitForResponseTimedOutError,
-          device_errors.CommandTimeoutError):
-    logging.info('Timed out waiting for device %s. Adding to blacklist.',
-                 str(device))
-    # Device black list is reset by bb_device_status_check.py per build.
-    device_blacklist.ExtendBlacklist([str(device)])
-  except device_errors.CommandFailedError:
-    logging.exception('Failed to provision device %s. Adding to blacklist.',
-                      str(device))
-    device_blacklist.ExtendBlacklist([str(device)])
-
-
-def ProvisionDevices(options):
-  if options.device is not None:
-    devices = [options.device]
-  else:
-    devices = android_commands.GetAttachedDevices()
-
-  parallel_devices = device_utils.DeviceUtils.parallel(devices)
-  parallel_devices.pMap(ProvisionDevice, options)
-  if options.auto_reconnect:
-    LaunchHostHeartbeat()
-  blacklist = device_blacklist.ReadBlacklist()
-  if all(d in blacklist for d in devices):
-    raise device_errors.NoDevicesError
-  return 0
+def KillHostHeartbeat():
+  ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  stdout, _ = ps.communicate()
+  matches = re.findall('\\n.*host_heartbeat.*', stdout)
+  for match in matches:
+    logging.info('An instance of host heart beart running... will kill')
+    pid = re.findall(r'(\S+)', match)[1]
+    subprocess.call(['kill', str(pid)])
 
 
 def main():
-  custom_handler = logging.StreamHandler(sys.stdout)
-  custom_handler.setFormatter(run_tests_helper.CustomFormatter())
-  logging.getLogger().addHandler(custom_handler)
-  logging.getLogger().setLevel(logging.INFO)
-
   # Recommended options on perf bots:
   # --disable-network
   #     TODO(tonyg): We eventually want network on. However, currently radios
@@ -271,6 +279,10 @@
   parser.add_argument('-d', '--device', metavar='SERIAL',
                       help='the serial number of the device to be provisioned'
                       ' (the default is to provision all devices attached)')
+  parser.add_argument('--phase', action='append', choices=_PHASES.ALL,
+                      dest='phases',
+                      help='Phases of provisioning to run. '
+                           '(If omitted, all phases will be run.)')
   parser.add_argument('--skip-wipe', action='store_true', default=False,
                       help="don't wipe device data during provisioning")
   parser.add_argument('--reboot-timeout', metavar='SECS', type=int,
@@ -294,9 +306,13 @@
                       ' disconnections')
   parser.add_argument('--adb-key-files', type=str, nargs='+',
                       help='list of adb keys to push to device')
+  parser.add_argument('-v', '--verbose', action='count', default=1,
+                      help='Log more information.')
   args = parser.parse_args()
   constants.SetBuildType(args.target)
 
+  run_tests_helper.SetLogLevel(args.verbose)
+
   return ProvisionDevices(args)
 
 
diff --git a/build/android/pylib/base/base_test_runner.py b/build/android/pylib/base/base_test_runner.py
index 4e2eae7..1ca0338 100644
--- a/build/android/pylib/base/base_test_runner.py
+++ b/build/android/pylib/base/base_test_runner.py
@@ -26,12 +26,11 @@
 class BaseTestRunner(object):
   """Base class for running tests on a single device."""
 
-  def __init__(self, device_serial, tool, cleanup_test_files=False):
+  def __init__(self, device_serial, tool):
     """
       Args:
         device: Tests will run on the device of this ID.
         tool: Name of the Valgrind tool.
-        cleanup_test_files: Whether or not to cleanup test files on device.
     """
     self.device_serial = device_serial
     self.device = device_utils.DeviceUtils(device_serial)
@@ -45,7 +44,6 @@
     # starting it in TestServerThread.
     self.test_server_spawner_port = 0
     self.test_server_port = 0
-    self._cleanup_test_files = cleanup_test_files
 
   def _PushTestServerPortInfoToDevice(self):
     """Pushes the latest port information to device."""
@@ -77,8 +75,6 @@
   def TearDown(self):
     """Run once after all tests are run."""
     self.ShutdownHelperToolsForTestSuite()
-    if self._cleanup_test_files:
-      self.device.old_interface.RemovePushedFiles()
 
   def LaunchTestHttpServer(self, document_root, port=None,
                            extra_config_contents=None):
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants/__init__.py
similarity index 95%
rename from build/android/pylib/constants.py
rename to build/android/pylib/constants/__init__.py
index 34dbf19..6e92f6d 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants/__init__.py
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 """Defines a set of constants shared by test runners and other scripts."""
+
+# TODO(jbudorick): Split these constants into coherent modules.
+
 # pylint: disable=W0212
 
 import collections
@@ -13,7 +16,7 @@
 
 DIR_SOURCE_ROOT = os.environ.get('CHECKOUT_SOURCE_ROOT',
     os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                 os.pardir, os.pardir, os.pardir)))
+                                 os.pardir, os.pardir, os.pardir, os.pardir)))
 ISOLATE_DEPS_DIR = os.path.join(DIR_SOURCE_ROOT, 'isolate_deps_dir')
 
 CHROME_SHELL_HOST_DRIVEN_DIR = os.path.join(
@@ -50,7 +53,7 @@
         'chrome_devtools_remote',
         None),
     'chrome_dev': PackageInfo(
-        'com.google.android.apps.chrome_dev',
+        'com.chrome.dev',
         'com.google.android.apps.chrome.Main',
         '/data/local/chrome-command-line',
         'chrome_devtools_remote',
@@ -103,6 +106,13 @@
         '/data/local/tmp/chrome-native-tests-command-line',
         None,
         None),
+    'components_browsertests': PackageInfo(
+        'org.chromium.components_browsertests_apk',
+        ('org.chromium.components_browsertests_apk' +
+         '.ComponentsBrowserTestsActivity'),
+        '/data/local/tmp/components-browser-tests-command-line',
+        None,
+        None),
     'content_browsertests': PackageInfo(
         'org.chromium.content_browsertests_apk',
         'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity',
diff --git a/build/android/pylib/constants/keyevent.py b/build/android/pylib/constants/keyevent.py
new file mode 100644
index 0000000..06736b3
--- /dev/null
+++ b/build/android/pylib/constants/keyevent.py
@@ -0,0 +1,14 @@
+# 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.
+
+"""Android KeyEvent constants.
+
+http://developer.android.com/reference/android/view/KeyEvent.html
+"""
+
+KEYCODE_BACK = 4
+KEYCODE_DPAD_RIGHT = 22
+KEYCODE_ENTER = 66
+KEYCODE_MENU = 82
+
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 36f8f48..20787c1 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -12,6 +12,7 @@
 import errno
 import logging
 import os
+import re
 
 from pylib import cmd_helper
 from pylib import constants
@@ -23,6 +24,10 @@
 _DEFAULT_TIMEOUT = 30
 _DEFAULT_RETRIES = 2
 
+_EMULATOR_RE = re.compile(r'^emulator-[0-9]+$')
+
+_READY_STATE = 'device'
+
 
 def _VerifyLocalFileExists(path):
   """Verifies a local file exists.
@@ -158,9 +163,15 @@
     cls._RunAdbCmd(['start-server'], timeout=timeout, retries=retries,
                    cpu_affinity=0)
 
-  # TODO(craigdh): Determine the filter criteria that should be supported.
   @classmethod
   def GetDevices(cls, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
+    """DEPRECATED. Refer to Devices(...) below."""
+    # TODO(jbudorick): Remove this function once no more clients are using it.
+    return cls.Devices(timeout=timeout, retries=retries)
+
+  @classmethod
+  def Devices(cls, is_ready=True, timeout=_DEFAULT_TIMEOUT,
+              retries=_DEFAULT_RETRIES):
     """Get the list of active attached devices.
 
     Args:
@@ -171,9 +182,9 @@
       AdbWrapper instances.
     """
     output = cls._RunAdbCmd(['devices'], timeout=timeout, retries=retries)
-    lines = [line.split() for line in output.splitlines()]
+    lines = (line.split() for line in output.splitlines())
     return [AdbWrapper(line[0]) for line in lines
-            if len(line) == 2 and line[1] == 'device']
+            if len(line) == 2 and (not is_ready or line[1] == _READY_STATE)]
 
   def GetDeviceSerial(self):
     """Gets the device serial number associated with this object.
@@ -530,3 +541,15 @@
     if 'cannot' in output:
       raise device_errors.AdbCommandFailedError(
           ['root'], output, device_serial=self._device_serial)
+
+  @property
+  def is_emulator(self):
+    return _EMULATOR_RE.match(self._device_serial)
+
+  @property
+  def is_ready(self):
+    try:
+      return self.GetState() == _READY_STATE
+    except device_errors.CommandFailedError:
+      return False
+
diff --git a/build/android/pylib/device/adb_wrapper_test.py b/build/android/pylib/device/adb_wrapper_test.py
index 52ba2e3..5fc9eb6 100644
--- a/build/android/pylib/device/adb_wrapper_test.py
+++ b/build/android/pylib/device/adb_wrapper_test.py
@@ -16,7 +16,7 @@
 class TestAdbWrapper(unittest.TestCase):
 
   def setUp(self):
-    devices = adb_wrapper.AdbWrapper.GetDevices()
+    devices = adb_wrapper.AdbWrapper.Devices()
     assert devices, 'A device must be attached'
     self._adb = devices[0]
     self._adb.WaitForDevice()
diff --git a/build/android/pylib/device/battery_utils.py b/build/android/pylib/device/battery_utils.py
new file mode 100644
index 0000000..cca2cf9
--- /dev/null
+++ b/build/android/pylib/device/battery_utils.py
@@ -0,0 +1,386 @@
+# 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.
+
+"""Provides a variety of device interactions with power.
+"""
+# pylint: disable=unused-argument
+
+import collections
+import contextlib
+import csv
+import logging
+
+from pylib import constants
+from pylib.device import decorators
+from pylib.device import device_errors
+from pylib.device import device_utils
+from pylib.utils import timeout_retry
+
+_DEFAULT_TIMEOUT = 30
+_DEFAULT_RETRIES = 3
+
+_CONTROL_CHARGING_COMMANDS = [
+  {
+    # Nexus 4
+    'witness_file': '/sys/module/pm8921_charger/parameters/disabled',
+    'enable_command': 'echo 0 > /sys/module/pm8921_charger/parameters/disabled',
+    'disable_command':
+        'echo 1 > /sys/module/pm8921_charger/parameters/disabled',
+  },
+  {
+    # Nexus 5
+    # Setting the HIZ bit of the bq24192 causes the charger to actually ignore
+    # energy coming from USB. Setting the power_supply offline just updates the
+    # Android system to reflect that.
+    'witness_file': '/sys/kernel/debug/bq24192/INPUT_SRC_CONT',
+    'enable_command': (
+        'echo 0x4A > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
+        'echo 1 > /sys/class/power_supply/usb/online'),
+    'disable_command': (
+        'echo 0xCA > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
+        'chmod 644 /sys/class/power_supply/usb/online && '
+        'echo 0 > /sys/class/power_supply/usb/online'),
+  },
+]
+
+# The list of useful dumpsys columns.
+# Index of the column containing the format version.
+_DUMP_VERSION_INDEX = 0
+# Index of the column containing the type of the row.
+_ROW_TYPE_INDEX = 3
+# Index of the column containing the uid.
+_PACKAGE_UID_INDEX = 4
+# Index of the column containing the application package.
+_PACKAGE_NAME_INDEX = 5
+# The column containing the uid of the power data.
+_PWI_UID_INDEX = 1
+# The column containing the type of consumption. Only consumtion since last
+# charge are of interest here.
+_PWI_AGGREGATION_INDEX = 2
+# The column containing the amount of power used, in mah.
+_PWI_POWER_CONSUMPTION_INDEX = 5
+
+
+class BatteryUtils(object):
+
+  def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
+               default_retries=_DEFAULT_RETRIES):
+    """BatteryUtils constructor.
+
+      Args:
+        device: A DeviceUtils instance.
+        default_timeout: An integer containing the default number of seconds to
+                         wait for an operation to complete if no explicit value
+                         is provided.
+        default_retries: An integer containing the default number or times an
+                         operation should be retried on failure if no explicit
+                         value is provided.
+
+      Raises:
+        TypeError: If it is not passed a DeviceUtils instance.
+    """
+    if not isinstance(device, device_utils.DeviceUtils):
+      raise TypeError('Must be initialized with DeviceUtils object.')
+    self._device = device
+    self._cache = device.GetClientCache(self.__class__.__name__)
+    self._default_timeout = default_timeout
+    self._default_retries = default_retries
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetNetworkData(self, package, timeout=None, retries=None):
+    """ Get network data for specific package.
+
+    Args:
+      package: package name you want network data for.
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Returns:
+      Tuple of (sent_data, recieved_data)
+      None if no network data found
+    """
+    # If device_utils clears cache, cache['uids'] doesn't exist
+    if 'uids' not in self._cache:
+      self._cache['uids'] = {}
+    if package not in self._cache['uids']:
+      self.GetPowerData()
+      if package not in self._cache['uids']:
+        logging.warning('No UID found for %s. Can\'t get network data.',
+                        package)
+        return None
+
+    network_data_path = '/proc/uid_stat/%s/' % self._cache['uids'][package]
+    try:
+      send_data = int(self._device.ReadFile(network_data_path + 'tcp_snd'))
+    # If ReadFile throws exception, it means no network data usage file for
+    # package has been recorded. Return 0 sent and 0 received.
+    except device_errors.AdbShellCommandFailedError:
+      logging.warning('No sent data found for package %s', package)
+      send_data = 0
+    try:
+      recv_data = int(self._device.ReadFile(network_data_path + 'tcp_rcv'))
+    except device_errors.AdbShellCommandFailedError:
+      logging.warning('No received data found for package %s', package)
+      recv_data = 0
+    return (send_data, recv_data)
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetPowerData(self, timeout=None, retries=None):
+    """ Get power data for device.
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Returns:
+      Dict of power data, keyed on package names.
+      {
+        package_name: {
+          'uid': uid,
+          'data': [1,2,3]
+        },
+      }
+    """
+    if 'uids' not in self._cache:
+      self._cache['uids'] = {}
+    dumpsys_output = self._device.RunShellCommand(
+        ['dumpsys', 'batterystats', '-c'], check_return=True)
+    csvreader = csv.reader(dumpsys_output)
+    pwi_entries = collections.defaultdict(list)
+    for entry in csvreader:
+      if entry[_DUMP_VERSION_INDEX] not in ['8', '9']:
+        # Wrong dumpsys version.
+        raise device_errors.DeviceVersionError(
+            'Dumpsys version must be 8 or 9. %s found.'
+            % entry[_DUMP_VERSION_INDEX])
+      if _ROW_TYPE_INDEX < len(entry) and entry[_ROW_TYPE_INDEX] == 'uid':
+        current_package = entry[_PACKAGE_NAME_INDEX]
+        if (self._cache['uids'].get(current_package)
+            and self._cache['uids'].get(current_package)
+            != entry[_PACKAGE_UID_INDEX]):
+          raise device_errors.CommandFailedError(
+              'Package %s found multiple times with differnt UIDs %s and %s'
+               % (current_package, self._cache['uids'][current_package],
+               entry[_PACKAGE_UID_INDEX]))
+        self._cache['uids'][current_package] = entry[_PACKAGE_UID_INDEX]
+      elif (_PWI_POWER_CONSUMPTION_INDEX < len(entry)
+          and entry[_ROW_TYPE_INDEX] == 'pwi'
+          and entry[_PWI_AGGREGATION_INDEX] == 'l'):
+        pwi_entries[entry[_PWI_UID_INDEX]].append(
+            float(entry[_PWI_POWER_CONSUMPTION_INDEX]))
+
+    return {p: {'uid': uid, 'data': pwi_entries[uid]}
+            for p, uid in self._cache['uids'].iteritems()}
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetPackagePowerData(self, package, timeout=None, retries=None):
+    """ Get power data for particular package.
+
+    Args:
+      package: Package to get power data on.
+
+    returns:
+      Dict of UID and power data.
+      {
+        'uid': uid,
+        'data': [1,2,3]
+      }
+      None if the package is not found in the power data.
+    """
+    return self.GetPowerData().get(package)
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetBatteryInfo(self, timeout=None, retries=None):
+    """Gets battery info for the device.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+    Returns:
+      A dict containing various battery information as reported by dumpsys
+      battery.
+    """
+    result = {}
+    # Skip the first line, which is just a header.
+    for line in self._device.RunShellCommand(
+        ['dumpsys', 'battery'], check_return=True)[1:]:
+      # If usb charging has been disabled, an extra line of header exists.
+      if 'UPDATES STOPPED' in line:
+        logging.warning('Dumpsys battery not receiving updates. '
+                        'Run dumpsys battery reset if this is in error.')
+      elif ':' not in line:
+        logging.warning('Unknown line found in dumpsys battery: "%s"', line)
+      else:
+        k, v = line.split(':', 1)
+        result[k.strip()] = v.strip()
+    return result
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetCharging(self, timeout=None, retries=None):
+    """Gets the charging state of the device.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+    Returns:
+      True if the device is charging, false otherwise.
+    """
+    battery_info = self.GetBatteryInfo()
+    for k in ('AC powered', 'USB powered', 'Wireless powered'):
+      if (k in battery_info and
+          battery_info[k].lower() in ('true', '1', 'yes')):
+        return True
+    return False
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def SetCharging(self, enabled, timeout=None, retries=None):
+    """Enables or disables charging on the device.
+
+    Args:
+      enabled: A boolean indicating whether charging should be enabled or
+        disabled.
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.CommandFailedError: If method of disabling charging cannot
+        be determined.
+    """
+    if 'charging_config' not in self._cache:
+      for c in _CONTROL_CHARGING_COMMANDS:
+        if self._device.FileExists(c['witness_file']):
+          self._cache['charging_config'] = c
+          break
+      else:
+        raise device_errors.CommandFailedError(
+            'Unable to find charging commands.')
+
+    if enabled:
+      command = self._cache['charging_config']['enable_command']
+    else:
+      command = self._cache['charging_config']['disable_command']
+
+    def set_and_verify_charging():
+      self._device.RunShellCommand(command, check_return=True)
+      return self.GetCharging() == enabled
+
+    timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
+
+  # TODO(rnephew): Make private when all use cases can use the context manager.
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def DisableBatteryUpdates(self, timeout=None, retries=None):
+    """ Resets battery data and makes device appear like it is not
+    charging so that it will collect power data since last charge.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.CommandFailedError: When resetting batterystats fails to
+        reset power values.
+      device_errors.DeviceVersionError: If device is not L or higher.
+    """
+    def battery_updates_disabled():
+      return self.GetCharging() is False
+
+    if (self._device.build_version_sdk <
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+      raise device_errors.DeviceVersionError('Device must be L or higher.')
+
+    self._device.RunShellCommand(
+        ['dumpsys', 'battery', 'reset'], check_return=True)
+    self._device.RunShellCommand(
+        ['dumpsys', 'batterystats', '--reset'], check_return=True)
+    battery_data = self._device.RunShellCommand(
+        ['dumpsys', 'batterystats', '--charged', '--checkin'],
+        check_return=True)
+    ROW_TYPE_INDEX = 3
+    PWI_POWER_INDEX = 5
+    for line in battery_data:
+      l = line.split(',')
+      if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
+          and l[PWI_POWER_INDEX] != 0):
+        raise device_errors.CommandFailedError(
+            'Non-zero pmi value found after reset.')
+    self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '0'],
+                                 check_return=True)
+    self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
+                                 check_return=True)
+    timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
+
+  # TODO(rnephew): Make private when all use cases can use the context manager.
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def EnableBatteryUpdates(self, timeout=None, retries=None):
+    """ Restarts device charging so that dumpsys no longer collects power data.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.DeviceVersionError: If device is not L or higher.
+    """
+    def battery_updates_enabled():
+      return self.GetCharging() is True
+
+    if (self._device.build_version_sdk <
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+      raise device_errors.DeviceVersionError('Device must be L or higher.')
+
+    self._device.RunShellCommand(['dumpsys', 'battery', 'reset'],
+                                 check_return=True)
+    timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
+
+  @contextlib.contextmanager
+  def BatteryMeasurement(self, timeout=None, retries=None):
+    """Context manager that enables battery data collection. It makes
+    the device appear to stop charging so that dumpsys will start collecting
+    power data since last charge. Once the with block is exited, charging is
+    resumed and power data since last charge is no longer collected.
+
+    Only for devices L and higher.
+
+    Example usage:
+      with BatteryMeasurement():
+        browser_actions()
+        get_power_data() # report usage within this block
+      after_measurements() # Anything that runs after power
+                           # measurements are collected
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.DeviceVersionError: If device is not L or higher.
+    """
+    if (self._device.build_version_sdk <
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+      raise device_errors.DeviceVersionError('Device must be L or higher.')
+    try:
+      self.DisableBatteryUpdates(timeout=timeout, retries=retries)
+      yield
+    finally:
+      self.EnableBatteryUpdates(timeout=timeout, retries=retries)
+
+  def ChargeDeviceToLevel(self, level, wait_period=60):
+    """Enables charging and waits for device to be charged to given level.
+
+    Args:
+      level: level of charge to wait for.
+      wait_period: time in seconds to wait between checking.
+    """
+    self.SetCharging(True)
+
+    def device_charged():
+      battery_level = self.GetBatteryInfo().get('level')
+      if battery_level is None:
+        logging.warning('Unable to find current battery level.')
+        battery_level = 100
+      else:
+        logging.info('current battery level: %s', battery_level)
+        battery_level = int(battery_level)
+      return battery_level >= level
+
+    timeout_retry.WaitFor(device_charged, wait_period=wait_period)
diff --git a/build/android/pylib/device/battery_utils_test.py b/build/android/pylib/device/battery_utils_test.py
new file mode 100755
index 0000000..15b4c34
--- /dev/null
+++ b/build/android/pylib/device/battery_utils_test.py
@@ -0,0 +1,316 @@
+#!/usr/bin/env python
+# 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.
+
+"""
+Unit tests for the contents of battery_utils.py
+"""
+
+# pylint: disable=W0613
+
+import logging
+import os
+import sys
+import unittest
+
+from pylib import android_commands
+from pylib import constants
+from pylib.device import battery_utils
+from pylib.device import device_errors
+from pylib.device import device_utils
+from pylib.device import device_utils_test
+from pylib.utils import mock_calls
+
+# RunCommand from third_party/android_testrunner/run_command.py is mocked
+# below, so its path needs to be in sys.path.
+sys.path.append(os.path.join(
+    constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner'))
+
+sys.path.append(os.path.join(
+    constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
+import mock # pylint: disable=F0401
+
+_DUMPSYS_OUTPUT = [
+    '9,0,i,uid,1000,test_package1',
+    '9,0,i,uid,1001,test_package2',
+    '9,1000,l,pwi,uid,1',
+    '9,1001,l,pwi,uid,2'
+]
+
+
+class BatteryUtilsTest(mock_calls.TestCase):
+
+  def ShellError(self, output=None, status=1):
+    def action(cmd, *args, **kwargs):
+      raise device_errors.AdbShellCommandFailedError(
+          cmd, output, status, str(self.device))
+    if output is None:
+      output = 'Permission denied\n'
+    return action
+
+  def setUp(self):
+    self.adb = device_utils_test._AdbWrapperMock('0123456789abcdef')
+    self.device = device_utils.DeviceUtils(
+        self.adb, default_timeout=10, default_retries=0)
+    self.watchMethodCalls(self.call.adb, ignore=['GetDeviceSerial'])
+    self.battery = battery_utils.BatteryUtils(
+        self.device, default_timeout=10, default_retries=0)
+
+
+class BatteryUtilsInitTest(unittest.TestCase):
+
+  def testInitWithDeviceUtil(self):
+    serial = '0fedcba987654321'
+    a = android_commands.AndroidCommands(device=serial)
+    d = device_utils.DeviceUtils(a)
+    b = battery_utils.BatteryUtils(d)
+    self.assertEqual(d, b._device)
+
+  def testInitWithMissing_fails(self):
+    with self.assertRaises(TypeError):
+      battery_utils.BatteryUtils(None)
+    with self.assertRaises(TypeError):
+      battery_utils.BatteryUtils('')
+
+
+class BatteryUtilsSetChargingTest(BatteryUtilsTest):
+
+  @mock.patch('time.sleep', mock.Mock())
+  def testSetCharging_enabled(self):
+    with self.assertCalls(
+        (self.call.device.FileExists(mock.ANY), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), False),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), True)):
+      self.battery.SetCharging(True)
+
+  def testSetCharging_alreadyEnabled(self):
+    with self.assertCalls(
+        (self.call.device.FileExists(mock.ANY), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), True)):
+      self.battery.SetCharging(True)
+
+  @mock.patch('time.sleep', mock.Mock())
+  def testSetCharging_disabled(self):
+    with self.assertCalls(
+        (self.call.device.FileExists(mock.ANY), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), False)):
+      self.battery.SetCharging(False)
+
+
+class BatteryUtilsSetBatteryMeasurementTest(BatteryUtilsTest):
+
+  def testBatteryMeasurement(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            mock.ANY, retries=0, single_line=True,
+            timeout=10, check_return=True), '22'),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'reset'], check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '--charged', '--checkin'],
+            check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
+        (self.call.battery.GetCharging(), False),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'reset'], check_return=True), []),
+        (self.call.battery.GetCharging(), True)):
+      with self.battery.BatteryMeasurement():
+        pass
+
+
+class BatteryUtilsGetPowerData(BatteryUtilsTest):
+
+  def testGetPowerData(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      data = self.battery.GetPowerData()
+      check = {
+          'test_package1': {'uid': '1000', 'data': [1.0]},
+          'test_package2': {'uid': '1001', 'data': [2.0]}
+      }
+      self.assertEqual(data, check)
+
+  def testGetPowerData_packageCollisionSame(self):
+      self.battery._cache['uids'] = {'test_package1': '1000'}
+      with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT):
+        data = self.battery.GetPowerData()
+        check = {
+            'test_package1': {'uid': '1000', 'data': [1.0]},
+            'test_package2': {'uid': '1001', 'data': [2.0]}
+        }
+        self.assertEqual(data, check)
+
+  def testGetPowerData_packageCollisionDifferent(self):
+      self.battery._cache['uids'] = {'test_package1': '1'}
+      with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT):
+        with self.assertRaises(device_errors.CommandFailedError):
+          self.battery.GetPowerData()
+
+  def testGetPowerData_cacheCleared(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      self.battery._cache.clear()
+      data = self.battery.GetPowerData()
+      check = {
+          'test_package1': {'uid': '1000', 'data': [1.0]},
+          'test_package2': {'uid': '1001', 'data': [2.0]}
+      }
+      self.assertEqual(data, check)
+
+  def testGetPackagePowerData(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      data = self.battery.GetPackagePowerData('test_package2')
+      self.assertEqual(data, {'uid': '1001', 'data': [2.0]})
+
+  def testGetPackagePowerData_badPackage(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      data = self.battery.GetPackagePowerData('not_a_package')
+      self.assertEqual(data, None)
+
+
+class BatteryUtilsChargeDevice(BatteryUtilsTest):
+
+  @mock.patch('time.sleep', mock.Mock())
+  def testChargeDeviceToLevel(self):
+    with self.assertCalls(
+        (self.call.battery.SetCharging(True)),
+        (self.call.battery.GetBatteryInfo(), {'level': '50'}),
+        (self.call.battery.GetBatteryInfo(), {'level': '100'})):
+      self.battery.ChargeDeviceToLevel(95)
+
+
+class DeviceUtilsGetBatteryInfoTest(BatteryUtilsTest):
+
+  def testGetBatteryInfo_normal(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'battery'], check_return=True),
+        [
+          'Current Battery Service state:',
+          '  AC powered: false',
+          '  USB powered: true',
+          '  level: 100',
+          '  temperature: 321',
+        ]):
+      self.assertEquals(
+          {
+            'AC powered': 'false',
+            'USB powered': 'true',
+            'level': '100',
+            'temperature': '321',
+          },
+          self.battery.GetBatteryInfo())
+
+  def testGetBatteryInfo_nothing(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'battery'], check_return=True), []):
+      self.assertEquals({}, self.battery.GetBatteryInfo())
+
+
+class DeviceUtilsGetChargingTest(BatteryUtilsTest):
+
+  def testGetCharging_usb(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'USB powered': 'true'}):
+      self.assertTrue(self.battery.GetCharging())
+
+  def testGetCharging_usbFalse(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'USB powered': 'false'}):
+      self.assertFalse(self.battery.GetCharging())
+
+  def testGetCharging_ac(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'AC powered': 'true'}):
+      self.assertTrue(self.battery.GetCharging())
+
+  def testGetCharging_wireless(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'Wireless powered': 'true'}):
+      self.assertTrue(self.battery.GetCharging())
+
+  def testGetCharging_unknown(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'level': '42'}):
+      self.assertFalse(self.battery.GetCharging())
+
+
+class DeviceUtilsGetNetworkDataTest(BatteryUtilsTest):
+
+  def testGetNetworkData_noDataUsage(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'),
+            self.ShellError()),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'),
+            self.ShellError())):
+      self.assertEquals(self.battery.GetNetworkData('test_package1'), (0, 0))
+
+  def testGetNetworkData_badPackage(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT):
+      self.assertEqual(self.battery.GetNetworkData('asdf'), None)
+
+  def testGetNetworkData_packageNotCached(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+      self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+  def testGetNetworkData_packageCached(self):
+    self.battery._cache['uids'] = {'test_package1': '1000'}
+    with self.assertCalls(
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+      self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+  def testGetNetworkData_clearedCache(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+      self.battery._cache.clear()
+      self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+
+if __name__ == '__main__':
+  logging.getLogger().setLevel(logging.DEBUG)
+  unittest.main(verbosity=2)
diff --git a/build/android/pylib/device/decorators.py b/build/android/pylib/device/decorators.py
index 074a0fc..73c13da 100644
--- a/build/android/pylib/device/decorators.py
+++ b/build/android/pylib/device/decorators.py
@@ -11,6 +11,7 @@
 import sys
 import threading
 
+from pylib import cmd_helper
 from pylib import constants
 from pylib.device import device_errors
 from pylib.utils import reraiser_thread
@@ -56,13 +57,16 @@
         return timeout_retry.Run(impl, timeout, retries)
     except old_errors.WaitForResponseTimedOutError as e:
       raise device_errors.CommandTimeoutError(str(e)), None, (
-             sys.exc_info()[2])
+          sys.exc_info()[2])
     except old_errors.DeviceUnresponsiveError as e:
       raise device_errors.DeviceUnreachableError(str(e)), None, (
-             sys.exc_info()[2])
+          sys.exc_info()[2])
     except reraiser_thread.TimeoutError as e:
       raise device_errors.CommandTimeoutError(str(e)), None, (
-             sys.exc_info()[2])
+          sys.exc_info()[2])
+    except cmd_helper.TimeoutError as e:
+      raise device_errors.CommandTimeoutError(str(e)), None, (
+          sys.exc_info()[2])
   return TimeoutRetryWrapper
 
 
diff --git a/build/android/pylib/device/device_errors.py b/build/android/pylib/device/device_errors.py
index 26d9eaf..e94968f 100644
--- a/build/android/pylib/device/device_errors.py
+++ b/build/android/pylib/device/device_errors.py
@@ -42,6 +42,13 @@
     super(AdbCommandFailedError, self).__init__(message, device_serial)
 
 
+class DeviceVersionError(CommandFailedError):
+  """Exception for device version failures."""
+
+  def __init__(self, message, device_serial=None):
+    super(DeviceVersionError, self).__init__(message, device_serial)
+
+
 class AdbShellCommandFailedError(AdbCommandFailedError):
   """Exception for shell command failures run via adb."""
 
@@ -52,7 +59,11 @@
     message.append('  exit status: %s\n' % status)
     if output:
       message.append('  output:\n')
-      message.extend('  - %s\n' % line for line in output.splitlines())
+      if isinstance(output, basestring):
+        output_lines = output.splitlines()
+      else:
+        output_lines = output
+      message.extend('  - %s\n' % line for line in output_lines)
     else:
       message.append("  output: ''\n")
     message = ''.join(message)
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 9f538e1..46aec6f 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -25,8 +25,10 @@
 import pylib.android_commands
 from pylib import cmd_helper
 from pylib import constants
+from pylib import device_signal
 from pylib.device import adb_wrapper
 from pylib.device import decorators
+from pylib.device import device_blacklist
 from pylib.device import device_errors
 from pylib.device import intent
 from pylib.device import logcat_monitor
@@ -72,6 +74,7 @@
   },
 ]
 
+
 @decorators.WithExplicitTimeoutAndRetries(
     _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
 def GetAVDs():
@@ -168,6 +171,7 @@
     self._default_timeout = default_timeout
     self._default_retries = default_retries
     self._cache = {}
+    self._client_caches = {}
     assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)
     assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR)
 
@@ -406,7 +410,7 @@
       return not self.IsOnline()
 
     self.adb.Reboot()
-    self._cache = {}
+    self._ClearCache()
     timeout_retry.WaitFor(device_offline, wait_period=1)
     if block:
       self.WaitUntilFullyBooted(wifi=wifi)
@@ -446,8 +450,8 @@
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None,
-                      as_root=False, single_line=False, timeout=None,
-                      retries=None):
+                      as_root=False, single_line=False, large_output=False,
+                      timeout=None, retries=None):
     """Run an ADB shell command.
 
     The command to run |cmd| should be a sequence of program arguments or else
@@ -480,6 +484,8 @@
         with root privileges.
       single_line: A boolean indicating if only a single line of output is
         expected.
+      large_output: Uses a work-around for large shell command output. Without
+        this large output will be truncated.
       timeout: timeout in seconds
       retries: number of retries
 
@@ -502,15 +508,49 @@
       # using double quotes here to allow interpolation of shell variables
       return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
 
-    def do_run(cmd):
+    def run(cmd):
+      return self.adb.Shell(cmd)
+
+    def handle_check_return(cmd):
       try:
-        return self.adb.Shell(cmd)
+        return run(cmd)
       except device_errors.AdbCommandFailedError as exc:
         if check_return:
           raise
         else:
           return exc.output
 
+    def handle_large_command(cmd):
+      if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
+        return handle_check_return(cmd)
+      else:
+        with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
+          self._WriteFileWithPush(script.name, cmd)
+          logging.info('Large shell command will be run from file: %s ...',
+                       cmd[:100])
+          return handle_check_return('sh %s' % script.name_quoted)
+
+    def handle_large_output(cmd, large_output_mode):
+      if large_output_mode:
+        with device_temp_file.DeviceTempFile(self.adb) as large_output_file:
+          cmd = '%s > %s' % (cmd, large_output_file.name)
+          logging.info('Large output mode enabled. Will write output to device '
+                       ' and read results from file.')
+          handle_large_command(cmd)
+          return self.ReadFile(large_output_file.name)
+      else:
+        try:
+          return handle_large_command(cmd)
+        except device_errors.AdbCommandFailedError as exc:
+          if exc.status is None:
+            logging.exception('No output found for %s', cmd)
+            logging.warning('Attempting to run in large_output mode.')
+            logging.warning('Use RunShellCommand(..., large_output=True) for '
+                            'shell commands that expect a lot of output.')
+            return handle_large_output(cmd, True)
+          else:
+            raise
+
     if not isinstance(cmd, basestring):
       cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
     if env:
@@ -521,19 +561,9 @@
     if as_root and self.NeedsSU():
       # "su -c sh -c" allows using shell features in |cmd|
       cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
-    if timeout is None:
-      timeout = self._default_timeout
 
-    if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
-      output = do_run(cmd)
-    else:
-      with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
-        self._WriteFileWithPush(script.name, cmd)
-        logging.info('Large shell command will be run from file: %s ...',
-                     cmd[:100])
-        output = do_run('sh %s' % script.name_quoted)
+    output = handle_large_output(cmd, large_output).splitlines()
 
-    output = output.splitlines()
     if single_line:
       if not output:
         return ''
@@ -545,38 +575,70 @@
     else:
       return output
 
+  def _RunPipedShellCommand(self, script, **kwargs):
+    PIPESTATUS_LEADER = 'PIPESTATUS: '
+
+    script += '; echo "%s${PIPESTATUS[@]}"' % PIPESTATUS_LEADER
+    kwargs['check_return'] = True
+    output = self.RunShellCommand(script, **kwargs)
+    pipestatus_line = output[-1]
+
+    if not pipestatus_line.startswith(PIPESTATUS_LEADER):
+      logging.error('Pipe exit statuses of shell script missing.')
+      raise device_errors.AdbShellCommandFailedError(
+          script, output, status=None,
+          device_serial=self.adb.GetDeviceSerial())
+
+    output = output[:-1]
+    statuses = [
+        int(s) for s in pipestatus_line[len(PIPESTATUS_LEADER):].split()]
+    if any(statuses):
+      raise device_errors.AdbShellCommandFailedError(
+          script, output, status=statuses,
+          device_serial=self.adb.GetDeviceSerial())
+    return output
+
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
-              timeout=None, retries=None):
+  def KillAll(self, process_name, signum=device_signal.SIGKILL, as_root=False,
+              blocking=False, quiet=False, timeout=None, retries=None):
     """Kill all processes with the given name on the device.
 
     Args:
       process_name: A string containing the name of the process to kill.
       signum: An integer containing the signal number to send to kill. Defaults
-              to 9 (SIGKILL).
+              to SIGKILL (9).
       as_root: A boolean indicating whether the kill should be executed with
                root privileges.
       blocking: A boolean indicating whether we should wait until all processes
                 with the given |process_name| are dead.
+      quiet: A boolean indicating whether to ignore the fact that no processes
+             to kill were found.
       timeout: timeout in seconds
       retries: number of retries
 
+    Returns:
+      The number of processes attempted to kill.
+
     Raises:
-      CommandFailedError if no process was killed.
+      CommandFailedError if no process was killed and |quiet| is False.
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    pids = self._GetPidsImpl(process_name)
+    pids = self.GetPids(process_name)
     if not pids:
-      raise device_errors.CommandFailedError(
-          'No process "%s"' % process_name, str(self))
+      if quiet:
+        return 0
+      else:
+        raise device_errors.CommandFailedError(
+            'No process "%s"' % process_name, str(self))
 
     cmd = ['kill', '-%d' % signum] + pids.values()
     self.RunShellCommand(cmd, as_root=as_root, check_return=True)
 
     if blocking:
+      # TODO(perezu): use timeout_retry.WaitFor
       wait_period = 0.1
-      while self._GetPidsImpl(process_name):
+      while self.GetPids(process_name):
         time.sleep(wait_period)
 
     return len(pids)
@@ -791,29 +853,27 @@
     if not real_device_path:
       return [(host_path, device_path)]
 
-    host_hash_tuples = md5sum.CalculateHostMd5Sums([real_host_path])
+    host_checksums = md5sum.CalculateHostMd5Sums([real_host_path])
     device_paths_to_md5 = (
         real_device_path if os.path.isfile(real_host_path)
         else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path))
-              for _, p in host_hash_tuples))
-    device_hash_tuples = md5sum.CalculateDeviceMd5Sums(
+              for p in host_checksums.iterkeys()))
+    device_checksums = md5sum.CalculateDeviceMd5Sums(
         device_paths_to_md5, self)
 
     if os.path.isfile(host_path):
-      if (not device_hash_tuples
-          or device_hash_tuples[0].hash != host_hash_tuples[0].hash):
+      host_checksum = host_checksums.get(real_host_path)
+      device_checksum = device_checksums.get(real_device_path)
+      if host_checksum != device_checksum:
         return [(host_path, device_path)]
       else:
         return []
     else:
-      device_tuple_dict = dict((d.path, d.hash) for d in device_hash_tuples)
       to_push = []
-      for host_hash, host_abs_path in (
-          (h.hash, h.path) for h in host_hash_tuples):
+      for host_abs_path, host_checksum in host_checksums.iteritems():
         device_abs_path = '%s/%s' % (
             real_device_path, os.path.relpath(host_abs_path, real_host_path))
-        if (device_abs_path not in device_tuple_dict
-            or device_tuple_dict[device_abs_path] != host_hash):
+        if (device_checksums.get(device_abs_path) != host_checksum):
           to_push.append((host_abs_path, device_abs_path))
       return to_push
 
@@ -991,7 +1051,7 @@
     else:
       logging.warning('Could not determine size of %s.', device_path)
 
-    if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH:
+    if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH:
       return _JoinLines(self.RunShellCommand(
           ['cat', device_path], as_root=as_root, check_return=True))
     elif as_root and self.NeedsSU():
@@ -1326,11 +1386,19 @@
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    return self._GetPidsImpl(process_name)
-
-  def _GetPidsImpl(self, process_name):
     procs_pids = {}
-    for line in self.RunShellCommand('ps', check_return=True):
+    try:
+      ps_output = self._RunPipedShellCommand(
+          'ps | grep -F %s' % cmd_helper.SingleQuote(process_name))
+    except device_errors.AdbShellCommandFailedError as e:
+      if e.status and isinstance(e.status, list) and not e.status[0]:
+        # If ps succeeded but grep failed, there were no processes with the
+        # given name.
+        return procs_pids
+      else:
+        raise
+
+    for line in ps_output:
       try:
         ps_data = line.split()
         if process_name in ps_data[-1]:
@@ -1402,10 +1470,8 @@
         'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean',
         'Private_Dirty')
 
-    showmap_out = self.RunShellCommand(
-        ['showmap', str(pid)], as_root=True, check_return=True)
-    if not showmap_out:
-      raise device_errors.CommandFailedError('No output from showmap')
+    showmap_out = self._RunPipedShellCommand(
+        'showmap %d | grep TOTAL' % int(pid), as_root=True)
 
     split_totals = showmap_out[-1].split()
     if (not split_totals
@@ -1439,155 +1505,6 @@
     return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def GetBatteryInfo(self, timeout=None, retries=None):
-    """Gets battery info for the device.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    Returns:
-      A dict containing various battery information as reported by dumpsys
-      battery.
-    """
-    result = {}
-    # Skip the first line, which is just a header.
-    for line in self.RunShellCommand(
-        ['dumpsys', 'battery'], check_return=True)[1:]:
-      # If usb charging has been disabled, an extra line of header exists.
-      if 'UPDATES STOPPED' in line:
-        logging.warning('Dumpsys battery not receiving updates. '
-                        'Run dumpsys battery reset if this is in error.')
-      elif ':' not in line:
-        logging.warning('Unknown line found in dumpsys battery.')
-        logging.warning(line)
-      else:
-        k, v = line.split(': ', 1)
-        result[k.strip()] = v.strip()
-    return result
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def GetCharging(self, timeout=None, retries=None):
-    """Gets the charging state of the device.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    Returns:
-      True if the device is charging, false otherwise.
-    """
-    battery_info = self.GetBatteryInfo()
-    for k in ('AC powered', 'USB powered', 'Wireless powered'):
-      if (k in battery_info and
-          battery_info[k].lower() in ('true', '1', 'yes')):
-        return True
-    return False
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def SetCharging(self, enabled, timeout=None, retries=None):
-    """Enables or disables charging on the device.
-
-    Args:
-      enabled: A boolean indicating whether charging should be enabled or
-        disabled.
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    if 'charging_config' not in self._cache:
-      for c in _CONTROL_CHARGING_COMMANDS:
-        if self.FileExists(c['witness_file']):
-          self._cache['charging_config'] = c
-          break
-      else:
-        raise device_errors.CommandFailedError(
-            'Unable to find charging commands.')
-
-    if enabled:
-      command = self._cache['charging_config']['enable_command']
-    else:
-      command = self._cache['charging_config']['disable_command']
-
-    def set_and_verify_charging():
-      self.RunShellCommand(command, check_return=True)
-      return self.GetCharging() == enabled
-
-    timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
-
-  # TODO(rnephew): Make private when all use cases can use the context manager.
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def DisableBatteryUpdates(self, timeout=None, retries=None):
-    """ Resets battery data and makes device appear like it is not
-    charging so that it will collect power data since last charge.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    def battery_updates_disabled():
-      return self.GetCharging() is False
-
-    self.RunShellCommand(
-        ['dumpsys', 'batterystats', '--reset'], check_return=True)
-    battery_data = self.RunShellCommand(
-        ['dumpsys', 'batterystats', '--charged', '--checkin'],
-        check_return=True)
-    ROW_TYPE_INDEX = 3
-    PWI_POWER_INDEX = 5
-    for line in battery_data:
-      l = line.split(',')
-      if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
-          and l[PWI_POWER_INDEX] != 0):
-        raise device_errors.CommandFailedError(
-            'Non-zero pmi value found after reset.')
-    self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
-                         check_return=True)
-    timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
-
-  # TODO(rnephew): Make private when all use cases can use the context manager.
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def EnableBatteryUpdates(self, timeout=None, retries=None):
-    """ Restarts device charging so that dumpsys no longer collects power data.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    def battery_updates_enabled():
-      return self.GetCharging() is True
-
-    self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'],
-                         check_return=True)
-    self.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True)
-    timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
-
-  @contextlib.contextmanager
-  def BatteryMeasurement(self, timeout=None, retries=None):
-    """Context manager that enables battery data collection. It makes
-    the device appear to stop charging so that dumpsys will start collecting
-    power data since last charge. Once the with block is exited, charging is
-    resumed and power data since last charge is no longer collected.
-
-    Only for devices L and higher.
-
-    Example usage:
-      with BatteryMeasurement():
-        browser_actions()
-        get_power_data() # report usage within this block
-      after_measurements() # Anything that runs after power
-                           # measurements are collected
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    if self.build_version_sdk < constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP:
-      raise device_errors.CommandFailedError('Device must be L or higher.')
-    try:
-      self.DisableBatteryUpdates(timeout=timeout, retries=retries)
-      yield
-    finally:
-      self.EnableBatteryUpdates(timeout=timeout, retries=retries)
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
   def GetDevicePieWrapper(self, timeout=None, retries=None):
     """Gets the absolute path to the run_pie wrapper on the device.
 
@@ -1622,12 +1539,24 @@
 
     return self._cache['run_pie']
 
+  def GetClientCache(self, client_name):
+    """Returns client cache."""
+    if client_name not in self._client_caches:
+      self._client_caches[client_name] = {}
+    return self._client_caches[client_name]
+
+  def _ClearCache(self):
+    """Clears all caches."""
+    for client in self._client_caches:
+      self._client_caches[client].clear()
+    self._cache.clear()
+
   @classmethod
   def parallel(cls, devices=None, async=False):
     """Creates a Parallelizer to operate over the provided list of devices.
 
     If |devices| is either |None| or an empty list, the Parallelizer will
-    operate over all attached devices.
+    operate over all attached devices that have not been blacklisted.
 
     Args:
       devices: A list of either DeviceUtils instances or objects from
@@ -1640,11 +1569,25 @@
       A Parallelizer operating over |devices|.
     """
     if not devices:
-      devices = adb_wrapper.AdbWrapper.GetDevices()
+      devices = cls.HealthyDevices()
       if not devices:
         raise device_errors.NoDevicesError()
+
     devices = [d if isinstance(d, cls) else cls(d) for d in devices]
     if async:
       return parallelizer.Parallelizer(devices)
     else:
       return parallelizer.SyncParallelizer(devices)
+
+  @classmethod
+  def HealthyDevices(cls):
+    blacklist = device_blacklist.ReadBlacklist()
+    def blacklisted(adb):
+      if adb.GetDeviceSerial() in blacklist:
+        logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial())
+        return True
+      return False
+
+    return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices()
+            if not blacklisted(adb)]
+
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 98e3539..4301e9d 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -16,13 +16,13 @@
 import logging
 import os
 import re
-import signal
 import sys
 import unittest
 
 from pylib import android_commands
 from pylib import cmd_helper
 from pylib import constants
+from pylib import device_signal
 from pylib.device import adb_wrapper
 from pylib.device import device_errors
 from pylib.device import device_utils
@@ -114,6 +114,10 @@
   def __exit__(self, exc_type, exc_val, exc_tb):
     pass
 
+  @property
+  def name(self):
+    return self.file.name
+
 
 class _PatchedFunction(object):
   def __init__(self, patched=None, mocked=None):
@@ -582,6 +586,81 @@
       self.assertEquals([output.rstrip()],
                         self.device.RunShellCommand(cmd, check_return=False))
 
+  def testRunShellCommand_largeOutput_enabled(self):
+    cmd = 'echo $VALUE'
+    temp_file = MockTempFile('/sdcard/temp-123')
+    cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+    with self.assertCalls(
+        (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.adb),
+            temp_file),
+        (self.call.adb.Shell(cmd_redirect)),
+        (self.call.device.ReadFile(temp_file.name), 'something')):
+      self.assertEquals(
+          ['something'],
+          self.device.RunShellCommand(
+              cmd, large_output=True, check_return=True))
+
+  def testRunShellCommand_largeOutput_disabledNoTrigger(self):
+    cmd = 'something'
+    with self.assertCall(self.call.adb.Shell(cmd), self.ShellError('')):
+      with self.assertRaises(device_errors.AdbCommandFailedError):
+        self.device.RunShellCommand(cmd, check_return=True)
+
+  def testRunShellCommand_largeOutput_disabledTrigger(self):
+    cmd = 'echo $VALUE'
+    temp_file = MockTempFile('/sdcard/temp-123')
+    cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+    with self.assertCalls(
+        (self.call.adb.Shell(cmd), self.ShellError('', None)),
+        (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.adb),
+            temp_file),
+        (self.call.adb.Shell(cmd_redirect)),
+        (self.call.device.ReadFile(mock.ANY), 'something')):
+      self.assertEquals(['something'],
+                        self.device.RunShellCommand(cmd, check_return=True))
+
+
+class DeviceUtilsRunPipedShellCommandTest(DeviceUtilsTest):
+
+  def testRunPipedShellCommand_success(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['This line contains foo', 'PIPESTATUS: 0 0']):
+      self.assertEquals(['This line contains foo'],
+                        self.device._RunPipedShellCommand('ps | grep foo'))
+
+  def testRunPipedShellCommand_firstCommandFails(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['PIPESTATUS: 1 0']):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+        self.device._RunPipedShellCommand('ps | grep foo')
+      self.assertEquals([1, 0], ec.exception.status)
+
+  def testRunPipedShellCommand_secondCommandFails(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['PIPESTATUS: 0 1']):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+        self.device._RunPipedShellCommand('ps | grep foo')
+      self.assertEquals([0, 1], ec.exception.status)
+
+  def testRunPipedShellCommand_outputCutOff(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['foo.bar'] * 256 + ['foo.ba']):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+        self.device._RunPipedShellCommand('ps | grep foo')
+      self.assertIs(None, ec.exception.status)
+
 
 class DeviceUtilsGetDevicePieWrapper(DeviceUtilsTest):
 
@@ -604,53 +683,45 @@
 @mock.patch('time.sleep', mock.Mock())
 class DeviceUtilsKillAllTest(DeviceUtilsTest):
 
-  def testKillAll_noMatchingProcesses(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'):
+  def testKillAll_noMatchingProcessesFailure(self):
+    with self.assertCall(self.call.device.GetPids('test_process'), {}):
       with self.assertRaises(device_errors.CommandFailedError):
         self.device.KillAll('test_process')
 
+  def testKillAll_noMatchingProcessesQuiet(self):
+    with self.assertCall(self.call.device.GetPids('test_process'), {}):
+      self.assertEqual(0, self.device.KillAll('test_process', quiet=True))
+
   def testKillAll_nonblocking(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.adb.Shell('kill -9 1234'), '')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', blocking=False))
+      self.assertEquals(
+          1, self.device.KillAll('some.process', blocking=False))
 
   def testKillAll_blocking(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.adb.Shell('kill -9 1234'), ''),
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', blocking=True))
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
+        (self.call.device.GetPids('some.process'), [])):
+      self.assertEquals(
+          1, self.device.KillAll('some.process', blocking=True))
 
   def testKillAll_root(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.device.NeedsSU(), True),
         (self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', as_root=True))
+      self.assertEquals(
+          1, self.device.KillAll('some.process', as_root=True))
 
   def testKillAll_sigterm(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.adb.Shell('kill -15 1234'), '')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', signum=signal.SIGTERM))
+      self.assertEquals(
+          1, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
 
 
 class DeviceUtilsStartActivityTest(DeviceUtilsTest):
@@ -1078,7 +1149,8 @@
             as_root=False, check_return=True),
          ['-rw-rw---- root foo 256 1970-01-01 00:00 file']),
         (self.call.device.RunShellCommand(
-            ['cat', '/read/this/test/file'], as_root=False, check_return=True),
+            ['cat', '/read/this/test/file'],
+            as_root=False, check_return=True),
          ['this is a test file'])):
       self.assertEqual('this is a test file\n',
                        self.device.ReadFile('/read/this/test/file'))
@@ -1092,6 +1164,17 @@
       with self.assertRaises(device_errors.CommandFailedError):
         self.device.ReadFile('/this/file/does.not.exist')
 
+  def testReadFile_zeroSize(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['ls', '-l', '/this/file/has/zero/size'],
+            as_root=False, check_return=True),
+         ['-r--r--r-- root foo 0 1970-01-01 00:00 zero_size_file']),
+        (self.call.device._ReadFileWithPull('/this/file/has/zero/size'),
+         'but it has contents\n')):
+      self.assertEqual('but it has contents\n',
+                       self.device.ReadFile('/this/file/has/zero/size'))
+
   def testReadFile_withSU(self):
     with self.assertCalls(
         (self.call.device.RunShellCommand(
@@ -1350,38 +1433,43 @@
 class DeviceUtilsGetPidsTest(DeviceUtilsTest):
 
   def testGetPids_noMatches(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 no.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F does.not.match'),
+        []):
       self.assertEqual({}, self.device.GetPids('does.not.match'))
 
   def testGetPids_oneMatch(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 not.a.match\n'
-        'user  1001    100   1024 1024   ffffffff 00000000 one.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F one.match'),
+        ['user  1001    100   1024 1024   ffffffff 00000000 one.match']):
       self.assertEqual({'one.match': '1001'}, self.device.GetPids('one.match'))
 
   def testGetPids_mutlipleMatches(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 not\n'
-        'user  1001    100   1024 1024   ffffffff 00000000 one.match\n'
-        'user  1002    100   1024 1024   ffffffff 00000000 two.match\n'
-        'user  1003    100   1024 1024   ffffffff 00000000 three.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F match'),
+        ['user  1001    100   1024 1024   ffffffff 00000000 one.match',
+         'user  1002    100   1024 1024   ffffffff 00000000 two.match',
+         'user  1003    100   1024 1024   ffffffff 00000000 three.match']):
       self.assertEqual(
           {'one.match': '1001', 'two.match': '1002', 'three.match': '1003'},
           self.device.GetPids('match'))
 
   def testGetPids_exactMatch(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 not.exact.match\n'
-        'user  1234    100   1024 1024   ffffffff 00000000 exact.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F exact.match'),
+        ['user  1000    100   1024 1024   ffffffff 00000000 not.exact.match',
+         'user  1234    100   1024 1024   ffffffff 00000000 exact.match']):
       self.assertEqual(
           {'not.exact.match': '1000', 'exact.match': '1234'},
           self.device.GetPids('exact.match'))
 
+  def testGetPids_quotable(self):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand("ps | grep -F 'my$process'"),
+        ['user  1234    100   1024 1024   ffffffff 00000000 my$process']):
+      self.assertEqual(
+          {'my$process': '1234'}, self.device.GetPids('my$process'))
+
 
 class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest):
 
@@ -1404,8 +1492,8 @@
 
   def testGetMemoryUsageForPid_validPid(self):
     with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            ['showmap', '1234'], as_root=True, check_return=True),
+        (self.call.device._RunPipedShellCommand(
+            'showmap 1234 | grep TOTAL', as_root=True),
          ['100 101 102 103 104 105 106 107 TOTAL']),
         (self.call.device.ReadFile('/proc/1234/status', as_root=True),
          'VmHWM: 1024 kB\n')):
@@ -1424,8 +1512,8 @@
 
   def testGetMemoryUsageForPid_noSmaps(self):
     with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            ['showmap', '4321'], as_root=True, check_return=True),
+        (self.call.device._RunPipedShellCommand(
+            'showmap 4321 | grep TOTAL', as_root=True),
          ['cannot open /proc/4321/smaps: No such file or directory']),
         (self.call.device.ReadFile('/proc/4321/status', as_root=True),
          'VmHWM: 1024 kb\n')):
@@ -1433,8 +1521,8 @@
 
   def testGetMemoryUsageForPid_noStatus(self):
     with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            ['showmap', '4321'], as_root=True, check_return=True),
+        (self.call.device._RunPipedShellCommand(
+            'showmap 4321 | grep TOTAL', as_root=True),
          ['100 101 102 103 104 105 106 107 TOTAL']),
         (self.call.device.ReadFile('/proc/4321/status', as_root=True),
          self.CommandError())):
@@ -1451,116 +1539,6 @@
           self.device.GetMemoryUsageForPid(4321))
 
 
-class DeviceUtilsGetBatteryInfoTest(DeviceUtilsTest):
-  def testGetBatteryInfo_normal(self):
-    with self.assertCall(
-        self.call.device.RunShellCommand(
-            ['dumpsys', 'battery'], check_return=True),
-        [
-          'Current Battery Service state:',
-          '  AC powered: false',
-          '  USB powered: true',
-          '  level: 100',
-          '  temperature: 321',
-        ]):
-      self.assertEquals(
-          {
-            'AC powered': 'false',
-            'USB powered': 'true',
-            'level': '100',
-            'temperature': '321',
-          },
-          self.device.GetBatteryInfo())
-
-
-  def testGetBatteryInfo_nothing(self):
-    with self.assertCall(
-        self.call.device.RunShellCommand(
-            ['dumpsys', 'battery'], check_return=True), []):
-      self.assertEquals({}, self.device.GetBatteryInfo())
-
-
-class DeviceUtilsGetChargingTest(DeviceUtilsTest):
-  def testGetCharging_usb(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'USB powered': 'true'}):
-      self.assertTrue(self.device.GetCharging())
-
-  def testGetCharging_usbFalse(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'USB powered': 'false'}):
-      self.assertFalse(self.device.GetCharging())
-
-  def testGetCharging_ac(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'AC powered': 'true'}):
-      self.assertTrue(self.device.GetCharging())
-
-  def testGetCharging_wireless(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'Wireless powered': 'true'}):
-      self.assertTrue(self.device.GetCharging())
-
-  def testGetCharging_unknown(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'level': '42'}):
-      self.assertFalse(self.device.GetCharging())
-
-
-class DeviceUtilsSetChargingTest(DeviceUtilsTest):
-
-  @mock.patch('time.sleep', mock.Mock())
-  def testSetCharging_enabled(self):
-    with self.assertCalls(
-        (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), False),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), True)):
-      self.device.SetCharging(True)
-
-  def testSetCharging_alreadyEnabled(self):
-    with self.assertCalls(
-        (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), True)):
-      self.device.SetCharging(True)
-
-  @mock.patch('time.sleep', mock.Mock())
-  def testSetCharging_disabled(self):
-    with self.assertCalls(
-        (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), False)):
-      self.device.SetCharging(False)
-
-
-class DeviceUtilsSetBatteryMeasurementTest(DeviceUtilsTest):
-
-  def testBatteryMeasurement(self):
-    with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            mock.ANY, retries=0, single_line=True,
-            timeout=10, check_return=True), '22'),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'batterystats', '--charged', '--checkin'],
-            check_return=True), []),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
-        (self.call.device.GetCharging(), False),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True), []),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'battery', 'reset'], check_return=True), []),
-        (self.call.device.GetCharging(), True)):
-      with self.device.BatteryMeasurement():
-        pass
-
-
 class DeviceUtilsStrTest(DeviceUtilsTest):
 
   def testStr_returnsSerial(self):
@@ -1569,27 +1547,83 @@
       self.assertEqual('0123456789abcdef', str(self.device))
 
 
+class DeviceUtilsClientCache(DeviceUtilsTest):
+
+  def testClientCache_twoCaches(self):
+    self.device._cache['test'] = 0
+    client_cache_one = self.device.GetClientCache('ClientOne')
+    client_cache_one['test'] = 1
+    client_cache_two = self.device.GetClientCache('ClientTwo')
+    client_cache_two['test'] = 2
+    self.assertEqual(self.device._cache, {'test': 0})
+    self.assertEqual(client_cache_one, {'test': 1})
+    self.assertEqual(client_cache_two, {'test': 2})
+    self.device._ClearCache()
+    self.assertEqual(self.device._cache, {})
+    self.assertEqual(client_cache_one, {})
+    self.assertEqual(client_cache_two, {})
+
+  def testClientCache_multipleInstances(self):
+    client_cache_one = self.device.GetClientCache('ClientOne')
+    client_cache_one['test'] = 1
+    client_cache_two = self.device.GetClientCache('ClientOne')
+    self.assertEqual(client_cache_one, {'test': 1})
+    self.assertEqual(client_cache_two, {'test': 1})
+    self.device._ClearCache()
+    self.assertEqual(client_cache_one, {})
+    self.assertEqual(client_cache_two, {})
+
+
 class DeviceUtilsParallelTest(mock_calls.TestCase):
 
   def testParallel_default(self):
     test_serials = ['0123456789abcdef', 'fedcba9876543210']
     with self.assertCall(
-        mock.call.pylib.device.adb_wrapper.AdbWrapper.GetDevices(),
-        [_AdbWrapperMock(serial) for serial in test_serials]):
+        mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(),
+        [device_utils.DeviceUtils(s) for s in test_serials]):
       parallel_devices = device_utils.DeviceUtils.parallel()
     for serial, device in zip(test_serials, parallel_devices.pGet(None)):
-      self.assertTrue(
-          isinstance(device, device_utils.DeviceUtils)
-          and serial == str(device),
-          'Expected a DeviceUtils object with serial %s' % serial)
+      self.assertTrue(isinstance(device, device_utils.DeviceUtils))
+      self.assertEquals(serial, device.adb.GetDeviceSerial())
 
   def testParallel_noDevices(self):
     with self.assertCall(
-        mock.call.pylib.device.adb_wrapper.AdbWrapper.GetDevices(), []):
+        mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(), []):
       with self.assertRaises(device_errors.NoDevicesError):
         device_utils.DeviceUtils.parallel()
 
 
+class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
+
+  def _createAdbWrapperMock(self, serial, is_ready=True):
+    adb = _AdbWrapperMock(serial)
+    adb.is_ready = is_ready
+    return adb
+
+  def testHealthyDevices_default(self):
+    test_serials = ['0123456789abcdef', 'fedcba9876543210']
+    with self.assertCalls(
+        (mock.call.pylib.device.device_blacklist.ReadBlacklist(), []),
+        (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(),
+         [self._createAdbWrapperMock(s) for s in test_serials])):
+      devices = device_utils.DeviceUtils.HealthyDevices()
+    for serial, device in zip(test_serials, devices):
+      self.assertTrue(isinstance(device, device_utils.DeviceUtils))
+      self.assertEquals(serial, device.adb.GetDeviceSerial())
+
+  def testHealthyDevices_blacklisted(self):
+    test_serials = ['0123456789abcdef', 'fedcba9876543210']
+    with self.assertCalls(
+        (mock.call.pylib.device.device_blacklist.ReadBlacklist(),
+         ['fedcba9876543210']),
+        (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(),
+         [self._createAdbWrapperMock(s) for s in test_serials])):
+      devices = device_utils.DeviceUtils.HealthyDevices()
+    self.assertEquals(1, len(devices))
+    self.assertTrue(isinstance(devices[0], device_utils.DeviceUtils))
+    self.assertEquals('0123456789abcdef', devices[0].adb.GetDeviceSerial())
+
+
 if __name__ == '__main__':
   logging.getLogger().setLevel(logging.DEBUG)
   unittest.main(verbosity=2)
diff --git a/build/android/pylib/device_signal.py b/build/android/pylib/device_signal.py
new file mode 100644
index 0000000..6a5b709
--- /dev/null
+++ b/build/android/pylib/device_signal.py
@@ -0,0 +1,41 @@
+# 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.
+
+"""Defines constants for signals that should be supported on devices.
+
+Note: Obtained by running `kill -l` on a user device.
+"""
+
+
+SIGHUP = 1 # Hangup
+SIGINT = 2 # Interrupt
+SIGQUIT = 3 # Quit
+SIGILL = 4 # Illegal instruction
+SIGTRAP = 5 # Trap
+SIGABRT = 6 # Aborted
+SIGBUS = 7 # Bus error
+SIGFPE = 8 # Floating point exception
+SIGKILL = 9 # Killed
+SIGUSR1 = 10 # User signal 1
+SIGSEGV = 11 # Segmentation fault
+SIGUSR2 = 12 # User signal 2
+SIGPIPE = 13 # Broken pipe
+SIGALRM = 14 # Alarm clock
+SIGTERM = 15 # Terminated
+SIGSTKFLT = 16 # Stack fault
+SIGCHLD = 17 # Child exited
+SIGCONT = 18 # Continue
+SIGSTOP = 19 # Stopped (signal)
+SIGTSTP = 20 # Stopped
+SIGTTIN = 21 # Stopped (tty input)
+SIGTTOU = 22 # Stopped (tty output)
+SIGURG = 23 # Urgent I/O condition
+SIGXCPU = 24 # CPU time limit exceeded
+SIGXFSZ = 25 # File size limit exceeded
+SIGVTALRM = 26 # Virtual timer expired
+SIGPROF = 27 # Profiling timer expired
+SIGWINCH = 28 # Window size changed
+SIGIO = 29 # I/O possible
+SIGPWR = 30 # Power failure
+SIGSYS = 31 # Bad system call
diff --git a/build/android/pylib/forwarder.py b/build/android/pylib/forwarder.py
index eb83d68..d16b9b1 100644
--- a/build/android/pylib/forwarder.py
+++ b/build/android/pylib/forwarder.py
@@ -288,11 +288,8 @@
         self._device_forwarder_path_on_host,
         Forwarder._DEVICE_FORWARDER_FOLDER)])
     cmd = '%s %s' % (tool.GetUtilWrapper(), Forwarder._DEVICE_FORWARDER_PATH)
-    (exit_code, output) = device.old_interface.GetAndroidToolStatusAndOutput(
-        cmd, lib_path=Forwarder._DEVICE_FORWARDER_FOLDER)
-    if exit_code != 0:
-      raise Exception(
-          'Failed to start device forwarder:\n%s' % '\n'.join(output))
+    device.RunShellCommand(
+        cmd, env={'LD_LIBRARY_PATH': Forwarder._DEVICE_FORWARDER_FOLDER})
     self._initialized_devices.add(device_serial)
 
   def _KillHostLocked(self):
@@ -328,5 +325,5 @@
 
     cmd = '%s %s --kill-server' % (tool.GetUtilWrapper(),
                                    Forwarder._DEVICE_FORWARDER_PATH)
-    device.old_interface.GetAndroidToolStatusAndOutput(
-        cmd, lib_path=Forwarder._DEVICE_FORWARDER_FOLDER)
+    device.RunShellCommand(
+        cmd, env={'LD_LIBRARY_PATH': Forwarder._DEVICE_FORWARDER_FOLDER})
diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled
index 3c36264..39eff4d 100644
--- a/build/android/pylib/gtest/filter/content_browsertests_disabled
+++ b/build/android/pylib/gtest/filter/content_browsertests_disabled
@@ -2,13 +2,6 @@
 # Timeouts
 Http/MediaTest.*
 File/MediaTest.*
-WorkerTest.IncognitoSharedWorkers
-WorkerTest.MultipleSharedWorkers
-WorkerTest.PassMessagePortToSharedWorker
-WorkerTest.PassMessagePortToSharedWorkerDontWaitForConnect
-WorkerTest.SharedWorkerHttpAuth
-WorkerTest.SingleSharedWorker
-WorkerTest.WebSocketSharedWorker
 MediaTest.*
 DatabaseTest.*
 
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index 8608ed7..6ce0fb1 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -6,6 +6,7 @@
 
 # Add new suites here before upgrading them to the stable list below.
 EXPERIMENTAL_TEST_SUITES = [
+    'components_browsertests',
     'content_gl_tests',
     'heap_profiler_unittests',
     'devtools_bridge_tests',
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index 186b8fc..b6f83b3 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -92,9 +92,10 @@
       raise ValueError('Platform mode currently supports only 1 gtest suite')
     self._suite = args.suite_name[0]
 
-    if self._suite == 'content_browsertests':
-      error_func('content_browsertests are not currently supported '
-                 'in platform mode.')
+    if (self._suite == 'content_browsertests' or
+        self._suite == 'components_browsertests'):
+      error_func('%s are not currently supported '
+                 'in platform mode.' % self._suite)
       self._apk_path = os.path.join(
           constants.GetOutDirectory(), 'apks', '%s.apk' % self._suite)
     else:
diff --git a/build/android/pylib/gtest/local_device_gtest_run.py b/build/android/pylib/gtest/local_device_gtest_run.py
index c48c865..fd143d6 100644
--- a/build/android/pylib/gtest/local_device_gtest_run.py
+++ b/build/android/pylib/gtest/local_device_gtest_run.py
@@ -30,7 +30,8 @@
 # TODO(jbudorick): Move this up to the test instance if the net test server is
 # handled outside of the APK for the remote_device environment.
 _SUITE_REQUIRES_TEST_SERVER_SPAWNER = [
-  'content_unittests', 'content_browsertests', 'net_unittests', 'unit_tests'
+  'components_browsertests', 'content_unittests', 'content_browsertests',
+  'net_unittests', 'unit_tests'
 ]
 
 class _ApkDelegate(object):
@@ -112,12 +113,7 @@
     return output
 
   def Clear(self, device):
-    try:
-      device.KillAll(self._exe_file_name, blocking=True, timeout=30, retries=0)
-    except device_errors.CommandFailedError:
-      # Raised if there is no process with the given name, which in this case
-      # is all we care about.
-      pass
+    device.KillAll(self._exe_file_name, blocking=True, timeout=30, quiet=True)
 
 
 class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun):
diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py
index 1b882ca..44662d0 100644
--- a/build/android/pylib/gtest/setup.py
+++ b/build/android/pylib/gtest/setup.py
@@ -31,6 +31,7 @@
       'third_party/WebKit/Source/platform/heap/BlinkHeapUnitTests.isolate',
     'breakpad_unittests': 'breakpad/breakpad_unittests.isolate',
     'cc_perftests': 'cc/cc_perftests.isolate',
+    'components_browsertests': 'components/components_browsertests.isolate',
     'components_unittests': 'components/components_unittests.isolate',
     'content_browsertests': 'content/content_browsertests.isolate',
     'content_unittests': 'content/content_unittests.isolate',
@@ -236,7 +237,8 @@
     tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter)
 
   # Coalesce unit tests into a single test per device
-  if test_options.suite_name != 'content_browsertests':
+  if (test_options.suite_name != 'content_browsertests' and
+      test_options.suite_name != 'components_browsertests'):
     num_devices = len(devices)
     tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)]
     tests = [t for t in tests if t]
diff --git a/build/android/pylib/gtest/test_options.py b/build/android/pylib/gtest/test_options.py
index 5099ba6..58cd82b 100644
--- a/build/android/pylib/gtest/test_options.py
+++ b/build/android/pylib/gtest/test_options.py
@@ -8,7 +8,6 @@
 
 GTestOptions = collections.namedtuple('GTestOptions', [
     'tool',
-    'cleanup_test_files',
     'gtest_filter',
     'run_disabled',
     'test_arguments',
diff --git a/build/android/pylib/gtest/test_package_apk.py b/build/android/pylib/gtest/test_package_apk.py
index cdb6daf..8da3c74 100644
--- a/build/android/pylib/gtest/test_package_apk.py
+++ b/build/android/pylib/gtest/test_package_apk.py
@@ -34,6 +34,10 @@
       self.suite_path = os.path.join(
           constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name)
       self._package_info = constants.PACKAGE_INFO['content_browsertests']
+    elif suite_name == 'components_browsertests':
+      self.suite_path = os.path.join(
+          constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name)
+      self._package_info = constants.PACKAGE_INFO['components_browsertests']
     else:
       self.suite_path = os.path.join(
           constants.GetOutDirectory(), '%s_apk' % suite_name,
@@ -46,7 +50,7 @@
 
   def _GetFifo(self):
     # The test.fifo path is determined by:
-    # testing/android/java/src/org/chromium/native_test/
+    # testing/android/native_test/java/src/org/chromium/native_test/
     #     ChromeNativeTestActivity.java and
     # testing/android/native_test_launcher.cc
     return '/data/data/' + self._package_info.package + '/files/test.fifo'
@@ -90,6 +94,15 @@
         # TODO(jbudorick) Handle this exception appropriately once the
         #                 conversions are done.
         pass
+    elif self.suite_name == 'components_browsertests':
+      try:
+        device.RunShellCommand(
+            'rm -r %s/components_shell' % device.GetExternalStoragePath(),
+            timeout=60 * 2)
+      except device_errors.CommandFailedError:
+        # TODO(jbudorick) Handle this exception appropriately once the
+        #                 conversions are done.
+        pass
 
   #override
   def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
diff --git a/build/android/pylib/gtest/test_package_exe.py b/build/android/pylib/gtest/test_package_exe.py
index e607cad..aa3374e 100644
--- a/build/android/pylib/gtest/test_package_exe.py
+++ b/build/android/pylib/gtest/test_package_exe.py
@@ -6,6 +6,7 @@
 
 import logging
 import os
+import posixpath
 import sys
 import tempfile
 
@@ -78,15 +79,7 @@
 
   #override
   def ClearApplicationState(self, device):
-    try:
-      # We don't expect the executable to be running, so we don't attempt
-      # to retry on failure.
-      device.KillAll(self.suite_name, blocking=True, timeout=30, retries=0)
-    except device_errors.CommandFailedError:
-      # KillAll raises an exception if it can't find a process with the given
-      # name. We only care that there is no process with the given name, so
-      # we can safely eat the exception.
-      pass
+    device.KillAll(self.suite_name, blocking=True, timeout=30, quiet=True)
 
   #override
   def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
@@ -119,14 +112,19 @@
 
   #override
   def GetAllTests(self, device):
-    cmd = '%s %s/%s --gtest_list_tests' % (self.tool.GetTestWrapper(),
-        constants.TEST_EXECUTABLE_DIR, self.suite_name)
-    lib_path = '%s/%s_deps' % (constants.TEST_EXECUTABLE_DIR, self.suite_name)
-    (exit_code, output) = device.old_interface.GetAndroidToolStatusAndOutput(
-        cmd, lib_path=lib_path)
-    if exit_code != 0:
-      raise Exception(
-          'Failed to start binary:\n%s' % '\n'.join(output))
+    lib_path = posixpath.join(
+        constants.TEST_EXECUTABLE_DIR, '%s_deps' % self.suite_name)
+
+    cmd = []
+    for wrapper in (device.GetDevicePieWrapper(), self.tool.GetTestWrapper()):
+      if wrapper:
+        cmd.append(wrapper)
+    cmd.extend([
+        posixpath.join(constants.TEST_EXECUTABLE_DIR, self.suite_name),
+        '--gtest_list_tests'])
+
+    output = device.RunShellCommand(
+        cmd, check_return=True, env={'LD_LIBRARY_PATH': lib_path})
     return gtest_test_instance.ParseGTestListTests(output)
 
   #override
diff --git a/build/android/pylib/gtest/test_runner.py b/build/android/pylib/gtest/test_runner.py
index 4bb9737..4926388 100644
--- a/build/android/pylib/gtest/test_runner.py
+++ b/build/android/pylib/gtest/test_runner.py
@@ -26,10 +26,15 @@
 # to output the CRASHED marker when a crash happens.
 RE_CRASH = re.compile('\\[ CRASHED      \\](.*)\r\n')
 
+# Bots that don't output anything for 20 minutes get timed out, so that's our
+# hard cap.
+_INFRA_STDOUT_TIMEOUT = 20 * 60
+
 
 def _TestSuiteRequiresMockTestServer(suite_name):
   """Returns True if the test suite requires mock test server."""
   tests_require_net_test_server = ['unit_tests', 'net_unittests',
+                                   'components_browsertests',
                                    'content_unittests',
                                    'content_browsertests']
   return (suite_name in
@@ -49,8 +54,7 @@
       test_package: An instance of TestPackage class.
     """
 
-    super(TestRunner, self).__init__(device, test_options.tool,
-                                     test_options.cleanup_test_files)
+    super(TestRunner, self).__init__(device, test_options.tool)
 
     self.test_package = test_package
     self.test_package.tool = self.tool
@@ -63,7 +67,8 @@
     if os.environ.get('BUILDBOT_SLAVENAME'):
       timeout = timeout * 2
 
-    self._timeout = timeout * self.tool.GetTimeoutScale()
+    self._timeout = min(timeout * self.tool.GetTimeoutScale(),
+                        _INFRA_STDOUT_TIMEOUT)
     if _TestSuiteRequiresHighPerfMode(self.test_package.suite_name):
       self._perf_controller = perf_control.PerfControl(self.device)
 
diff --git a/build/android/pylib/host_driven/setup.py b/build/android/pylib/host_driven/setup.py
index 285bcd4..b2ed348 100644
--- a/build/android/pylib/host_driven/setup.py
+++ b/build/android/pylib/host_driven/setup.py
@@ -195,7 +195,6 @@
   def TestRunnerFactory(device, shard_index):
     return test_runner.HostDrivenTestRunner(
         device, shard_index,
-        instrumentation_options.tool,
-        instrumentation_options.cleanup_test_files)
+        instrumentation_options.tool)
 
   return (TestRunnerFactory, available_tests)
diff --git a/build/android/pylib/host_driven/test_case.py b/build/android/pylib/host_driven/test_case.py
index 8c372cd..a7c6a18 100644
--- a/build/android/pylib/host_driven/test_case.py
+++ b/build/android/pylib/host_driven/test_case.py
@@ -50,8 +50,6 @@
       instrumentation_options: An InstrumentationOptions object.
     """
     class_name = self.__class__.__name__
-    self.adb = None
-    self.cleanup_test_files = False
     self.device = None
     self.device_id = ''
     self.has_forwarded_ports = False
@@ -67,15 +65,12 @@
 
   # TODO(bulach): make ports_to_forward not optional and move the Forwarder
   # mapping here.
-  def SetUp(self, device, shard_index,
-            cleanup_test_files, ports_to_forward=None):
+  def SetUp(self, device, shard_index, ports_to_forward=None):
     if not ports_to_forward:
       ports_to_forward = []
     self.device_id = device
     self.shard_index = shard_index
     self.device = device_utils.DeviceUtils(self.device_id)
-    self.adb = self.device.old_interface
-    self.cleanup_test_files = cleanup_test_files
     if ports_to_forward:
       self.ports_to_forward = ports_to_forward
 
diff --git a/build/android/pylib/host_driven/test_runner.py b/build/android/pylib/host_driven/test_runner.py
index 865be20..5e175bc 100644
--- a/build/android/pylib/host_driven/test_runner.py
+++ b/build/android/pylib/host_driven/test_runner.py
@@ -47,23 +47,27 @@
   result, rather than being re-raised on the main thread.
   """
 
+  # TODO(jbudorick): Remove cleanup_test_files once it's no longer used.
+  # pylint: disable=unused-argument
   #override
-  def __init__(self, device, shard_index, tool, cleanup_test_files):
+  def __init__(self, device, shard_index, tool, cleanup_test_files=None):
     """Creates a new HostDrivenTestRunner.
 
     Args:
       device: Attached android device.
       shard_index: Shard index.
       tool: Name of the Valgrind tool.
-      cleanup_test_files: Whether or not to cleanup test files on device.
+      cleanup_test_files: Deprecated.
     """
 
-    super(HostDrivenTestRunner, self).__init__(device, tool, cleanup_test_files)
+    super(HostDrivenTestRunner, self).__init__(device, tool)
 
     # The shard index affords the ability to create unique port numbers (e.g.
     # DEFAULT_PORT + shard_index) if the test so wishes.
     self.shard_index = shard_index
 
+  # pylint: enable=unused-argument
+
   #override
   def RunTest(self, test):
     """Sets up and runs a test case.
@@ -82,7 +86,7 @@
     exception_raised = False
 
     try:
-      test.SetUp(str(self.device), self.shard_index, self._cleanup_test_files)
+      test.SetUp(str(self.device), self.shard_index)
     except Exception:
       logging.exception(
           'Caught exception while trying to run SetUp() for test: ' +
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 3f56e6d..ccc0e72 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -335,7 +335,7 @@
 
     with open(pickle_path, 'r') as pickle_file:
       pickle_data = pickle.loads(pickle_file.read())
-    jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0]
+    jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path]
 
     try:
       if pickle_data['VERSION'] != _PICKLE_FORMAT_VERSION:
@@ -377,7 +377,7 @@
             if is_test_class(c)]
 
   def _SaveTestsToPickle(self, pickle_path, jar_path, tests):
-    jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0]
+    jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path]
     pickle_data = {
       'VERSION': _PICKLE_FORMAT_VERSION,
       'JAR_MD5SUM': jar_md5,
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py
index c3faef3..9c38510 100644
--- a/build/android/pylib/instrumentation/test_jar.py
+++ b/build/android/pylib/instrumentation/test_jar.py
@@ -65,7 +65,7 @@
       try:
         with open(self._pickled_proguard_name, 'r') as r:
           d = pickle.loads(r.read())
-        jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash
+        jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]
         if (d['JAR_MD5SUM'] == jar_md5 and
             d['VERSION'] == PICKLE_FORMAT_VERSION):
           self._test_methods = d['TEST_METHODS']
@@ -105,7 +105,8 @@
     logging.info('Storing proguard output to %s', self._pickled_proguard_name)
     d = {'VERSION': PICKLE_FORMAT_VERSION,
          'TEST_METHODS': self._test_methods,
-         'JAR_MD5SUM': md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash}
+         'JAR_MD5SUM':
+              md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]}
     with open(self._pickled_proguard_name, 'w') as f:
       f.write(pickle.dumps(d))
 
diff --git a/build/android/pylib/instrumentation/test_options.py b/build/android/pylib/instrumentation/test_options.py
index 4a16b11..792010b 100644
--- a/build/android/pylib/instrumentation/test_options.py
+++ b/build/android/pylib/instrumentation/test_options.py
@@ -8,7 +8,6 @@
 
 InstrumentationOptions = collections.namedtuple('InstrumentationOptions', [
     'tool',
-    'cleanup_test_files',
     'annotations',
     'exclude_annotations',
     'test_filter',
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index f3983fd..6e8be34 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -48,8 +48,7 @@
       test_pkg: A TestPackage object.
       additional_flags: A list of additional flags to add to the command line.
     """
-    super(TestRunner, self).__init__(device, test_options.tool,
-                                     test_options.cleanup_test_files)
+    super(TestRunner, self).__init__(device, test_options.tool)
     self._lighttp_port = constants.LIGHTTPD_RANDOM_PORT_FIRST + shard_index
     self._logcat_monitor = None
 
@@ -229,7 +228,7 @@
     # just quits and does not do anything.  The java test harness will still
     # print the appropriate annotation for us, but will add --NORUN-- for
     # us so we know to ignore the results.
-    # The --NORUN-- tag is managed by MainActivityTestBase.java
+    # The --NORUN-- tag is managed by ChromeTabbedActivityTestBase.java
     if regex.group(1) != '--NORUN--':
 
       # Obtain the relevant perf data.  The data is dumped to a
diff --git a/build/android/pylib/junit/test_dispatcher.py b/build/android/pylib/junit/test_dispatcher.py
index b821b75..6e0d865 100644
--- a/build/android/pylib/junit/test_dispatcher.py
+++ b/build/android/pylib/junit/test_dispatcher.py
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from pylib import constants
+from pylib.base import base_test_result
+
 def RunTests(tests, runner_factory):
   """Runs a set of java tests on the host.
 
@@ -11,9 +14,15 @@
   def run(t):
     runner = runner_factory(None, None)
     runner.SetUp()
-    result = runner.RunTest(t)
+    results_list, return_code = runner.RunTest(t)
     runner.TearDown()
-    return result == 0
+    return (results_list, return_code == 0)
 
-  return (None, 0 if all(run(t) for t in tests) else 1)
-
+  test_run_results = base_test_result.TestRunResults()
+  exit_code = 0
+  for t in tests:
+    results_list, passed = run(t)
+    test_run_results.AddResults(results_list)
+    if not passed:
+      exit_code = constants.ERROR_EXIT_CODE
+  return (test_run_results, exit_code)
\ No newline at end of file
diff --git a/build/android/pylib/junit/test_runner.py b/build/android/pylib/junit/test_runner.py
index b85967b..a6d3bf9 100644
--- a/build/android/pylib/junit/test_runner.py
+++ b/build/android/pylib/junit/test_runner.py
@@ -2,10 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import json
 import os
+import tempfile
 
 from pylib import cmd_helper
 from pylib import constants
+from pylib.base import base_test_result
+from pylib.results import json_results
 
 class JavaTestRunner(object):
   """Runs java tests on the host."""
@@ -22,22 +26,24 @@
 
   def RunTest(self, _test):
     """Runs junit tests from |self._test_suite|."""
-
-    command = ['java',
-               '-Drobolectric.dependency.dir=%s' %
-                    os.path.join(constants.GetOutDirectory(), 'lib.java'),
-               '-jar', os.path.join(constants.GetOutDirectory(), 'lib.java',
-                                    '%s.jar' % self._test_suite)]
-
-    if self._test_filter:
-      command.extend(['-gtest-filter', self._test_filter])
-    if self._package_filter:
-      command.extend(['-package-filter', self._package_filter])
-    if self._runner_filter:
-      command.extend(['-runner-filter', self._runner_filter])
-    if self._sdk_version:
-      command.extend(['-sdk-version', self._sdk_version])
-    return cmd_helper.RunCmd(command)
+    with tempfile.NamedTemporaryFile() as json_file:
+      java_script = os.path.join(
+          constants.GetOutDirectory(), 'bin', self._test_suite)
+      command = [java_script,
+                 '-test-jars', self._test_suite + '.jar',
+                 '-json-results-file', json_file.name]
+      if self._test_filter:
+        command.extend(['-gtest-filter', self._test_filter])
+      if self._package_filter:
+        command.extend(['-package-filter', self._package_filter])
+      if self._runner_filter:
+        command.extend(['-runner-filter', self._runner_filter])
+      if self._sdk_version:
+        command.extend(['-sdk-version', self._sdk_version])
+      return_code = cmd_helper.RunCmd(command)
+      results_list = json_results.ParseResultsFromJson(
+          json.loads(json_file.read()))
+      return (results_list, return_code)
 
   def TearDown(self):
     pass
diff --git a/build/android/pylib/linker/setup.py b/build/android/pylib/linker/setup.py
index ff21f10..5776f5a 100644
--- a/build/android/pylib/linker/setup.py
+++ b/build/android/pylib/linker/setup.py
@@ -40,7 +40,6 @@
                  if t.qualified_name in filtered_test_names]
 
   def TestRunnerFactory(device, _shard_index):
-    return test_runner.LinkerTestRunner(
-        device, args.tool, args.cleanup_test_files)
+    return test_runner.LinkerTestRunner(device, args.tool)
 
   return (TestRunnerFactory, all_tests)
diff --git a/build/android/pylib/linker/test_runner.py b/build/android/pylib/linker/test_runner.py
index 3680f83..b6803e4 100644
--- a/build/android/pylib/linker/test_runner.py
+++ b/build/android/pylib/linker/test_runner.py
@@ -49,16 +49,14 @@
   """
 
   #override
-  def __init__(self, device, tool, cleanup_test_files):
+  def __init__(self, device, tool):
     """Creates a new LinkerTestRunner.
 
     Args:
       device: Attached android device.
       tool: Name of the Valgrind tool.
-      cleanup_test_files: Whether or not to cleanup test files on device.
     """
-
-    super(LinkerTestRunner, self).__init__(device, tool, cleanup_test_files)
+    super(LinkerTestRunner, self).__init__(device, tool)
 
   #override
   def InstallTestPackage(self):
@@ -68,8 +66,7 @@
     if not os.path.exists(apk_path):
       raise Exception('%s not found, please build it' % apk_path)
 
-    package_name = apk_helper.GetPackageName(apk_path)
-    self.device.old_interface.ManagedInstall(apk_path, package_name)
+    self.device.Install(apk_path)
 
   #override
   def RunTest(self, test):
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py
index 72acb6e..0d02ca3 100644
--- a/build/android/pylib/local/device/local_device_environment.py
+++ b/build/android/pylib/local/device/local_device_environment.py
@@ -13,26 +13,24 @@
 
   def __init__(self, args, _error_func):
     super(LocalDeviceEnvironment, self).__init__()
-    self._device = args.test_device
+    self._device_serial = args.test_device
     self._devices = []
     self._max_tries = 1 + args.num_retries
     self._tool_name = args.tool
 
   #override
   def SetUp(self):
-    # TODO(jbudorick): This can be refined to support filters etc.
-    available_devices = adb_wrapper.AdbWrapper.GetDevices()
+    available_devices = device_utils.DeviceUtils.HealthyDevices()
     if not available_devices:
       raise device_errors.NoDevicesError
-    if self._device:
-      if self._device not in available_devices:
+    if self._device_serial:
+      self._devices = [d for d in available_devices
+                       if d.adb.GetDeviceSerial == self._device_serial]
+      if not self._devices:
         raise device_errors.DeviceUnreachableError(
-            'Could not find device %r' % self._device)
-      self._devices = [device_utils.DeviceUtils(self._device)]
+            'Could not find device %r' % self._device_serial)
     else:
-      self._devices = [
-          device_utils.DeviceUtils(s)
-          for s in available_devices]
+      self._devices = available_devices
 
   @property
   def devices(self):
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index ac3f5b1..adc1037 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -3,11 +3,14 @@
 # found in the LICENSE file.
 
 import logging
+import re
 import time
 
 from pylib import flag_changer
 from pylib.base import base_test_result
 from pylib.base import test_run
+from pylib.constants import keyevent
+from pylib.device import device_errors
 from pylib.local.device import local_device_test_run
 
 
@@ -27,16 +30,39 @@
 def DidPackageCrashOnDevice(package_name, device):
   # Dismiss any error dialogs. Limit the number in case we have an error
   # loop or we are failing to dismiss.
-  for _ in xrange(10):
-    package = device.old_interface.DismissCrashDialogIfNeeded()
-    if not package:
-      return False
-    # Assume test package convention of ".test" suffix
-    if package in package_name:
-      return True
+  try:
+    for _ in xrange(10):
+      package = _DismissCrashDialog(device)
+      if not package:
+        return False
+      # Assume test package convention of ".test" suffix
+      if package in package_name:
+        return True
+  except device_errors.CommandFailedError:
+    logging.exception('Error while attempting to dismiss crash dialog.')
   return False
 
 
+_CURRENT_FOCUS_CRASH_RE = re.compile(
+    r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}')
+
+
+def _DismissCrashDialog(device):
+  # TODO(jbudorick): Try to grep the output on the device instead of using
+  # large_output if/when DeviceUtils exposes a public interface for piped
+  # shell command handling.
+  for l in device.RunShellCommand(
+      ['dumpsys', 'window', 'windows'], check_return=True, large_output=True):
+    m = re.match(_CURRENT_FOCUS_CRASH_RE, l)
+    if m:
+      device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT)
+      device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT)
+      device.SendKeyEvent(keyevent.KEYCODE_ENTER)
+      return m.group(2)
+
+  return None
+
+
 class LocalDeviceInstrumentationTestRun(
     local_device_test_run.LocalDeviceTestRun):
   def __init__(self, env, test_instance):
diff --git a/build/android/pylib/monkey/test_runner.py b/build/android/pylib/monkey/test_runner.py
index 19dd339..3fd1797 100644
--- a/build/android/pylib/monkey/test_runner.py
+++ b/build/android/pylib/monkey/test_runner.py
@@ -10,8 +10,11 @@
 from pylib import constants
 from pylib.base import base_test_result
 from pylib.base import base_test_runner
+from pylib.device import device_errors
 from pylib.device import intent
 
+_CHROME_PACKAGE = constants.PACKAGE_INFO['chrome'].package
+
 class TestRunner(base_test_runner.BaseTestRunner):
   """A TestRunner instance runs a monkey test on a single device."""
 
@@ -87,9 +90,17 @@
           test_name, base_test_result.ResultType.FAIL, log=output)
       if 'chrome' in self._options.package:
         logging.warning('Starting MinidumpUploadService...')
+        # TODO(jbudorick): Update this after upstreaming.
+        minidump_intent = intent.Intent(
+            action='%s.crash.ACTION_FIND_ALL' % _CHROME_PACKAGE,
+            package=self._package,
+            activity='%s.crash.MinidumpUploadService' % _CHROME_PACKAGE)
         try:
-          self.device.old_interface.StartCrashUploadService(self._package)
-        except AssertionError as e:
-          logging.error('Failed to start MinidumpUploadService: %s', e)
+          self.device.RunShellCommand(
+              ['am', 'startservice'] + minidump_intent.am_args,
+              as_root=True, check_return=True)
+        except device_errors.CommandFailedError:
+          logging.exception('Failed to start MinidumpUploadService')
+
     results.AddResult(result)
     return results, False
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py
index 97fa4a7..b6a0989 100644
--- a/build/android/pylib/perf/perf_control.py
+++ b/build/android/pylib/perf/perf_control.py
@@ -28,7 +28,7 @@
 
   def SetHighPerfMode(self):
     """Sets the highest stable performance mode for the device."""
-    if not self._device.old_interface.IsRootEnabled():
+    if not self._device.HasRoot():
       message = 'Need root for performance mode. Results may be NOISY!!'
       logging.warning(message)
       # Add an additional warning at exit, such that it's clear that any results
@@ -58,13 +58,13 @@
     self._ForceAllCpusOnline(True)
     self._SetScalingGovernorInternal('performance')
     if not self._AllCpusAreOnline():
-      if not self._device.old_interface.IsRootEnabled():
+      if not self._device.HasRoot():
         raise RuntimeError('Need root to force CPUs online.')
       raise RuntimeError('Failed to force CPUs online.')
 
   def SetDefaultPerfMode(self):
     """Sets the performance mode for the device to its default mode."""
-    if not self._device.old_interface.IsRootEnabled():
+    if not self._device.HasRoot():
       return
     product_model = self._device.product_model
     if 'Nexus 5' == product_model:
diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py
index da66d07..9d1f437 100644
--- a/build/android/pylib/perf/test_runner.py
+++ b/build/android/pylib/perf/test_runner.py
@@ -170,7 +170,7 @@
       tests: a dict mapping test_name to command.
       flaky_tests: a list of flaky test_name.
     """
-    super(TestRunner, self).__init__(device, None, 'Release')
+    super(TestRunner, self).__init__(device, None)
     self._options = test_options
     self._shard_index = shard_index
     self._max_shard = max_shard
diff --git a/build/android/pylib/remote/device/appurify_constants.py b/build/android/pylib/remote/device/appurify_constants.py
new file mode 100644
index 0000000..9343178
--- /dev/null
+++ b/build/android/pylib/remote/device/appurify_constants.py
@@ -0,0 +1,57 @@
+# 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.
+
+"""Defines a set of constants specific to appurify."""
+
+# Appurify network config constants.
+class NETWORK(object):
+  WIFI_1_BAR = 1
+  SPRINT_4G_LTE_4_BARS = 2
+  SPRINT_3G_5_BARS = 3
+  SPRINT_3G_4_BARS = 4
+  SPRINT_3G_3_BARS = 5
+  SPRINT_3G_2_BARS = 6
+  SPRINT_3G_1_BAR = 7
+  SPRING_4G_1_BAR = 8
+  VERIZON_3G_5_BARS = 9
+  VERIZON_3G_4_BARS = 10
+  VERIZON_3G_3_BARS = 11
+  VERIZON_3G_2_BARS = 12
+  VERIZON_3G_1_BAR = 13
+  VERIZON_4G_1_BAR = 14
+  ATANDT_3G_5_BARS = 15
+  ATANDT_3G_4_BARS = 16
+  ATANDT_3G_3_BARS = 17
+  ATANDT_3G_2_BARS = 18
+  ATANDT_3G_1_BAR = 19
+  GENERIC_2G_4_BARS = 20
+  GENERIC_2G_3_BARS = 21
+  GENERIC_EVOLVED_EDGE = 22
+  GENERIC_GPRS = 23
+  GENERIC_ENHANCED_GPRS = 24
+  GENERIC_LTE = 25
+  GENERIC_HIGH_LATENCY_DNS = 26
+  GENERIC_100_PERCENT_PACKET_LOSS = 27
+  ATANDT_HSPA_PLUS = 28
+  ATANDT_4G_LTE_4_BARS = 29
+  VERIZON_4G_LTE_4_BARS = 30
+  GENERIC_DIGITAL_SUBSCRIBE_LINE = 31
+  WIFI_STARBUCKS_3_BARS = 32
+  WIFI_STARBUCKS_4_BARS = 33
+  WIFI_STARBUCKS_HIGH_TRAFFIC = 34
+  WIFI_TARGET_1_BAR = 35
+  WIFI_TARGET_3_BARS = 36
+  WIFI_TARGET_4_BARS = 37
+  PUBLIC_WIFI_MCDONALDS_5_BARS = 38
+  PUBLIC_WIFI_MCDONALDS_4_BARS = 39
+  PUBLIC_WIFI_MCDONALDS_2_BARS = 40
+  PUBLIC_WIFI_MCDONALDS_1_BAR = 41
+  PUBLIC_WIFI_KOHLS_5_BARS = 42
+  PUBLIC_WIFI_KOHLS_4_BARS = 43
+  PUBLIC_WIFI_KOHLS_2_BARS = 44
+  PUBLIC_WIFI_ATANDT_5_BARS = 45
+  PUBLIC_WIFI_ATANDT_4_BARS = 46
+  PUBLIC_WIFI_ATANDT_2_BARS = 47
+  PUBLIC_WIFI_ATANDT_1_BAR = 48
+  BOINGO = 49
\ No newline at end of file
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index 8875096..b69c7b2 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -73,6 +73,7 @@
     self._api_secret = device_json.get('api_secret', None)
     self._device_oem = device_json.get('device_oem', None)
     self._device_type = device_json.get('device_type', 'Android')
+    self._network_config = device_json.get('network_config', None)
     self._remote_device = device_json.get('remote_device', None)
     self._remote_device_minimum_os = device_json.get(
         'remote_device_minimum_os', None)
@@ -81,9 +82,7 @@
     self._results_path = device_json.get('results_path', None)
     self._runner_package = device_json.get('runner_package', None)
     self._runner_type = device_json.get('runner_type', None)
-    if 'timeouts' in device_json:
-      for key in device_json['timeouts']:
-        self._timeouts[key] = device_json['timeouts'][key]
+    self._timeouts.update(device_json.get('timeouts', {}))
 
     def command_line_override(
         file_value, cmd_line_value, desc, print_value=True):
@@ -107,6 +106,8 @@
         self._device_oem, args.device_oem, 'device_oem')
     self._device_type = command_line_override(
         self._device_type, args.device_type, 'device_type')
+    self._network_config = command_line_override(
+        self._network_config, args.network_config, 'network_config')
     self._remote_device = command_line_override(
         self._remote_device, args.remote_device, 'remote_device')
     self._remote_device_minimum_os = command_line_override(
@@ -325,6 +326,10 @@
     return self._device['device_type_id']
 
   @property
+  def network_config(self):
+    return self._network_config
+
+  @property
   def only_output_failures(self):
     # TODO(jbudorick): Remove this once b/18981674 is fixed.
     return True
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py
index 4a155ac..7aa91ae 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -14,6 +14,7 @@
 
 from pylib import constants
 from pylib.base import test_run
+from pylib.remote.device import appurify_constants
 from pylib.remote.device import appurify_sanitized
 from pylib.remote.device import remote_device_helper
 from pylib.utils import zip_utils
@@ -230,7 +231,10 @@
       self._test_id = self._UploadTestToDevice('robotium', test_path)
 
     logging.info('Setting config: %s' % config)
-    self._SetTestConfig('robotium', config)
+    appurify_configs = {}
+    if self._env.network_config:
+      appurify_configs['network'] = self._env.network_config
+    self._SetTestConfig('robotium', config, **appurify_configs)
 
   def _UploadAppToDevice(self, app_path):
     """Upload app to device."""
@@ -259,21 +263,32 @@
           'Unable to upload %s.' % test_path)
       return upload_results.json()['response']['test_id']
 
-  def _SetTestConfig(self, runner_type, body):
+  def _SetTestConfig(self, runner_type, runner_configs,
+                     network=appurify_constants.NETWORK.WIFI_1_BAR,
+                     pcap=0, profiler=0, videocapture=0):
     """Generates and uploads config file for test.
     Args:
-      extras: Extra arguments to set in the config file.
+      runner_configs: Configs specific to the runner you are using.
+      network: Config to specify the network environment the devices running
+          the tests will be in.
+      pcap: Option to set the recording the of network traffic from the device.
+      profiler: Option to set the recording of CPU, memory, and network
+          transfer usage in the tests.
+      videocapture: Option to set video capture during the tests.
+
     """
     logging.info('Generating config file for test.')
     with tempfile.TemporaryFile() as config:
       config_data = [
-        '[appurify]',
-        'pcap=0',
-        'profiler=0',
-        'videocapture=0',
-        '[%s]' % runner_type
+          '[appurify]',
+          'network=%s' % network,
+          'pcap=%s' % pcap,
+          'profiler=%s' % profiler,
+          'videocapture=%s' % videocapture,
+          '[%s]' % runner_type
       ]
-      config_data.extend('%s=%s' % (k, v) for k, v in body.iteritems())
+      config_data.extend(
+          '%s=%s' % (k, v) for k, v in runner_configs.iteritems())
       config.write(''.join('%s\n' % l for l in config_data))
       config.flush()
       config.seek(0)
@@ -282,4 +297,4 @@
         config_response = appurify_sanitized.api.config_upload(
             self._env.token, config, self._test_id)
       remote_device_helper.TestHttpResponse(
-          config_response, 'Unable to upload test config.')
+          config_response, 'Unable to upload test config.')
\ No newline at end of file
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py
index c34244e..65664e3 100644
--- a/build/android/pylib/results/json_results.py
+++ b/build/android/pylib/results/json_results.py
@@ -16,6 +16,38 @@
     A results dict that mirrors the one generated by
       base/test/launcher/test_results_tracker.cc:SaveSummaryAsJSON.
   """
+  # Example json output.
+  # {
+  #   "global_tags": [],
+  #   "all_tests": [
+  #     "test1",
+  #     "test2",
+  #    ],
+  #   "disabled_tests": [],
+  #   "per_iteration_data": [
+  #     {
+  #       "test1": [
+  #         {
+  #           "status": "SUCCESS",
+  #           "elapsed_time_ms": 1,
+  #           "output_snippet": "",
+  #           "output_snippet_base64": "",
+  #           "losless_snippet": "",
+  #         },
+  #       ],
+  #       "test2": [
+  #         {
+  #           "status": "FAILURE",
+  #           "elapsed_time_ms": 12,
+  #           "output_snippet": "",
+  #           "output_snippet_base64": "",
+  #           "losless_snippet": "",
+  #         },
+  #       ],
+  #     },
+  #   ],
+  # }
+
   assert isinstance(test_run_result, base_test_result.TestRunResults)
 
   def status_as_string(s):
@@ -71,3 +103,37 @@
   with open(file_path, 'w') as json_result_file:
     json_result_file.write(json.dumps(GenerateResultsDict(test_run_result)))
 
+
+def ParseResultsFromJson(json_results):
+  """Creates a list of BaseTestResult objects from JSON.
+
+  Args:
+    json_results: A JSON dict in the format created by
+                  GenerateJsonResultsFile.
+  """
+
+  def string_as_status(s):
+    if s == 'SUCCESS':
+      return base_test_result.ResultType.PASS
+    elif s == 'SKIPPED':
+      return base_test_result.ResultType.SKIP
+    elif s == 'FAILURE':
+      return base_test_result.ResultType.FAIL
+    elif s == 'CRASH':
+      return base_test_result.ResultType.CRASH
+    elif s == 'TIMEOUT':
+      return base_test_result.ResultType.TIMEOUT
+    else:
+      return base_test_result.ResultType.UNKNOWN
+
+  results_list = []
+  testsuite_runs = json_results['per_iteration_data']
+  for testsuite_run in testsuite_runs:
+    for test, test_runs in testsuite_run.iteritems():
+      results_list.extend(
+          [base_test_result.BaseTestResult(test,
+                                           string_as_status(tr['status']),
+                                           duration=tr['elapsed_time_ms'])
+          for tr in test_runs])
+  return results_list
+
diff --git a/build/android/pylib/screenshot.py b/build/android/pylib/screenshot.py
index e21d756..0fcc590 100644
--- a/build/android/pylib/screenshot.py
+++ b/build/android/pylib/screenshot.py
@@ -2,11 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import logging
 import os
-import signal
 import tempfile
+import time
 
 from pylib import cmd_helper
+from pylib import device_signal
+from pylib.device import device_errors
 
 # TODO(jbudorick) Remove once telemetry gets switched over.
 import pylib.android_commands
@@ -71,7 +74,9 @@
     self._is_started = False
     if not self._recorder:
       return
-    self._device.KillAll('screenrecord', signum=signal.SIGINT)
+    if not self._device.KillAll('screenrecord', signum=device_signal.SIGINT,
+                                quiet=True):
+      logging.warning('Nothing to kill: screenrecord was not running')
     self._recorder.wait()
 
   def Pull(self, host_file=None):
@@ -82,10 +87,13 @@
     Returns:
       Output video file name on the host.
     """
-    host_file_name = host_file or ('screen-recording-%s.mp4' %
-                                   self._device.old_interface.GetTimestamp())
+    # TODO(jbudorick): Merge filename generation with the logic for doing so in
+    # DeviceUtils.
+    host_file_name = (
+        host_file
+        or 'screen-recording-%s.mp4' % time.strftime('%Y%m%dT%H%M%S',
+                                                     time.localtime()))
     host_file_name = os.path.abspath(host_file_name)
-    self._device.old_interface.EnsureHostDirectory(host_file_name)
     self._device.PullFile(self._device_file, host_file_name)
     self._device.RunShellCommand('rm -f "%s"' % self._device_file)
     return host_file_name
diff --git a/build/android/pylib/uiautomator/test_options.py b/build/android/pylib/uiautomator/test_options.py
index b383b20..3f5f950 100644
--- a/build/android/pylib/uiautomator/test_options.py
+++ b/build/android/pylib/uiautomator/test_options.py
@@ -8,7 +8,6 @@
 
 UIAutomatorOptions = collections.namedtuple('UIAutomatorOptions', [
     'tool',
-    'cleanup_test_files',
     'annotations',
     'exclude_annotations',
     'test_filter',
diff --git a/build/android/pylib/uiautomator/test_runner.py b/build/android/pylib/uiautomator/test_runner.py
index d7a4bdf..296bd47 100644
--- a/build/android/pylib/uiautomator/test_runner.py
+++ b/build/android/pylib/uiautomator/test_runner.py
@@ -26,7 +26,6 @@
     # Create an InstrumentationOptions object to pass to the super class
     instrumentation_options = instr_test_options.InstrumentationOptions(
         test_options.tool,
-        test_options.cleanup_test_files,
         test_options.annotations,
         test_options.exclude_annotations,
         test_options.test_filter,
diff --git a/build/android/pylib/utils/emulator.py b/build/android/pylib/utils/emulator.py
index 81b9c98..26b9109 100644
--- a/build/android/pylib/utils/emulator.py
+++ b/build/android/pylib/utils/emulator.py
@@ -19,6 +19,7 @@
 from pylib import cmd_helper
 from pylib import constants
 from pylib import pexpect
+from pylib.device import device_errors
 from pylib.device import device_utils
 from pylib.utils import time_profile
 
@@ -394,33 +395,30 @@
     """
     seconds_waited = 0
     number_of_waits = 2  # Make sure we can wfd twice
-    # TODO(jbudorick) Un-handroll this in the implementation switch.
-    adb_cmd = "adb -s %s %s" % (self.device_serial, 'wait-for-device')
+
+    device = device_utils.DeviceUtils(self.device_serial)
     while seconds_waited < self._LAUNCH_TIMEOUT:
       try:
-        run_command.RunCommand(adb_cmd,
-                               timeout_time=self._WAITFORDEVICE_TIMEOUT,
-                               retry_count=1)
+        device.adb.WaitForDevice(
+            timeout=self._WAITFORDEVICE_TIMEOUT, retries=1)
         number_of_waits -= 1
         if not number_of_waits:
           break
-      except errors.WaitForResponseTimedOutError:
+      except device_errors.CommandTimeoutError:
         seconds_waited += self._WAITFORDEVICE_TIMEOUT
-        adb_cmd = "adb -s %s %s" % (self.device_serial, 'kill-server')
-        run_command.RunCommand(adb_cmd)
+        device.adb.KillServer()
       self.popen.poll()
       if self.popen.returncode != None:
         raise EmulatorLaunchException('EMULATOR DIED')
+
     if seconds_waited >= self._LAUNCH_TIMEOUT:
       raise EmulatorLaunchException('TIMEOUT with wait-for-device')
+
     logging.info('Seconds waited on wait-for-device: %d', seconds_waited)
     if wait_for_boot:
       # Now that we checked for obvious problems, wait for a boot complete.
       # Waiting for the package manager is sometimes problematic.
-      # TODO(jbudorick) Convert this once waiting for the package manager and
-      #                 the external storage is no longer problematic.
-      d = device_utils.DeviceUtils(self.device_serial)
-      d.old_interface.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT)
+      device.WaitUntilFullyBooted(timeout=self._WAITFORBOOT_TIMEOUT)
 
   def Shutdown(self):
     """Shuts down the process started by launch."""
diff --git a/build/android/pylib/utils/findbugs.py b/build/android/pylib/utils/findbugs.py
index 82408b0..8deb0fe 100644
--- a/build/android/pylib/utils/findbugs.py
+++ b/build/android/pylib/utils/findbugs.py
@@ -2,254 +2,153 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import optparse
+import argparse
+import logging
 import os
 import re
 import shlex
-import subprocess
 import sys
+import xml.dom.minidom
 
 from pylib import cmd_helper
 from pylib import constants
 
 
-def _PrintMessage(warnings, title, action, known_bugs_file):
-  if warnings:
-    print
-    print '*' * 80
-    print '%s warnings.' % title
-    print '%s %s' % (action, known_bugs_file)
-    print '-' * 80
-    for warning in warnings:
-      print warning
-    print '-' * 80
-    print
+_FINDBUGS_HOME = os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
+                              'findbugs')
+_FINDBUGS_JAR = os.path.join(_FINDBUGS_HOME, 'lib', 'findbugs.jar')
+_FINDBUGS_MAX_HEAP = 768
+_FINDBUGS_PLUGIN_PATH = os.path.join(
+    constants.DIR_SOURCE_ROOT, 'tools', 'android', 'findbugs_plugin', 'lib',
+    'chromiumPlugin.jar')
 
 
-def _StripLineNumbers(current_warnings):
-  re_line = r':\[line.*?\]$'
-  return [re.sub(re_line, '', x) for x in current_warnings]
+def _ParseXmlResults(results_doc):
+  warnings = set()
+  for en in (n for n in results_doc.documentElement.childNodes
+             if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+    if en.tagName == 'BugInstance':
+      warnings.add(_ParseBugInstance(en))
+  return warnings
 
 
-def _DiffKnownWarnings(current_warnings_set, known_bugs_file):
-  if os.path.exists(known_bugs_file):
-    with open(known_bugs_file, 'r') as known_bugs:
-      known_bugs_set = set(known_bugs.read().splitlines())
-  else:
-    known_bugs_set = set()
-
-  new_warnings = current_warnings_set - known_bugs_set
-  _PrintMessage(sorted(new_warnings), 'New', 'Please fix, or perhaps add to',
-                known_bugs_file)
-
-  obsolete_warnings = known_bugs_set - current_warnings_set
-  _PrintMessage(sorted(obsolete_warnings), 'Obsolete', 'Please remove from',
-                known_bugs_file)
-
-  count = len(new_warnings) + len(obsolete_warnings)
-  if count:
-    print '*** %d FindBugs warning%s! ***' % (count, 's' * (count > 1))
-    if len(new_warnings):
-      print '*** %d: new ***' % len(new_warnings)
-    if len(obsolete_warnings):
-      print '*** %d: obsolete ***' % len(obsolete_warnings)
-    print
-    print 'Alternatively,  rebaseline with --rebaseline command option'
-    print
-  else:
-    print 'No new FindBugs warnings.'
-  print
-  return count
+def _GetMessage(node):
+  for c in (n for n in node.childNodes
+            if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+    if c.tagName == 'Message':
+      if (len(c.childNodes) == 1
+          and c.childNodes[0].nodeType == xml.dom.Node.TEXT_NODE):
+        return c.childNodes[0].data
+  return None
 
 
-def _Rebaseline(current_warnings_set, known_bugs_file):
-  with file(known_bugs_file, 'w') as known_bugs:
-    for warning in sorted(current_warnings_set):
-      print >> known_bugs, warning
-  return 0
+def _ParseBugInstance(node):
+  bug = FindBugsWarning(node.getAttribute('type'))
+  msg_parts = []
+  for c in (n for n in node.childNodes
+            if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+    if c.tagName == 'Class':
+      msg_parts.append(_GetMessage(c))
+    elif c.tagName == 'Method':
+      msg_parts.append(_GetMessage(c))
+    elif c.tagName == 'Field':
+      msg_parts.append(_GetMessage(c))
+    elif c.tagName == 'SourceLine':
+      bug.file_name = c.getAttribute('sourcefile')
+      if c.hasAttribute('start'):
+        bug.start_line = int(c.getAttribute('start'))
+      if c.hasAttribute('end'):
+        bug.end_line = int(c.getAttribute('end'))
+      msg_parts.append(_GetMessage(c))
+    elif (c.tagName == 'ShortMessage' and len(c.childNodes) == 1
+          and c.childNodes[0].nodeType == xml.dom.Node.TEXT_NODE):
+      msg_parts.append(c.childNodes[0].data)
+  bug.message = tuple(m for m in msg_parts if m)
+  return bug
 
 
-def _GetChromeJars(release_version):
-  version = 'Debug'
-  if release_version:
-    version = 'Release'
-  path = os.path.join(constants.DIR_SOURCE_ROOT,
-                      os.environ.get('CHROMIUM_OUT_DIR', 'out'),
-                      version,
-                      'lib.java')
-  cmd = 'find %s -name "*.jar"' % path
-  out = cmd_helper.GetCmdOutput(shlex.split(cmd))
-  out = [p for p in out.splitlines() if not p.endswith('.dex.jar')]
-  if not out:
-    print 'No classes found in %s' % path
-  return ' '.join(out)
+class FindBugsWarning(object):
+
+  def __init__(self, bug_type='', end_line=0, file_name='', message=None,
+               start_line=0):
+    self.bug_type = bug_type
+    self.end_line = end_line
+    self.file_name = file_name
+    if message is None:
+      self.message = tuple()
+    else:
+      self.message = message
+    self.start_line = start_line
+
+  def __cmp__(self, other):
+    return (cmp(self.file_name, other.file_name)
+            or cmp(self.start_line, other.start_line)
+            or cmp(self.end_line, other.end_line)
+            or cmp(self.bug_type, other.bug_type)
+            or cmp(self.message, other.message))
+
+  def __eq__(self, other):
+    return self.__dict__ == other.__dict__
+
+  def __hash__(self):
+    return hash((self.bug_type, self.end_line, self.file_name, self.message,
+                 self.start_line))
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __str__(self):
+    return '%s: %s' % (self.bug_type, '\n  '.join(self.message))
 
 
-def _Run(exclude, known_bugs, classes_to_analyze, auxiliary_classes,
-        rebaseline, release_version, findbug_args):
-  """Run the FindBugs.
+def Run(exclude, classes_to_analyze, auxiliary_classes, output_file,
+        findbug_args, jars):
+  """Run FindBugs.
 
   Args:
     exclude: the exclude xml file, refer to FindBugs's -exclude command option.
-    known_bugs: the text file of known bugs. The bugs in it will not be
-                reported.
     classes_to_analyze: the list of classes need to analyze, refer to FindBug's
                         -onlyAnalyze command line option.
     auxiliary_classes: the classes help to analyze, refer to FindBug's
                        -auxclasspath command line option.
-    rebaseline: True if the known_bugs file needs rebaseline.
-    release_version: True if the release version needs check, otherwise check
-                     debug version.
-    findbug_args: addtional command line options needs pass to Findbugs.
+    output_file: An optional path to dump XML results to.
+    findbug_args: A list of addtional command line options to pass to Findbugs.
   """
+  # TODO(jbudorick): Get this from the build system.
+  system_classes = [
+    os.path.join(constants.ANDROID_SDK_ROOT, 'platforms',
+                 'android-%s' % constants.ANDROID_SDK_VERSION, 'android.jar')
+  ]
+  system_classes.extend(os.path.abspath(classes)
+                        for classes in auxiliary_classes or [])
 
-  chrome_src = constants.DIR_SOURCE_ROOT
-  sdk_root = constants.ANDROID_SDK_ROOT
-  sdk_version = constants.ANDROID_SDK_VERSION
-
-  system_classes = []
-  system_classes.append(os.path.join(sdk_root, 'platforms',
-                                     'android-%s' % sdk_version, 'android.jar'))
-  if auxiliary_classes:
-    for classes in auxiliary_classes:
-      system_classes.append(os.path.abspath(classes))
-
-  findbugs_javacmd = 'java'
-  findbugs_home = os.path.join(chrome_src, 'third_party', 'findbugs')
-  findbugs_jar = os.path.join(findbugs_home, 'lib', 'findbugs.jar')
-  findbugs_pathsep = ':'
-  findbugs_maxheap = '768'
-
-  cmd = '%s ' % findbugs_javacmd
-  cmd = '%s -classpath %s%s' % (cmd, findbugs_jar, findbugs_pathsep)
-  cmd = '%s -Xmx%sm ' % (cmd, findbugs_maxheap)
-  cmd = '%s -Dfindbugs.home="%s" ' % (cmd, findbugs_home)
-  cmd = '%s -jar %s ' % (cmd, findbugs_jar)
-
-  cmd = '%s -textui -sortByClass ' % cmd
-  cmd = '%s -pluginList %s' % (cmd, os.path.join(chrome_src, 'tools', 'android',
-                                                 'findbugs_plugin', 'lib',
-                                                 'chromiumPlugin.jar'))
-  if len(system_classes):
-    cmd = '%s -auxclasspath %s ' % (cmd, ':'.join(system_classes))
-
+  cmd = ['java',
+         '-classpath', '%s:' % _FINDBUGS_JAR,
+         '-Xmx%dm' % _FINDBUGS_MAX_HEAP,
+         '-Dfindbugs.home="%s"' % _FINDBUGS_HOME,
+         '-jar', _FINDBUGS_JAR,
+         '-textui', '-sortByClass',
+         '-pluginList', _FINDBUGS_PLUGIN_PATH, '-xml:withMessages']
+  if system_classes:
+    cmd.extend(['-auxclasspath', ':'.join(system_classes)])
   if classes_to_analyze:
-    cmd = '%s -onlyAnalyze %s ' % (cmd, classes_to_analyze)
-
+    cmd.extend(['-onlyAnalyze', classes_to_analyze])
   if exclude:
-    cmd = '%s -exclude %s ' % (cmd, os.path.abspath(exclude))
-
+    cmd.extend(['-exclude', os.path.abspath(exclude)])
+  if output_file:
+    cmd.extend(['-output', output_file])
   if findbug_args:
-    cmd = '%s %s ' % (cmd, findbug_args)
+    cmd.extend(findbug_args)
+  cmd.extend(os.path.abspath(j) for j in jars or [])
 
-  chrome_classes = _GetChromeJars(release_version)
-  if not chrome_classes:
-    return 1
-  cmd = '%s %s ' % (cmd, chrome_classes)
-
-  print
-  print '*' * 80
-  print 'Command used to run findbugs:'
-  print cmd
-  print '*' * 80
-  print
-
-  proc = subprocess.Popen(shlex.split(cmd),
-                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-  out, _err = proc.communicate()
-  current_warnings_set = set(_StripLineNumbers(filter(None, out.splitlines())))
-
-  if rebaseline:
-    return _Rebaseline(current_warnings_set, known_bugs)
+  if output_file:
+    cmd_helper.RunCmd(cmd)
+    results_doc = xml.dom.minidom.parse(output_file)
   else:
-    return _DiffKnownWarnings(current_warnings_set, known_bugs)
+    raw_out = cmd_helper.GetCmdOutput(cmd)
+    results_doc = xml.dom.minidom.parseString(raw_out)
 
-def Run(options):
-  exclude_file = None
-  known_bugs_file = None
+  current_warnings_set = _ParseXmlResults(results_doc)
 
-  if options.exclude:
-    exclude_file = options.exclude
-  elif options.base_dir:
-    exclude_file = os.path.join(options.base_dir, 'findbugs_exclude.xml')
+  return (' '.join(cmd), current_warnings_set)
 
-  if options.known_bugs:
-    known_bugs_file = options.known_bugs
-  elif options.base_dir:
-    known_bugs_file = os.path.join(options.base_dir, 'findbugs_known_bugs.txt')
-
-  auxclasspath = None
-  if options.auxclasspath:
-    auxclasspath = options.auxclasspath.split(':')
-  return _Run(exclude_file, known_bugs_file, options.only_analyze, auxclasspath,
-              options.rebaseline, options.release_build, options.findbug_args)
-
-
-def GetCommonParser():
-  parser = optparse.OptionParser()
-  parser.add_option('-r',
-                    '--rebaseline',
-                    action='store_true',
-                    dest='rebaseline',
-                    help='Rebaseline known findbugs issues.')
-
-  parser.add_option('-a',
-                    '--auxclasspath',
-                    action='store',
-                    default=None,
-                    dest='auxclasspath',
-                    help='Set aux classpath for analysis.')
-
-  parser.add_option('-o',
-                    '--only-analyze',
-                    action='store',
-                    default=None,
-                    dest='only_analyze',
-                    help='Only analyze the given classes and packages.')
-
-  parser.add_option('-e',
-                    '--exclude',
-                    action='store',
-                    default=None,
-                    dest='exclude',
-                    help='Exclude bugs matching given filter.')
-
-  parser.add_option('-k',
-                    '--known-bugs',
-                    action='store',
-                    default=None,
-                    dest='known_bugs',
-                    help='Not report the bugs in the given file.')
-
-  parser.add_option('-l',
-                    '--release-build',
-                    action='store_true',
-                    dest='release_build',
-                    help='Analyze release build instead of debug.')
-
-  parser.add_option('-f',
-                    '--findbug-args',
-                    action='store',
-                    default=None,
-                    dest='findbug_args',
-                    help='Additional findbug arguments.')
-
-  parser.add_option('-b',
-                    '--base-dir',
-                    action='store',
-                    default=None,
-                    dest='base_dir',
-                    help='Base directory for configuration file.')
-
-  return parser
-
-
-def main():
-  parser = GetCommonParser()
-  options, _ = parser.parse_args()
-
-  return Run(options)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index fcbe427..90d5ca0 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -24,12 +24,16 @@
 
 
 def DefaultConfigVariables():
+  # Note: This list must match the --config-vars in build/isolate.gypi
   return {
     'CONFIGURATION_NAME': constants.GetBuildType(),
     'OS': 'android',
     'asan': '0',
+    'branding': 'Chromium',
     'chromeos': '0',
     'component': 'static_library',
+    'enable_pepper_cdms': '0',
+    'enable_plugins': '0',
     'fastbuild': '0',
     'icu_use_data_file_flag': '1',
     'lsan': '0',
@@ -39,6 +43,7 @@
     'tsan': '0',
     'use_custom_libcxx': '0',
     'use_instrumented_libraries': '0',
+    'use_prebuilt_instrumented_libraries': '0',
     'use_openssl': '0',
     'use_ozone': '0',
     'use_x11': '0',
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py
index da3cd15..4d7d0b0 100644
--- a/build/android/pylib/utils/md5sum.py
+++ b/build/android/pylib/utils/md5sum.py
@@ -5,6 +5,7 @@
 import collections
 import logging
 import os
+import re
 import tempfile
 import types
 
@@ -12,8 +13,6 @@
 from pylib import constants
 from pylib.utils import device_temp_file
 
-HashAndPath = collections.namedtuple('HashAndPath', ['hash', 'path'])
-
 MD5SUM_DEVICE_LIB_PATH = '/data/local/tmp/md5sum/'
 MD5SUM_DEVICE_BIN_PATH = MD5SUM_DEVICE_LIB_PATH + 'md5sum_bin'
 
@@ -21,6 +20,8 @@
     'test -f {path} -o -d {path} '
     '&& LD_LIBRARY_PATH={md5sum_lib} {device_pie_wrapper} {md5sum_bin} {path}')
 
+_STARTS_WITH_CHECKSUM_RE = re.compile(r'^\s*[0-9a-fA-f]{32}\s+')
+
 
 def CalculateHostMd5Sums(paths):
   """Calculates the MD5 sum value for all items in |paths|.
@@ -28,7 +29,7 @@
   Args:
     paths: A list of host paths to md5sum.
   Returns:
-    A list of named tuples with 'hash' and 'path' attributes.
+    A dict mapping paths to their respective md5sum checksums.
   """
   if isinstance(paths, basestring):
     paths = [paths]
@@ -36,7 +37,8 @@
   out = cmd_helper.GetCmdOutput(
       [os.path.join(constants.GetOutDirectory(), 'md5sum_bin_host')] +
           [p for p in paths])
-  return [HashAndPath(*l.split(None, 1)) for l in out.splitlines()]
+
+  return _ParseMd5SumOutput(out.splitlines())
 
 
 def CalculateDeviceMd5Sums(paths, device):
@@ -45,7 +47,7 @@
   Args:
     paths: A list of device paths to md5sum.
   Returns:
-    A list of named tuples with 'hash' and 'path' attributes.
+    A dict mapping paths to their respective md5sum checksums.
   """
   if isinstance(paths, basestring):
     paths = [paths]
@@ -72,5 +74,11 @@
       device.adb.Push(md5sum_script_file.name, md5sum_device_script_file.name)
       out = device.RunShellCommand(['sh', md5sum_device_script_file.name])
 
-  return [HashAndPath(*l.split(None, 1)) for l in out if l]
+  return _ParseMd5SumOutput(out)
+
+
+def _ParseMd5SumOutput(out):
+  hash_and_path = (l.split(None, 1) for l in out
+                   if l and _STARTS_WITH_CHECKSUM_RE.match(l))
+  return dict((p, h) for h, p in hash_and_path)
 
diff --git a/build/android/pylib/utils/md5sum_test.py b/build/android/pylib/utils/md5sum_test.py
index 6c689fb..de9cd35 100755
--- a/build/android/pylib/utils/md5sum_test.py
+++ b/build/android/pylib/utils/md5sum_test.py
@@ -39,8 +39,9 @@
     with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
       out = md5sum.CalculateHostMd5Sums(test_path)
       self.assertEquals(1, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/test/host/file.dat', out[0].path)
+      self.assertTrue('/test/host/file.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/test/host/file.dat'])
       mock_get_cmd_output.assert_called_once_with(
           [HOST_MD5_EXECUTABLE, '/test/host/file.dat'])
 
@@ -52,10 +53,12 @@
     with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
       out = md5sum.CalculateHostMd5Sums(test_paths)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/test/host/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/test/host/file1.dat', out[1].path)
+      self.assertTrue('/test/host/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/test/host/file0.dat'])
+      self.assertTrue('/test/host/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/test/host/file1.dat'])
       mock_get_cmd_output.assert_called_once_with(
           [HOST_MD5_EXECUTABLE, '/test/host/file0.dat',
            '/test/host/file1.dat'])
@@ -68,10 +71,12 @@
     with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
       out = md5sum.CalculateHostMd5Sums(test_paths)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/test/host/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/test/host/file1.dat', out[1].path)
+      self.assertTrue('/test/host/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/test/host/file0.dat'])
+      self.assertTrue('/test/host/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/test/host/file1.dat'])
       mock_get_cmd_output.assert_called_once_with(
           [HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat'])
 
@@ -99,8 +104,9 @@
                     new=mock_device_temp_file)):
       out = md5sum.CalculateDeviceMd5Sums(test_path, device)
       self.assertEquals(1, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file.dat', out[0].path)
+      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file.dat'])
       device.adb.Push.assert_called_once_with(
           '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
       device.RunShellCommand.assert_called_once_with(
@@ -132,10 +138,12 @@
                     new=mock_device_temp_file)):
       out = md5sum.CalculateDeviceMd5Sums(test_path, device)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file0.dat'])
+      self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/storage/emulated/legacy/test/file1.dat'])
       device.adb.Push.assert_called_once_with(
           '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
       device.RunShellCommand.assert_called_once_with(
@@ -168,10 +176,47 @@
                     new=mock_device_temp_file)):
       out = md5sum.CalculateDeviceMd5Sums(test_path, device)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file0.dat'])
+      self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/storage/emulated/legacy/test/file1.dat'])
+      device.adb.Push.assert_called_once_with(
+          '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
+      device.RunShellCommand.assert_called_once_with(
+          ['sh', '/data/local/tmp/test/script/file.sh'])
+
+  def testCalculateDeviceMd5Sums_singlePath_linkerWarning(self):
+    # See crbug/479966
+    test_path = '/storage/emulated/legacy/test/file.dat'
+
+    device = mock.NonCallableMock()
+    device.adb = mock.NonCallableMock()
+    device.adb.Push = mock.Mock()
+    device_md5sum_output = [
+        'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: '
+            'unused DT entry: type 0x1d arg 0x15db',
+        '0123456789abcdeffedcba9876543210 '
+            '/storage/emulated/legacy/test/file.dat',
+    ]
+    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
+
+    mock_temp_file = mock.mock_open()
+    mock_temp_file.return_value.name = '/tmp/test/script/file.sh'
+
+    mock_device_temp_file = mock.mock_open()
+    mock_device_temp_file.return_value.name = (
+        '/data/local/tmp/test/script/file.sh')
+
+    with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), (
+         mock.patch('pylib.utils.device_temp_file.DeviceTempFile',
+                    new=mock_device_temp_file)):
+      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
+      self.assertEquals(1, len(out))
+      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file.dat'])
       device.adb.Push.assert_called_once_with(
           '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
       device.RunShellCommand.assert_called_once_with(
diff --git a/build/android/pylib/utils/mock_calls.py b/build/android/pylib/utils/mock_calls.py
index 3052b0d..59167ba 100644
--- a/build/android/pylib/utils/mock_calls.py
+++ b/build/android/pylib/utils/mock_calls.py
@@ -36,7 +36,7 @@
           expected_call, action = self._expected_calls.pop(0)
           self._test_case.assertTrue(
               received_call == expected_call,
-              msg=('Expected call missmatch:\n'
+              msg=('Expected call mismatch:\n'
                    '  expected: %s\n'
                    '  received: %s\n'
                    % (str(expected_call), str(received_call))))
diff --git a/build/android/pylib/utils/test_environment.py b/build/android/pylib/utils/test_environment.py
index 4d88a45..e78eb5c 100644
--- a/build/android/pylib/utils/test_environment.py
+++ b/build/android/pylib/utils/test_environment.py
@@ -34,13 +34,14 @@
   """Clean up the test environment, restarting fresh adb and HTTP daemons."""
   _KillWebServers()
   device_utils.RestartServer()
-  p = device_utils.DeviceUtils.parallel()
-  p.old_interface.RestartAdbdOnDevice()
-  try:
-    p.EnableRoot()
-  except device_errors.CommandFailedError as e:
-    # TODO(jbudorick) Handle this exception appropriately after interface
-    #                 conversions are finished.
-    logging.error(str(e))
-  p.WaitUntilFullyBooted()
+
+  def cleanup_device(d):
+    d.old_interface.RestartAdbdOnDevice()
+    try:
+      d.EnableRoot()
+    except device_errors.CommandFailedError as e:
+      logging.error(str(e))
+    d.WaitUntilFullyBooted()
+
+  device_utils.DeviceUtils.parallel().pMap(cleanup_device)
 
diff --git a/build/android/screenshot.py b/build/android/screenshot.py
index 8fe2a95..c48a255 100755
--- a/build/android/screenshot.py
+++ b/build/android/screenshot.py
@@ -11,8 +11,8 @@
 import os
 import sys
 
-from pylib import android_commands
 from pylib import screenshot
+from pylib.device import device_errors
 from pylib.device import device_utils
 
 def _PrintMessage(heading, eol='\n'):
@@ -66,21 +66,25 @@
 
   (options, args) = parser.parse_args()
 
-  if options.verbose:
-    logging.getLogger().setLevel(logging.DEBUG)
-
-  devices = android_commands.GetAttachedDevices()
-
-  if not options.device and len(devices) > 1:
-    parser.error('Multiple devices are attached. '
-                 'Please specify device serial number with --device.')
-  elif not options.device and len(devices) == 1:
-    options.device = devices[0]
-
   if len(args) > 1:
     parser.error('Too many positional arguments.')
   host_file = args[0] if args else options.file
-  device = device_utils.DeviceUtils(options.device)
+
+  if options.verbose:
+    logging.getLogger().setLevel(logging.DEBUG)
+
+  devices = device_utils.DeviceUtils.HealthyDevices()
+
+  if not options.device:
+    if len(devices) > 1:
+      parser.error('Multiple devices are attached. '
+                   'Please specify device serial number with --device.')
+    elif len(devices) == 1:
+      device = devices[0]
+    else:
+      raise device_errors.NoDevicesError()
+  else:
+    device = device_utils.DeviceUtils(options.device)
 
   if options.video:
     _CaptureVideo(device, host_file, options)
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 368ac06..c54ed28 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -152,6 +152,9 @@
                            'Overrides all other flags.'))
   group.add_argument('--remote-device-timeout', type=int,
                      help='Times to retry finding remote device')
+  group.add_argument('--network-config', type=int,
+                     help='Integer that specifies the network environment '
+                          'that the tests will be run in.')
 
   device_os_group = group.add_mutually_exclusive_group()
   device_os_group.add_argument('--remote-device-minimum-os',
@@ -175,9 +178,6 @@
 def AddDeviceOptions(parser):
   """Adds device options to |parser|."""
   group = parser.add_argument_group(title='Device Options')
-  group.add_argument('-c', dest='cleanup_test_files',
-                     help='Cleanup test files on the device after run',
-                     action='store_true')
   group.add_argument('--tool',
                      dest='tool',
                      help=('Run the test under a tool '
@@ -372,7 +372,6 @@
   # TODO(jbudorick): Get rid of InstrumentationOptions.
   return instrumentation_test_options.InstrumentationOptions(
       args.tool,
-      args.cleanup_test_files,
       args.annotations,
       args.exclude_annotations,
       args.test_filter,
@@ -437,7 +436,6 @@
 
   return uiautomator_test_options.UIAutomatorOptions(
       args.tool,
-      args.cleanup_test_files,
       args.annotations,
       args.exclude_annotations,
       args.test_filter,
@@ -636,7 +634,6 @@
     # into the gtest code.
     gtest_options = gtest_test_options.GTestOptions(
         args.tool,
-        args.cleanup_test_files,
         args.test_filter,
         args.run_disabled,
         args.test_arguments,
@@ -768,7 +765,16 @@
 def _RunJUnitTests(args):
   """Subcommand of RunTestsCommand which runs junit tests."""
   runner_factory, tests = junit_setup.Setup(args)
-  _, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
+  results, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
+
+  report_results.LogFull(
+      results=results,
+      test_type='JUnit',
+      test_package=args.test_suite)
+
+  if args.json_results_file:
+    json_results.GenerateJsonResultsFile(results, args.json_results_file)
+
   return exit_code
 
 
diff --git a/build/android/tombstones.py b/build/android/tombstones.py
index 1a958ac..c83a584 100755
--- a/build/android/tombstones.py
+++ b/build/android/tombstones.py
@@ -19,7 +19,7 @@
 import sys
 import optparse
 
-from pylib import android_commands
+from pylib.device import adb_wrapper
 from pylib.device import device_errors
 from pylib.device import device_utils
 from pylib.utils import run_tests_helper
@@ -233,19 +233,19 @@
   options, _ = parser.parse_args()
 
   if options.device:
-    devices = [options.device]
+    devices = [device_utils.DeviceUtils(options.device)]
   else:
-    devices = android_commands.GetAttachedDevices()
+    devices = device_utils.DeviceUtils.HealthyDevices()
 
   # This must be done serially because strptime can hit a race condition if
   # used for the first time in a multithreaded environment.
   # http://bugs.python.org/issue7980
   tombstones = []
-  for device_serial in devices:
-    device = device_utils.DeviceUtils(device_serial)
+  for device in devices:
     tombstones += _GetTombstonesForDevice(device, options)
 
   _ResolveTombstones(options.jobs, tombstones)
 
+
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/build/android/update_verification.py b/build/android/update_verification.py
index fe89567..45c6e98 100755
--- a/build/android/update_verification.py
+++ b/build/android/update_verification.py
@@ -12,12 +12,11 @@
 import sys
 import time
 
-from pylib import android_commands
 from pylib.device import device_utils
 
 def _SaveAppData(device, package_name, from_apk=None, data_dir=None):
   def _BackupAppData(data_dir=None):
-    device.old_interface.Adb().SendCommand('backup %s' % package_name)
+    device.adb.Backup(package_name)
     backup_file = os.path.join(os.getcwd(), 'backup.ab')
     assert os.path.exists(backup_file), 'Backup failed.'
     if data_dir:
@@ -29,8 +28,7 @@
 
   if from_apk:
     logging.info('Installing %s...', from_apk)
-    # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-    output = device.old_interface.Install(from_apk, reinstall=True)
+    output = device.Install(from_apk, reinstall=True)
     if 'Success' not in output:
       raise Exception('Unable to install %s. output: %s' % (from_apk, output))
 
@@ -42,14 +40,13 @@
 def _VerifyAppUpdate(device, to_apk, app_data, from_apk=None):
   def _RestoreAppData():
     assert os.path.exists(app_data), 'Backup file does not exist!'
-    device.old_interface.Adb().SendCommand('restore %s' % app_data)
+    device.adb.Restore(app_data)
     # It seems restore command is not synchronous.
     time.sleep(15)
 
   if from_apk:
     logging.info('Installing %s...', from_apk)
-    # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-    output = device.old_interface.Install(from_apk, reinstall=True)
+    output = device.Install(from_apk, reinstall=True)
     if 'Success' not in output:
       raise Exception('Unable to install %s. output: %s' % (from_apk, output))
 
@@ -59,8 +56,7 @@
 
   logging.info('Verifying that %s cannot be installed side-by-side...',
                to_apk)
-  # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-  output = device.old_interface.Install(to_apk)
+  output = device.Install(to_apk)
   if 'INSTALL_FAILED_ALREADY_EXISTS' not in output:
     if 'Success' in output:
       raise Exception('Package name has changed! output: %s' % output)
@@ -68,8 +64,7 @@
       raise Exception(output)
 
   logging.info('Verifying that %s can be overinstalled...', to_apk)
-  # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-  output = device.old_interface.Install(to_apk, reinstall=True)
+  output = device.adb.Install(to_apk, reinstall=True)
   if 'Success' not in output:
     raise Exception('Unable to install %s.\n output: %s' % (to_apk, output))
   logging.info('Successfully updated to the new apk. Please verify that the '
@@ -112,10 +107,10 @@
     parser.print_help(sys.stderr)
     parser.error('Unknown arguments: %s.' % args)
 
-  devices = android_commands.GetAttachedDevices()
+  devices = device_utils.DeviceUtils.HealthyDevices()
   if len(devices) != 1:
     parser.error('Exactly 1 device must be attached.')
-  device = device_utils.DeviceUtils(devices[0])
+  device = devices[0]
 
   if options.from_apk:
     assert os.path.isfile(options.from_apk)
diff --git a/build/apk_test.gypi b/build/apk_test.gypi
index 05bafab..792d92c 100644
--- a/build/apk_test.gypi
+++ b/build/apk_test.gypi
@@ -31,7 +31,7 @@
          'apk_name': '<(test_suite_name)',
          'intermediate_dir': '<(PRODUCT_DIR)/<(test_suite_name)_apk',
          'final_apk_path': '<(intermediate_dir)/<(test_suite_name)-debug.apk',
-         'java_in_dir': '<(DEPTH)/testing/android/java',
+         'java_in_dir': '<(DEPTH)/testing/android/native_test/java',
          'native_lib_target': 'lib<(test_suite_name)',
          # TODO(yfriedman, cjhopman): Support managed installs for gtests.
          'gyp_managed_install': 0,
diff --git a/build/build_config.h b/build/build_config.h
index b07660d..d8c3db6 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -61,8 +61,8 @@
 #error Please add support for your platform in build/build_config.h
 #endif
 
-#if defined(USE_OPENSSL) && defined(USE_NSS)
-#error Cannot use both OpenSSL and NSS
+#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS)
+#error Cannot use both OpenSSL and NSS for certificates
 #endif
 
 // For access to standard BSD features, use OS_BSD instead of a
diff --git a/build/common.gypi b/build/common.gypi
index e900cc4..c5a8fac 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -70,7 +70,10 @@
           # certificates, use_openssl_certs must be set.
           'use_openssl%': 0,
 
-          # Typedef X509Certificate::OSCertHandle to OpenSSL's struct X509*.
+          # Use OpenSSL for representing certificates. When targeting Android,
+          # the platform certificate library is used for certificate
+          # verification. On other targets, this flag also enables OpenSSL for
+          # certificate verification, but this configuration is unsupported.
           'use_openssl_certs%': 0,
 
           # Disable viewport meta tag by default.
@@ -146,6 +149,7 @@
         'enable_hidpi%': '<(enable_hidpi)',
         'buildtype%': '<(buildtype)',
         'branding%': '<(branding)',
+        'branding_path_component%': '<(branding)',
         'host_arch%': '<(host_arch)',
         'target_arch%': '<(target_arch)',
 
@@ -155,12 +159,6 @@
         # default. "default" should be used on non-official builds.
         'android_channel%': 'default',
 
-        # This is set when building the Android WebView inside the Android
-        # build system, using the 'android' gyp backend. The WebView code is
-        # still built when this is unset, but builds using the normal chromium
-        # build system.
-        'android_webview_build%': 0,
-
         # Set ARM architecture version.
         'arm_version%': 7,
 
@@ -191,6 +189,14 @@
         'mips_dsp_rev%': 0,
 
         'conditions': [
+          ['branding == "Chrome"', {
+            'branding_path_component%': 'google_chrome',
+          }],
+
+          ['branding == "Chromium"', {
+            'branding_path_component%': 'chromium',
+          }],
+
           # Ash needs Aura.
           ['use_aura==0', {
             'use_ash%': 0,
@@ -248,14 +254,8 @@
 
           # Set the default "target_subarch" on iOS. Valid values are "arm32",
           # "arm64" and "both" (meaning a fat binary).
-          #
-          # TODO(sdefresne): change the default from "arm32" to "both" for
-          # "target_subarch" once http://crbug.com/339477 is fixed.
-          #
-          # TODO(sdefresne): set the "target_arch" to "arm" once compilation
-          # of skia has been fixed for simulator. http://crbug.com/342377
           ['OS=="ios"', {
-            'target_subarch%': 'arm32',
+            'target_subarch%': 'arm64',
           }],
 
           # Set arch variants for MIPS platforms.
@@ -298,13 +298,13 @@
       'enable_viewport%': '<(enable_viewport)',
       'enable_hidpi%': '<(enable_hidpi)',
       'android_channel%': '<(android_channel)',
-      'android_webview_build%': '<(android_webview_build)',
       'use_goma%': '<(use_goma)',
       'gomadir%': '<(gomadir)',
       'enable_app_list%': '<(enable_app_list)',
       'use_default_render_theme%': '<(use_default_render_theme)',
       'buildtype%': '<(buildtype)',
       'branding%': '<(branding)',
+      'branding_path_component%': '<(branding_path_component)',
       'arm_version%': '<(arm_version)',
       'sysroot%': '<(sysroot)',
       'chroot_cmd%': '<(chroot_cmd)',
@@ -633,14 +633,23 @@
       # compiler. Always do this by default.
       'host_clang%': 1,
 
-      # Variables to control Link-Time Optimizations (LTO).
-      # Note: the variables must *not* be enabled at the same time.
-      #       In this case LTO would 'merge' the optimization flags
-      #       at link-time which would lead to all code be optimized with -O2.
-      # Enable LTO on the code compiled with -Os.
-      # See crbug.com/407544
+      # Variables to control Link-Time Optimization (LTO).
+      # On Android, the variable use_lto enables LTO on code compiled with -Os,
+      # and use_lto_o2 enables LTO on code compiled with -O2. On other
+      # platforms, use_lto enables LTO in all translation units, and use_lto_o2
+      # has no effect.
+      #
+      # On Linux and Android, when using LLVM LTO, the script
+      # build/download_gold_plugin.py must be run to download a linker plugin.
+      # On Mac, LLVM needs to be built from scratch using
+      # tools/clang/scripts/update.py and the absolute path to
+      # third_party/llvm-build/Release+Asserts/lib must be added to
+      # $DYLD_LIBRARY_PATH to pick up the right version of the linker plugin.
+      #
+      # On Android, the variables must *not* be enabled at the same time.
+      # In this case LTO would 'merge' the optimization flags at link-time
+      # which would lead to all code be optimized with -O2. See crbug.com/407544
       'use_lto%': 0,
-      # Enable LTO on code compiled with -O2.
       'use_lto_o2%': 0,
 
       # Allowed level of identical code folding in the gold linker.
@@ -653,9 +662,22 @@
       # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
       'cfi_vptr%': 0,
 
+      # Control Flow Integrity for casts.
+      # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
+      'cfi_derived_cast%': 0,
+      'cfi_unrelated_cast%': 0,
+
+      'cfi_blacklist%': '<(PRODUCT_DIR)/../../tools/cfi/blacklist.txt',
+
       # Whether the entire browser uses toolkit-views on Mac instead of Cocoa.
       'mac_views_browser%': 0,
 
+      # By default, use ICU data file (icudtl.dat).
+      'icu_use_data_file_flag%': 1,
+
+      # Turn on JNI generation optimizations by default.
+      'optimize_jni_generation%': 1,
+
       'conditions': [
         # A flag for POSIX platforms
         ['OS=="win"', {
@@ -672,18 +694,10 @@
         }],
 
         # NSS usage.
-        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==0', {
-          'use_nss%': 1,
+        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris")', {
+          'use_nss_certs%': 1,
         }, {
-          'use_nss%': 0,
-        }],
-
-        # When OpenSSL is used for SSL and crypto on Unix-like systems, use
-        # OpenSSL's certificate definition.
-        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==1', {
-          'use_openssl_certs%': 1,
-        }, {
-          'use_openssl_certs%': 0,
+          'use_nss_certs%': 0,
         }],
 
         # libudev usage.  This currently only affects the content layer.
@@ -786,8 +800,8 @@
           'native_memory_pressure_signals%': 1,
         }],
 
-        # Enable autofill dialog for Android, Mac and Views-enabled platforms.
-        ['toolkit_views==1 or (OS=="android" and android_webview_build==0) or OS=="mac"', {
+        # Enable autofill dialog when not on iOS.
+        ['OS!="ios"', {
           'enable_autofill_dialog%': 1,
 
           'conditions': [
@@ -852,7 +866,7 @@
         # are using a custom toolchain and need to control -B in ldflags.
         # Do not use 32-bit gold on 32-bit hosts as it runs out address space
         # for component=static_library builds.
-        ['OS=="linux" and (target_arch=="x64" or target_arch=="arm")', {
+        ['(OS=="linux" or OS=="android") and (target_arch=="x64" or target_arch=="arm")', {
           'linux_use_bundled_gold%': 1,
         }, {
           'linux_use_bundled_gold%': 0,
@@ -901,7 +915,7 @@
         #
         # On Aura, this allows per-tile painting to be used in the browser
         # compositor.
-        ['OS!="android"', {
+        ['OS!="android" and OS!="ios"', {
           'use_canvas_skia%': 1,
         }],
 
@@ -986,15 +1000,6 @@
           'enable_print_preview%': 0,
         }],
 
-        # By default, use ICU data file (icudtl.dat) on all platforms
-        # except when building Android WebView.
-        # TODO(jshin): Handle 'use_system_icu' on Linux (Chromium).
-        # Set the data reduction proxy origin for Android Webview.
-        ['android_webview_build==0', {
-          'icu_use_data_file_flag%' : 1,
-        }, {
-          'icu_use_data_file_flag%' : 0,
-        }],
         ['OS=="win" or OS=="mac"', {
           'enable_wifi_bootstrapping%' : 1,
         }],
@@ -1006,23 +1011,12 @@
         }, {
           'sas_dll_path%': '<(DEPTH)/third_party/platformsdk_win7/files/redist/x86',
         }],
-
-        # Turn on JNI generation optimizations on non-WebView builds.
-        ['OS=="android" and android_webview_build==0', {
-          'optimize_jni_generation%': 1,
-        }, {
-          'optimize_jni_generation%': 0,
-        }],
-
-        # TODO(rmcilroy): Enable v8_use_external_startup_data on ChromeOS
-        # http://crbug.com/421063
-        ['android_webview_build==0 and chromecast==0 and chromeos==0 and OS!="ios"', {
-          'v8_use_external_startup_data%': 1,
-        }, {
-          'v8_use_external_startup_data%': 0,
-        }],
       ],
 
+      # Setting this to '0' will cause V8's startup snapshot to be
+      # embedded in the binary instead of being a external files.
+      'v8_use_external_startup_data%': 1,
+
       # Set this to 1 to enable use of concatenated impulse responses
       # for the HRTF panner in WebAudio.
       'use_concatenated_impulse_responses': 1,
@@ -1073,10 +1067,16 @@
       'google_default_client_secret%': '',
       # Native Client is enabled by default.
       'disable_nacl%': '0',
+
+      # Sets the default version name and code for Android app, by default we
+      # do a developer build.
+      'android_app_version_name%': 'Developer Build',
+      'android_app_version_code%': 1,
     },
 
     # Copy conditionally-set variables out one scope.
     'branding%': '<(branding)',
+    'branding_path_component%': '<(branding_path_component)',
     'buildtype%': '<(buildtype)',
     'target_arch%': '<(target_arch)',
     'target_subarch%': '<(target_subarch)',
@@ -1091,7 +1091,7 @@
     'use_libpci%': '<(use_libpci)',
     'use_openssl%': '<(use_openssl)',
     'use_openssl_certs%': '<(use_openssl_certs)',
-    'use_nss%': '<(use_nss)',
+    'use_nss_certs%': '<(use_nss_certs)',
     'use_udev%': '<(use_udev)',
     'os_bsd%': '<(os_bsd)',
     'os_posix%': '<(os_posix)',
@@ -1196,7 +1196,6 @@
     'use_libjpeg_turbo%': '<(use_libjpeg_turbo)',
     'use_system_libjpeg%': '<(use_system_libjpeg)',
     'android_channel%': '<(android_channel)',
-    'android_webview_build%': '<(android_webview_build)',
     'icu_use_data_file_flag%': '<(icu_use_data_file_flag)',
     'gyp_managed_install%': 0,
     'create_standalone_apk%': 1,
@@ -1224,7 +1223,12 @@
     'video_hole%': '<(video_hole)',
     'v8_use_external_startup_data%': '<(v8_use_external_startup_data)',
     'cfi_vptr%': '<(cfi_vptr)',
+    'cfi_derived_cast%': '<(cfi_derived_cast)',
+    'cfi_unrelated_cast%': '<(cfi_unrelated_cast)',
+    'cfi_blacklist%': '<(cfi_blacklist)',
     'mac_views_browser%': '<(mac_views_browser)',
+    'android_app_version_name%': '<(android_app_version_name)',
+    'android_app_version_code%': '<(android_app_version_code)',
 
     # Use system protobuf instead of bundled one.
     'use_system_protobuf%': 0,
@@ -1417,7 +1421,7 @@
 
     # Pseudo locales are special locales which are used for testing and
     # debugging. They don't get copied to the final app. For more info,
-    # check out https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
+    # check out https://www.chromium.org/developers/testing/fake-bidi
     'pseudo_locales': [
       'fake-bidi',
     ],
@@ -1456,11 +1460,6 @@
     # we can build a debug version with acceptable size and performance.
     'android_full_debug%': 0,
 
-    # Sets the default version name and code for Android app, by default we
-    # do a developer build.
-    'android_app_version_name%': 'Developer Build',
-    'android_app_version_code%': 1,
-
     # Contains data about the attached devices for gyp_managed_install.
     'build_device_config_path': '<(PRODUCT_DIR)/build_devices.cfg',
 
@@ -1503,6 +1502,7 @@
 
     # Ozone platforms to include in the build.
     'ozone_platform_caca%': 0,
+    'ozone_platform_cast%': 0,
     'ozone_platform_dri%': 0,
     'ozone_platform_drm%': 0,
     'ozone_platform_egltest%': 0,
@@ -1564,18 +1564,11 @@
       # it takes effect here.
       ['os_posix==1 and OS!="mac" and OS!="ios" and clang==0 and asan==0 and lsan==0 and tsan==0 and msan==0 and ubsan_vptr==0', {
         'conditions': [
-          ['OS=="android" and android_webview_build==0', {
+          ['OS=="android"', {
             'host_gcc_version%': '<!pymod_do_main(compiler_version host compiler)',
             # We directly set the gcc version since we know what we use.
             'gcc_version%': 49,
-          }],
-          ['OS=="android" and android_webview_build==1', {
-            # Android WebView uses a hermetic clang toolchain for host builds.
-            'host_gcc_version%': 0,
-            # Android WebView uses the GCC toolchain from the Android build.
-            'gcc_version%': 48,
-          }],
-          ['OS!="android"', {
+          }, {
             'host_gcc_version%': '<!pymod_do_main(compiler_version host compiler)',
             'gcc_version%': '<!pymod_do_main(compiler_version target compiler)',
           }],
@@ -1817,13 +1810,6 @@
 
         # Uses system APIs for decoding audio and video.
         'use_libffmpeg%': '0',
-
-        # TODO(torne): Remove this unsupported option once all the places that
-        # test it have been updated.
-        'use_system_stlport%': 0,
-
-        # Copy it out one scope.
-        'android_webview_build%': '<(android_webview_build)',
       }],  # OS=="android"
       ['embedded==1', {
         'use_system_fontconfig%': 0,
@@ -1844,10 +1830,8 @@
           }],
         ],
       }],
-      ['android_webview_build==1', {
-        # When building the WebView in the Android tree, jarjar will remap all
-        # the class names, so the JNI generator needs to know this.
-        'jni_generator_jarjar_file': '../android_webview/build/jarjar-rules.txt',
+      ['chromecast==1 and OS!="android"', {
+        'ozone_platform_cast%': 1
       }],
       ['OS=="linux" and target_arch!="mipsel"', {
         'clang%': 1,
@@ -2052,8 +2036,8 @@
       ['use_ash==1', {
         'grit_defines': ['-D', 'use_ash'],
       }],
-      ['use_nss==1', {
-        'grit_defines': ['-D', 'use_nss'],
+      ['use_nss_certs==1', {
+        'grit_defines': ['-D', 'use_nss_certs'],
       }],
       ['use_ozone==1', {
         'grit_defines': ['-D', 'use_ozone'],
@@ -2080,11 +2064,6 @@
           '-E', 'ANDROID_JAVA_TAGGED_ONLY=true',
           '--no-output-all-resource-defines',
         ],
-        'conditions': [
-          ['<(android_webview_build)==1', {
-            'grit_defines': ['-D', 'is_android_webview_build'],
-          }],
-        ],
       }],
       ['OS=="mac" or OS=="ios"', {
         'grit_defines': ['-D', 'scale_factors=2x'],
@@ -2175,20 +2154,31 @@
         'grit_defines': ['-D', 'enable_service_discovery'],
         'enable_service_discovery%': 1
       }],
-      ['clang_use_chrome_plugins==1 and OS!="win"', {
+      ['clang_use_chrome_plugins==1', {
         'variables': {
           'conditions': [
-            ['OS=="mac" or OS=="ios"', {
-              'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
-            }, { # OS != "mac" or OS != "ios"
-              'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
-            }],
+            ['OS!="win"', {
+              'variables': {
+                'conditions': [
+                  ['OS=="mac" or OS=="ios"', {
+                    'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
+                  }, { # OS != "mac" or OS != "ios"
+                    'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
+                  }],
+                ],
+              },
+              'clang_dynlib_flags%': '-Xclang -load -Xclang <(clang_lib_path) ',
+            }, { # OS == "win"
+              # On Windows, the plugin is built directly into clang, so there's
+              # no need to load it dynamically.
+              'clang_dynlib_flags%': '',
+            }]
           ],
         },
         # If you change these, also change build/config/clang/BUILD.gn.
         'clang_chrome_plugins_flags%':
-          '-Xclang -load -Xclang <(clang_lib_path)'
-          ' -Xclang -add-plugin -Xclang find-bad-constructs',
+          '<(clang_dynlib_flags)'
+          '-Xclang -add-plugin -Xclang find-bad-constructs',
       }],
       ['asan==1 or msan==1 or lsan==1 or tsan==1', {
         'clang%': 1,
@@ -2241,9 +2231,9 @@
       }],
 
       ['OS=="win"', {
-        # The Clang plugins don't currently work on Windows.
+        # The Blink GC plugin doesn't currently work on Windows.
         # TODO(hans): One day, this will work. (crbug.com/82385)
-        'clang_use_chrome_plugins%': 0,
+        'blink_gc_plugin%': 0,
       }],
 
       # On valgrind bots, override the optimizer settings so we don't inline too
@@ -2305,14 +2295,14 @@
       }],
 
       # Set default compiler flags depending on ARM version.
-      ['arm_version==6 and android_webview_build==0', {
+      ['arm_version==6', {
         'arm_arch%': 'armv6',
         'arm_tune%': '',
         'arm_fpu%': 'vfp',
         'arm_float_abi%': 'softfp',
         'arm_thumb%': 0,
       }],
-      ['arm_version==7 and android_webview_build==0', {
+      ['arm_version==7', {
         'arm_arch%': 'armv7-a',
         'arm_tune%': 'generic-armv7-a',
         'conditions': [
@@ -2328,24 +2318,13 @@
       }],
 
       # Set default compiler flags for MIPS floating-point support.
-      ['target_arch=="mipsel" and android_webview_build==0', {
+      ['target_arch=="mipsel"', {
         'mips_float_abi%': 'hard',
       }],
-      ['target_arch=="mipsel" and mips_arch_variant=="r2" and android_webview_build==0', {
+      ['target_arch=="mipsel" and mips_arch_variant=="r2"', {
         'mips_fpu_mode%': 'fp32',
       }],
 
-      ['android_webview_build==1', {
-        # The WebView build gets its cpu-specific flags from the Android build system.
-        'arm_arch%': '',
-        'arm_tune%': '',
-        'arm_fpu%': '',
-        'arm_float_abi%': '',
-        'arm_thumb%': 0,
-        'mips_float_abi%': '',
-        'mips_fpu_mode%': '',
-      }],
-
       # Enable brlapi by default for chromeos.
       [ 'chromeos==1', {
         'use_brlapi%': 1,
@@ -2403,7 +2382,7 @@
          'use_seccomp_bpf%': 0,
       }],
 
-      ['cfi_vptr==1', {
+      ['cfi_vptr==1 or cfi_derived_cast==1 or cfi_unrelated_cast==1', {
         'use_lto%': 1,
       }],
     ],
@@ -2702,6 +2681,9 @@
       ['enable_webrtc==1', {
         'defines': ['ENABLE_WEBRTC=1'],
       }],
+      ['enable_media_router==1', {
+        'defines': ['ENABLE_MEDIA_ROUTER=1'],
+      }],
       ['proprietary_codecs==1', {
         'defines': ['USE_PROPRIETARY_CODECS'],
         'conditions': [
@@ -3012,6 +2994,27 @@
       ['v8_use_external_startup_data==1', {
        'defines': ['V8_USE_EXTERNAL_STARTUP_DATA'],
       }],
+
+      # SAFE_BROWSING_SERVICE - browser manages a safe-browsing service.
+      # SAFE_BROWSING_DB_LOCAL - service manages a local database.
+      # SAFE_BROWSING_DB_REMOTE - service talks via API to a database
+      # SAFE_BROWSING_CSD - enable client-side phishing detection.
+      ['safe_browsing==1', {
+        # TODO(nparker): Remove existing uses of FULL_SAFE_BROWSING
+        'defines': [
+          'FULL_SAFE_BROWSING',
+          'SAFE_BROWSING_CSD',
+          'SAFE_BROWSING_DB_LOCAL',
+          'SAFE_BROWSING_SERVICE',
+        ],
+      }],
+      ['safe_browsing==2', {
+        'defines': [
+          # TODO(nparker): Remove existing uses of MOBILE_SAFE_BROWSING
+          'MOBILE_SAFE_BROWSING',
+          'SAFE_BROWSING_SERVICE',
+        ],
+      }],
     ],  # conditions for 'target_defaults'
     'target_conditions': [
       ['<(use_libpci)==1', {
@@ -3032,8 +3035,8 @@
       ['<(use_glib)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['USE_GLIB=1'],
       }],
-      ['<(use_nss)==1 and >(nacl_untrusted_build)==0', {
-        'defines': ['USE_NSS=1'],
+      ['<(use_nss_certs)==1 and >(nacl_untrusted_build)==0', {
+        'defines': ['USE_NSS_CERTS=1'],
       }],
       ['<(chromeos)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['OS_CHROMEOS=1'],
@@ -3603,8 +3606,6 @@
           '-pthread',
           '-fno-strict-aliasing',  # See http://crbug.com/32204
           '-Wall',
-          # TODO(evan): turn this back on once all the builds work.
-          # '-Wextra',
           # Don't warn about unused function params.  We use those everywhere.
           '-Wno-unused-parameter',
           # Don't warn about the "struct foo f = {0};" initialization pattern.
@@ -3676,6 +3677,12 @@
                   '-fomit-frame-pointer',
                 ],
               }],
+              ['OS!="android"', {
+                'defines': [
+                  '_LARGEFILE_SOURCE',
+                  '_LARGEFILE64_SOURCE',
+                ],
+              }],
               ['OS=="linux" and target_arch=="ia32"', {
                 'ldflags': [
                   '-Wl,--no-as-needed',
@@ -4025,6 +4032,8 @@
                           '-no-integrated-as',
                           '-B<(android_toolchain)',  # Else /usr/bin/as gets picked up.
                         ],
+                      }],
+                      ['clang==1 and linux_use_bundled_gold==0', {
                         'ldflags': [
                           # Let clang find the ld.gold in the NDK.
                           '--gcc-toolchain=<(android_toolchain)/..',
@@ -4076,10 +4085,6 @@
                     'cflags!': [
                        '-fstack-protector',  # stack protector is always enabled on arm64.
                     ],
-                  }],
-                  # TODO: Remove webview test once webview fully compiles from
-                  # Chromium. crbug.com/440793
-                  ['OS=="android" and android_webview_build==0', {
                     'ldflags': [
                       '-fuse-ld=gold',
                     ],
@@ -4092,38 +4097,74 @@
             'target_conditions': [
               ['_toolset=="target"', {
                 'conditions': [
-                  ['android_webview_build==0', {
+                  ['mips_arch_variant=="r6"', {
                     'conditions': [
-                      ['mips_arch_variant=="r6"', {
-                        'cflags': ['-mips32r6', '-Wa,-mips32r6'],
-                        'conditions': [
-                          ['OS=="android"', {
-                            'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
-                          }],
-                        ],
+                      ['clang==1', {
+                        'cflags': [ '-target mipsel-linux-gnu', '-march=mips32r6', ],
+                        'ldflags': [ '-target mipsel-linux-gnu', ],
+                      }, { # clang==0
+                        'cflags': ['-mips32r6', '-Wa,-mips32r6', ],
                       }],
-                      ['mips_arch_variant=="r2"', {
-                        'cflags': ['-mips32r2', '-Wa,-mips32r2'],
-                        'conditions': [
-                          ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
-                            'cflags': ['-m<(mips_fpu_mode)'],
-                          }],
-                        ],
+                      ['clang==0 and OS=="android"', {
+                        'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
                       }],
-                      ['mips_arch_variant=="r1"', {
-                        'cflags': ['-mips32', '-Wa,-mips32'],
-                      }],
-                      ['mips_dsp_rev==1', {
-                        'cflags': ['-mdsp'],
-                      }],
-                      ['mips_dsp_rev==2', {
-                        'cflags': ['-mdspr2'],
-                      }],
-                    ],
-                    'cflags': [
-                      '-m<(mips_float_abi)-float'
                     ],
                   }],
+                  ['mips_arch_variant=="r2"', {
+                    'conditions': [
+                      ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
+                        'cflags': ['-m<(mips_fpu_mode)'],
+                      }],
+                      ['clang==1', {
+                         'conditions': [
+                          ['OS=="android"', {
+                            'cflags': [ '-target mipsel-linux-android', '-march=mipsel', '-mcpu=mips32r2'],
+                            'ldflags': [ '-target mipsel-linux-android', ],
+                          }],
+                         ],
+                      }, { # clang==0
+                        'cflags': ['-mips32r2', '-Wa,-mips32r2', ],
+                      }],
+                    ],
+                  }],
+                  ['mips_arch_variant=="r1"', {
+                    'conditions': [
+                      ['clang==1', {
+                        'conditions': [
+                          ['OS=="android"', {
+                            'cflags': [ '-target mipsel-linux-android', '-march=mipsel', '-mcpu=mips32'],
+                            'ldflags': [ '-target mipsel-linux-android', ],
+                          }],
+                        ],
+                      }, { # clang==0
+                        'cflags': ['-mips32', '-Wa,-mips32', ],
+                      }],
+                    ],
+                  }],
+                  ['clang==1', {
+                    'cflags!': [
+                      # Clang does not support the following options.
+                      '-finline-limit=64',
+                    ],
+                    'cflags': [
+                      # TODO(gordanac) Enable integrated-as.
+                      '-no-integrated-as',
+                      '-B<(android_toolchain)',  # Else /usr/bin/as gets picked up.
+                    ],
+                    'ldflags': [
+                      # Let clang find the ld in the NDK.
+                      '--gcc-toolchain=<(android_toolchain)/..',
+                    ],
+                  }],
+                  ['mips_dsp_rev==1', {
+                    'cflags': ['-mdsp'],
+                  }],
+                  ['mips_dsp_rev==2', {
+                    'cflags': ['-mdspr2'],
+                  }],
+                ],
+                'cflags': [
+                  '-m<(mips_float_abi)-float'
                 ],
                 'ldflags': [
                   '-Wl,--no-keep-memory'
@@ -4138,17 +4179,13 @@
             'target_conditions': [
               ['_toolset=="target"', {
                 'conditions': [
-                  ['android_webview_build==0', {
-                    'conditions': [
-                      ['mips_arch_variant=="r6"', {
-                        'cflags': ['-mips64r6', '-Wa,-mips64r6'],
-                        'ldflags': ['-mips64r6'],
-                      }],
-                      ['mips_arch_variant=="r2"', {
-                        'cflags': ['-mips64r2', '-Wa,-mips64r2'],
-                        'ldflags': ['-mips64r2'],
-                      }],
-                    ],
+                  ['mips_arch_variant=="r6"', {
+                    'cflags': ['-mips64r6', '-Wa,-mips64r6'],
+                    'ldflags': ['-mips64r6'],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'cflags': ['-mips64r2', '-Wa,-mips64r2'],
+                    'ldflags': ['-mips64r2'],
                   }],
                 ],
                 'cflags_cc': [
@@ -4517,11 +4554,16 @@
               '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
             ],
           }],
-          ['linux_use_bundled_gold==1', {
+          ['linux_use_bundled_gold==1 and '
+           'not (clang==0 and (use_lto==1 or use_lto_o2==1))', {
             # Put our binutils, which contains gold in the search path. We pass
             # the path to gold to the compiler. gyp leaves unspecified what the
             # cwd is when running the compiler, so the normal gyp path-munging
             # fails us. This hack gets the right path.
+            #
+            # Disabled when using GCC LTO because GCC also uses the -B search
+            # path at link time to find "as", and our bundled "as" can only
+            # target x86.
             'ldflags': [
               '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
             ],
@@ -4668,8 +4710,13 @@
               '-fstack-protector',
               '-fno-short-enums',
               '-finline-limit=64',
-              '-Wa,--noexecstack',
               '<@(release_extra_cflags)',
+              '--sysroot=<(android_ndk_sysroot)',
+              # NOTE: The stlport header include paths below are specified in
+              # cflags rather than include_dirs because they need to come
+              # after include_dirs.
+              # The include ordering here is important; change with caution.
+              '-isystem<(android_stlport_include)',
             ],
             'defines': [
               'ANDROID',
@@ -4677,15 +4724,43 @@
               'USE_STLPORT=1',
               '_STLP_USE_PTR_SPECIALIZATIONS=1',
               'CHROME_BUILD_ID="<(chrome_build_id)"',
+              # The NDK has these things, but doesn't define the constants
+              # to say that it does. Define them here instead.
+              'HAVE_SYS_UIO_H',
             ],
             'ldflags!': [
               '-pthread',  # Not supported by Android toolchain.
             ],
             'ldflags': [
               '-Wl,--no-undefined',
+              '--sysroot=<(android_ndk_sysroot)',
+              '-nostdlib',
+              '-L<(android_stlport_libs_dir)',
+              # Don't allow visible symbols from libgcc or stlport to be
+              # re-exported.
+              '-Wl,--exclude-libs=libgcc.a',
+              '-Wl,--exclude-libs=libstlport_static.a',
+              # Don't allow visible symbols from libraries that contain
+              # assembly code with symbols that aren't hidden properly.
+              # http://crbug.com/448386
+              '-Wl,--exclude-libs=libcommon_audio.a',
+              '-Wl,--exclude-libs=libcommon_audio_neon.a',
+              '-Wl,--exclude-libs=libcommon_audio_sse2.a',
+              '-Wl,--exclude-libs=libiSACFix.a',
+              '-Wl,--exclude-libs=libisac_neon.a',
+              '-Wl,--exclude-libs=libopus.a',
+              '-Wl,--exclude-libs=libvpx.a',
+            ],
+            'libraries': [
+              '-l<(android_stlport_library)',
+              # Manually link the libgcc.a that the cross compiler uses.
+              '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+              '-lc',
+              '-ldl',
+              '-lm',
             ],
             'conditions': [
-              ['component=="static_library" and android_webview_build==0', {
+              ['component=="static_library"', {
                 'target_conditions': [
                   ['use_native_jni_exports==0', {
                     # Use a linker version script to strip JNI exports from
@@ -4741,112 +4816,12 @@
                   '-mllvm -asan-globals=0',
                 ],
               }],
-              ['android_webview_build==0', {
-                'defines': [
-                  # The NDK has these things, but doesn't define the constants
-                  # to say that it does. Define them here instead.
-                  'HAVE_SYS_UIO_H',
-                ],
-                'cflags': [
-                  '--sysroot=<(android_ndk_sysroot)',
-                ],
-                'ldflags': [
-                  '--sysroot=<(android_ndk_sysroot)',
-                  '-nostdlib',
-                  # Don't allow visible symbols from libgcc or stlport to be
-                  # re-exported.
-                  '-Wl,--exclude-libs=libgcc.a',
-                  '-Wl,--exclude-libs=libstlport_static.a',
-                  # Don't allow visible symbols from libraries that contain
-                  # assembly code with symbols that aren't hidden properly.
-                  # http://crbug.com/448386
-                  '-Wl,--exclude-libs=libcommon_audio.a',
-                  '-Wl,--exclude-libs=libcommon_audio_neon.a',
-                  '-Wl,--exclude-libs=libcommon_audio_sse2.a',
-                  '-Wl,--exclude-libs=libiSACFix.a',
-                  '-Wl,--exclude-libs=libisac_neon.a',
-                  '-Wl,--exclude-libs=libopus.a',
-                  '-Wl,--exclude-libs=libvpx.a',
-                ],
-                'libraries': [
-                  '-l<(android_stlport_library)',
-                  # Manually link the libgcc.a that the cross compiler uses.
-                  '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
-                  '-lc',
-                  '-ldl',
-                  '-lm',
-                ],
-              }],
-              ['android_webview_build==1', {
-                'cflags': [
-                  # Android predefines this as 1; undefine it here so Chromium
-                  # can redefine it later to be 2 for chromium code and unset
-                  # for third party code. This works because cflags are added
-                  # before defines.
-                  '-U_FORTIFY_SOURCE',
-                  # Disable any additional warnings enabled by the Android build system but which
-                  # chromium does not build cleanly with (when treating warning as errors).
-                  # Things that are part of -Wextra:
-                  '-Wno-extra', # Enabled by -Wextra, but no specific flag
-                  '-Wno-ignored-qualifiers',
-                  '-Wno-type-limits',
-                  '-Wno-unused-but-set-variable',
-                ],
-                'cflags_cc': [
-                  # Other things unrelated to -Wextra:
-                  '-Wno-non-virtual-dtor',
-                  '-Wno-sign-promo',
-                ],
-                'libraries': [
-                  '-ldl',
-                ],
-              }],
-              ['android_webview_build==1', {
-                'target_conditions': [
-                  ['chromium_code==0', {
-                    'cflags': [
-                      # There is a class of warning which:
-                      #  1) Android always enables and also treats as errors
-                      #  2) Chromium ignores in third party code
-                      # So we re-enable those warnings when building Android.
-                      '-Wno-address',
-                      '-Wno-format-security',
-                      '-Wno-return-type',
-                      '-Wno-sequence-point',
-                    ],
-                    'cflags_cc': [
-                      '-Wno-non-virtual-dtor',
-                    ],
-                  }],
-                ],
-              }],
               ['target_arch == "arm" and order_profiling==0', {
                 'ldflags': [
                   # Enable identical code folding to reduce size.
                   '-Wl,--icf=<(gold_icf_level)',
                 ],
               }],
-              # NOTE: The stlport header include paths below are specified in
-              # cflags rather than include_dirs because they need to come
-              # after include_dirs. Think of them like system headers, but
-              # don't use '-isystem' because the arm-linux-androideabi-4.4.3
-              # toolchain (circa Gingerbread) will exhibit strange errors.
-              # The include ordering here is important; change with caution.
-              ['android_webview_build==0', {
-                'cflags': [
-                  '-isystem<(android_stlport_include)',
-                ],
-                'ldflags': [
-                  '-L<(android_stlport_libs_dir)',
-                ],
-              }, { # else: android_webview_build!=0
-                'aosp_build_settings': {
-                  # Specify that we want to statically link stlport from the
-                  # NDK. This will provide all the include and library paths
-                  # automatically at build time, and link the right library.
-                  'LOCAL_NDK_STL_VARIANT': 'stlport_static',
-                },
-              }],
               ['target_arch=="ia32"', {
                 # The x86 toolchain currently has problems with stack-protector.
                 'cflags!': [
@@ -4885,19 +4860,13 @@
               ['_type=="shared_library" or _type=="loadable_module"', {
                 'ldflags': [
                   '-Wl,-shared,-Bsymbolic',
+                  # crtbegin_so.o should be the last item in ldflags.
+                  '<(android_ndk_lib)/crtbegin_so.o',
                 ],
-                'conditions': [
-                  ['android_webview_build==0', {
-                    'ldflags': [
-                      # crtbegin_so.o should be the last item in ldflags.
-                      '<(android_ndk_lib)/crtbegin_so.o',
-                    ],
-                    'libraries': [
-                      # crtend_so.o needs to be the last item in libraries.
-                      # Do not add any libraries after this!
-                      '<(android_ndk_lib)/crtend_so.o',
-                    ],
-                  }],
+                'libraries': [
+                  # crtend_so.o needs to be the last item in libraries.
+                  # Do not add any libraries after this!
+                  '<(android_ndk_lib)/crtend_so.o',
                 ],
               }],
             ],
@@ -5167,6 +5136,16 @@
             # specified or not.
             '-fno-strict-aliasing',  # See http://crbug.com/32204.
           ],
+          'conditions': [
+            ['branding=="Chrome" and buildtype=="Official"', {
+              'OTHER_CFLAGS': [
+                # The Google Chrome Framework dSYM generated by dsymutil has
+                # grown larger than 4GB, which dsymutil can't handle. Reduce
+                # the amount of debug symbols.
+                '-gline-tables-only',  # See http://crbug.com/479841
+              ]
+            }],
+          ],
         },
         'target_conditions': [
           ['_type=="executable"', {
@@ -5546,6 +5525,11 @@
           4512, # Assignment operator could not be generated
           4610, # Object can never be instantiated
           4996, # 'X': was declared deprecated (for GetVersionEx).
+
+          # These are variable shadowing warnings that are new in VS2015. We
+          # should work through these at some point -- they may be removed from
+          # the RTM release in the /W4 set.
+          4456, 4457, 4458, 4459,
         ],
         'msvs_settings': {
           'VCCLCompilerTool': {
@@ -5681,6 +5665,13 @@
                 ],
               },
             }],
+            ['clang==1 and clang_use_chrome_plugins==1', {
+              'VCCLCompilerTool': {
+                'AdditionalOptions': [
+                  '<@(clang_chrome_plugins_flags)',
+                ],
+              },
+            }],
           ],
         },
       },
@@ -5770,6 +5761,19 @@
                     }],
                   ],
                 }],
+                ['sanitizer_coverage!=0', {
+                  # TODO(asan/win): Move this down into the general
+                  # win-target_defaults section once the 64-bit asan runtime
+                  # exists.  See crbug.com/345874.
+                  'VCCLCompilerTool': {
+                    'AdditionalOptions': [
+                      '-fsanitize-coverage=<(sanitizer_coverage)',
+                    ],
+                    'defines': [
+                      'SANITIZER_COVERAGE',
+                    ],
+                  },
+                }],
               ],
             },
           },
@@ -5813,45 +5817,6 @@
         ],
       },
     }],
-    # In the android webview build, force host targets to be compiled with clang
-    # as the hermetic host gcc is very old on some platforms. This is already
-    # the default on the current development version of AOSP but we force it
-    # here in case we need to compile against an older release version. We also
-    # explicitly set it to false for target binaries to avoid causing problems
-    # for the work to enable clang by default in AOSP. We also force the use of
-    # libstdc++ on host as peculiarities of the android gyp backend mean that
-    # using libc++ doesn't work, and Chromium doesn't yet require a more modern
-    # C++ library.
-    ['android_webview_build==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'aosp_build_settings': {
-              'LOCAL_CLANG': 'true',
-              'LOCAL_CXX_STL': 'libstdc++',
-            },
-          }, {  # else: _toolset != "host"
-            'aosp_build_settings': {
-              'LOCAL_CLANG': 'false',
-            },
-          }],
-        ],
-      },
-    }],
-    # We need a special case to handle the android webview build on mac because
-    # the host gcc there doesn't accept this flag, but the target gcc may
-    # require it.
-    ['gcc_version>=48 and android_webview_build==1 and host_os=="mac"', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'cflags!': [
-              '-Wno-unused-local-typedefs',
-            ],
-          }],
-        ],
-      },
-    }],
     ['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
         'and OS!="win"', {
       'make_global_settings': [
@@ -5921,6 +5886,17 @@
             'cflags': [
               '-flto',
             ],
+            'xcode_settings': {
+              'LLVM_LTO': 'YES',
+            },
+          }],
+          # Work-around for http://openradar.appspot.com/20356002
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings': {
+              'OTHER_LDFLAGS': [
+                '-Wl,-all_load',
+              ],
+            },
           }],
         ],
       },
@@ -5947,6 +5923,25 @@
         ],
       },
     }],
+    # Apply a lower LTO optimization level in non-official builds.
+    ['use_lto==1 and clang==1 and buildtype!="Official"', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'ldflags': [
+              '-Wl,--plugin-opt,O1',
+            ],
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
+                '-Wl,-mllvm,-O1',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
     ['use_lto==1 and clang==1 and (target_arch=="ia32" or target_arch=="x64")', {
       'target_defaults': {
         'target_conditions': [
@@ -6030,6 +6025,74 @@
         ],
       },
     }],
+    ['cfi_derived_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-derived-cast',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-derived-cast',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize=cfi-derived-cast',
+              ],
+            },
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
+                '-fsanitize=cfi-derived-cast',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
+    ['cfi_unrelated_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize=cfi-unrelated-cast',
+              ],
+            },
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
+                '-fsanitize=cfi-unrelated-cast',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
+    ['cfi_vptr==1 or cfi_derived_cast==1 or cfi_unrelated_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize-blacklist=<(cfi_blacklist)',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize-blacklist=<(cfi_blacklist)',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
   ],
   'xcode_settings': {
     # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 15441a9..22cb45a 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -27,6 +27,9 @@
 
   # Set to true to enable dcheck in Release builds.
   dcheck_always_on = false
+
+  # Set to true to compile with the OpenGL ES 2.0 conformance tests.
+  internal_gles2_conform_tests = false
 }
 
 # TODO(brettw) Most of these should be removed. Instead of global feature
@@ -119,14 +122,12 @@
   }
   if (use_openssl) {
     defines += [ "USE_OPENSSL=1" ]
-    if (use_openssl_certs) {
-      defines += [ "USE_OPENSSL_CERTS=1" ]
-    }
-  } else if (use_nss_certs) {
-    # USE_NSS really means "use nss for certificate validation and storage"
-    # (like USE_OPENSSL_CERTS) and not "we're linking to NSS." It might be nice
-    # to rename this but we're hoping to transition away from NSS.
-    defines += [ "USE_NSS=1" ]
+  }
+  if (use_openssl_certs) {
+    defines += [ "USE_OPENSSL_CERTS=1" ]
+  }
+  if (use_nss_certs) {
+    defines += [ "USE_NSS_CERTS=1" ]
   }
   if (use_ozone) {
     defines += [ "USE_OZONE=1" ]
@@ -225,6 +226,18 @@
   if (enable_pre_sync_backup) {
     defines += [ "ENABLE_PRE_SYNC_BACKUP" ]
   }
+  if (enable_video_hole) {
+    defines += [ "VIDEO_HOLE=1" ]
+  }
+  if (safe_browsing_mode == 1) {
+    defines += [ "FULL_SAFE_BROWSING" ]
+    defines += [ "SAFE_BROWSING_CSD" ]
+    defines += [ "SAFE_BROWSING_DB_LOCAL" ]
+    defines += [ "SAFE_BROWSING_SERVICE" ]
+  } else if (safe_browsing_mode == 2) {
+    defines += [ "MOBILE_SAFE_BROWSING" ]
+    defines += [ "SAFE_BROWSING_SERVICE" ]
+  }
 }
 
 # Debug/release ----------------------------------------------------------------
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 8e30c4a..455ec0d 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -17,27 +17,12 @@
 # Use "is_*" names for intrinsic platform descriptions and build modes, and
 # "use_*" names for optional features libraries, and configurations.
 
-# TODO(dpranke): The os and cpu_arch variables exist for backwards
-# compatibility and should be deleted once all of the build files and
-# bots have been updated to use current_cpu/target_cpu and
-# current_os/target_os instead.
-
 if (target_os == "") {
-  if (defined(os)) {
-    # If os is defined, it was set in an args file and needs to be
-    # used for backwards-compatibility.
-    target_os = os
-  } else {
-    target_os = host_os
-  }
+  target_os = host_os
 }
 
 if (target_cpu == "") {
-  if (defined(cpu_arch)) {
-    # If cpu_arch is defined, it was set in an args file and needs to be
-    # used for backwards-compatibility.
-    target_cpu = cpu_arch
-  } else if (target_os == "android") {
+  if (target_os == "android") {
     # If we're building for Android, we should assume that we want to
     # build for ARM by default, not the host_cpu (which is likely x64).
     # This allows us to not have to specify both target_os and target_cpu
@@ -56,13 +41,6 @@
 }
 
 declare_args() {
-  # TODO(dpranke): These values are here for backwards compatibility and
-  # should be deleted when all of the builders and configs have been updated.
-  cpu_arch = target_cpu
-  os = target_os
-  build_cpu_arch = host_cpu
-  build_os = host_os
-
   # How many symbols to include in the build. This affects the performance of
   # the build since the symbols are large and dealing with them is slow.
   #   2 means regular build with symbols.
@@ -115,10 +93,6 @@
   }
 }
 
-# TODO(dpranke): Remove these asserts when os and cpu_arch are removed.
-assert(current_cpu == cpu_arch)
-assert(current_os == os)
-
 # =============================================================================
 # OS DEFINITIONS
 # =============================================================================
@@ -539,8 +513,8 @@
 } else if (is_nacl) {
   # TODO(GYP): This will need to change when we get NaCl working
   # on multiple platforms, but this whole block of code (how we define
-  # host_toolchain) needs to be reworked regardless to key off of build_os
-  # and build_cpu_arch rather than the is_* variables.
+  # host_toolchain) needs to be reworked regardless to key off of host_os
+  # and host_cpu rather than the is_* variables.
   host_toolchain = "//build/toolchain/linux:clang_x64"
 }
 
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 5a27e78..77ee311 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -30,11 +30,6 @@
     android_sdk_version = default_android_sdk_version
     android_sdk_build_tools_version = default_android_sdk_build_tools_version
 
-    # This is set when building the Android WebView inside the Android build
-    # system, using the 'android' gyp backend. The WebView code is still built
-    # when this is unset, but builds using the normal chromium build system.
-    is_android_webview_build = false
-
     android_default_keystore_path =
         "//build/android/ant/chromium-debug.keystore"
     android_default_keystore_name = "chromiumdebugkey"
@@ -44,6 +39,9 @@
     # identifying various build artifacts corresponding to a particular build of
     # chrome (e.g. where to find archived symbols).
     android_chrome_build_id = "\"\""
+
+    # Set to true to run findbugs on JAR targets.
+    run_findbugs = false
   }
 
   # Host stuff -----------------------------------------------------------------
@@ -189,8 +187,4 @@
   } else {
     assert(false, "Unknown Android ABI: " + current_cpu)
   }
-} else {
-  if (!defined(is_android_webview_build)) {
-    is_android_webview_build = false
-  }
 }
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 8920e95..ab773ea 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -62,6 +62,44 @@
   }
 }
 
+template("findbugs") {
+  jar_path = invoker.jar_path
+
+  build_config = invoker.build_config
+
+  action(target_name) {
+    script = "//build/android/findbugs_diff.py"
+    depfile = "$target_gen_dir/$target_name.d"
+    result_path = "$target_gen_dir/$target_name/result.xml"
+    exclusions_file = "//build/android/findbugs_filter/findbugs_exclude.xml"
+
+    rebased_build_config = rebase_path(build_config, root_build_dir)
+
+    inputs = [
+      "//build/android/pylib/utils/findbugs.py",
+      exclusions_file,
+      jar_path,
+    ]
+
+    outputs = [
+      depfile,
+      result_path,
+    ]
+
+    args = [
+      "--depfile",
+      rebase_path(depfile, root_build_dir),
+      "--exclude",
+      rebase_path(exclusions_file, root_build_dir),
+      "--auxclasspath-gyp",
+      "@FileArg($rebased_build_config:javac:classpath)",
+      "--output-file",
+      rebase_path(result_path, root_build_dir),
+      rebase_path(jar_path, root_build_dir),
+    ]
+  }
+}
+
 template("dex") {
   set_sources_assignment_filter([])
   if (defined(invoker.testonly)) {
@@ -188,7 +226,8 @@
       dep_name = get_label_info(d, "name")
       possible_deps_configs += [ "$dep_gen_dir/$dep_name.build_config" ]
     }
-    rebase_possible_deps_configs = rebase_path(possible_deps_configs)
+    rebase_possible_deps_configs =
+        rebase_path(possible_deps_configs, root_build_dir)
 
     outputs = [
       depfile,
@@ -250,6 +289,19 @@
       args += [ "--bypass-platform-checks" ]
     }
 
+    if (defined(invoker.apk_under_test)) {
+      deps += [ invoker.apk_under_test ]
+      apk_under_test_gen_dir =
+          get_label_info(invoker.apk_under_test, "target_gen_dir")
+      apk_under_test_name = get_label_info(invoker.apk_under_test, "name")
+      apk_under_test_config =
+          "$apk_under_test_gen_dir/$apk_under_test_name.build_config"
+      args += [
+        "--tested-apk-config",
+        rebase_path(apk_under_test_config, root_build_dir),
+      ]
+    }
+
     if (is_android_resources || is_apk) {
       assert(defined(invoker.resources_zip))
       args += [
@@ -262,6 +314,8 @@
           "--android-manifest",
           rebase_path(invoker.android_manifest, root_build_dir),
         ]
+      } else {
+        assert(!is_apk, "apk build configs require an android_manifest")
       }
       if (defined(invoker.custom_package)) {
         args += [
@@ -914,6 +968,14 @@
         jar_path = _jar_path
         java_files = _java_files
       }
+
+      if (run_findbugs) {
+        _final_datadeps += [ ":${_template_name}__findbugs" ]
+        findbugs("${_template_name}__findbugs") {
+          build_config = _build_config
+          jar_path = _jar_path
+        }
+      }
     }
 
     _final_deps += [ ":${_template_name}__dex" ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index a056997..39b2f39 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -49,9 +49,6 @@
     script = "//base/android/jni_generator/jni_generator.py"
     depfile = "$target_gen_dir/$target_name.{{source_name_part}}.d"
     sources = invoker.sources
-    inputs = [
-      jni_generator_include,
-    ]
     outputs = [
       depfile,
       "${jni_output_dir}/{{source_name_part}}_jni.h",
@@ -66,7 +63,7 @@
       "--output_dir",
       rebase_path(jni_output_dir, root_build_dir),
       "--includes",
-      rebase_path(jni_generator_include, "//"),
+      rebase_path(jni_generator_include, jni_output_dir),
       "--native_exports_optional",
     ]
     if (defined(invoker.jni_generator_jarjar_file)) {
@@ -166,7 +163,6 @@
       script = "//base/android/jni_generator/jni_generator.py"
       sources = [
         jar_file,
-        jni_generator_include,
       ]
       outputs = [
         depfile,
@@ -185,7 +181,7 @@
         "--output_dir",
         rebase_path(jni_output_dir, root_build_dir),
         "--includes",
-        rebase_path(jni_generator_include, root_build_dir),
+        rebase_path(jni_generator_include, jni_output_dir),
         "--native_exports_optional",
       ]
     }
@@ -733,7 +729,7 @@
 #   datadeps, testonly
 #
 # Example
-#   java_library("foo") {
+#   java_binary("foo") {
 #     java_files = [ "org/chromium/foo/FooMain.java" ]
 #     deps = [ ":bar_java" ]
 #     main_class = "org.chromium.foo.FooMain"
@@ -776,7 +772,65 @@
   }
 }
 
-# Declare an java library target
+# Declare a Junit executable target
+#
+# This target creates an executable from java code for running as a junit test
+# suite. The executable will be in the output folder's /bin/ directory.
+#
+# Variables
+#   deps: Specifies the dependencies of this target. Java targets in this list
+#     will be included in the executable (and the javac classpath).
+#
+#   java_files: List of .java files included in this library.
+#   srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
+#     will be added to java_files and be included in this library.
+#   srcjars: List of srcjars to be included in this library, together with the
+#     ones obtained from srcjar_deps.
+#
+#   chromium_code: If true, extra analysis warning/errors will be enabled.
+#
+# Example
+#   junit_binary("foo") {
+#     java_files = [ "org/chromium/foo/FooTest.java" ]
+#     deps = [ ":bar_java" ]
+#   }
+template("junit_binary") {
+  set_sources_assignment_filter([])
+
+  java_binary(target_name) {
+    bypass_platform_checks = true
+    main_class = "org.chromium.testing.local.JunitTestMain"
+    testonly = true
+
+    if (defined(invoker.DEPRECATED_java_in_dir)) {
+      DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir
+    }
+    if (defined(invoker.chromium_code)) {
+      chromium_code = invoker.chromium_code
+    }
+    deps = [
+      "//testing/android/junit:junit_test_support",
+      "//third_party/junit",
+      "//third_party/mockito:mockito_java",
+      "//third_party/robolectric:robolectric_java",
+      "//third_party/robolectric:android-all-4.3_r2-robolectric-0",
+    ]
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+    if (defined(invoker.java_files)) {
+      java_files = invoker.java_files
+    }
+    if (defined(invoker.srcjar_deps)) {
+      srcjar_deps = invoker.srcjar_deps
+    }
+    if (defined(invoker.srcjars)) {
+      srcjars = invoker.srcjars
+    }
+  }
+}
+
+# Declare a java library target
 #
 # Variables
 #   deps: Specifies the dependencies of this target. Java targets in this list
@@ -874,7 +928,7 @@
   }
 }
 
-# Declare an java library target for a prebuilt jar
+# Declare a java library target for a prebuilt jar
 #
 # Variables
 #   deps: Specifies the dependencies of this target. Java targets in this list
@@ -1107,6 +1161,8 @@
 #   native_libs: List paths of native libraries to include in this apk. If these
 #     libraries depend on other shared_library targets, those dependencies will
 #     also be included in the apk.
+#   apk_under_test: For an instrumentation test apk, this is the target of the
+#     tested apk.
 #   testonly: Marks this target as "test-only".
 #
 #   DEPRECATED_java_in_dir: Directory containing java files. All .java files in
@@ -1138,9 +1194,10 @@
   }
 
   assert(defined(invoker.final_apk_path) || defined(invoker.apk_name))
+  assert(defined(invoker.android_manifest))
   gen_dir = "$target_gen_dir/$target_name"
   base_path = "$gen_dir/$target_name"
-  _build_config = "$base_path.build_config"
+  _build_config = "$target_gen_dir/$target_name.build_config"
   resources_zip_path = "$base_path.resources.zip"
   all_resources_zip_path = "$base_path.resources.all.zip"
   jar_path = "$base_path.jar"
@@ -1223,6 +1280,7 @@
     }
   }
 
+  _android_manifest = invoker.android_manifest
   _rebased_build_config = rebase_path(_build_config, root_build_dir)
 
   write_build_config("${_template_name}__build_config") {
@@ -1230,11 +1288,16 @@
     dex_path = final_dex_path
     resources_zip = resources_zip_path
     build_config = _build_config
+    android_manifest = _android_manifest
 
     if (defined(invoker.deps)) {
       deps = invoker.deps
     }
 
+    if (defined(invoker.apk_under_test)) {
+      apk_under_test = invoker.apk_under_test
+    }
+
     native_libs = _native_libs
   }
 
@@ -1243,7 +1306,7 @@
   final_deps += [ ":${_template_name}__process_resources" ]
   process_resources("${_template_name}__process_resources") {
     srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
-    android_manifest = invoker.android_manifest
+    android_manifest = _android_manifest
     resource_dirs = [ "//build/android/ant/empty/res" ]
     zip_path = resources_zip_path
     generate_constant_ids = true
@@ -1289,7 +1352,7 @@
     supports_android = true
     requires_android = true
     override_build_config = _build_config
-    android_manifest = invoker.android_manifest
+    android_manifest = _android_manifest
     chromium_code = true
     if (defined(invoker.java_files)) {
       java_files = invoker.java_files
@@ -1397,7 +1460,7 @@
   final_deps += [ ":${_template_name}__create" ]
   create_apk("${_template_name}__create") {
     apk_path = _final_apk_path
-    android_manifest = invoker.android_manifest
+    android_manifest = _android_manifest
     resources_zip = all_resources_zip_path
     dex_path = final_dex_path
     load_library_from_apk = _load_library_from_apk
@@ -1490,13 +1553,12 @@
   }
 
   android_apk(target_name) {
-    _apk_name = apk_name
-    final_apk_path = "$root_build_dir/${_apk_name}_apk/${_apk_name}-debug.apk"
+    final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk"
     java_files = [
-      "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java",
-      "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java",
+      "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java",
+      "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java",
     ]
-    android_manifest = "//testing/android/java/AndroidManifest.xml"
+    android_manifest = "//testing/android/native_test/java/AndroidManifest.xml"
     native_libs = [ unittests_binary ]
     if (defined(invoker.asset_location)) {
       asset_location = invoker.asset_location
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
index 39fe251..3d96500 100644
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -6,20 +6,29 @@
 
 config("find_bad_constructs") {
   if (clang_use_chrome_plugins) {
-    cflags = [
-      "-Xclang",
-      "-load",
-      "-Xclang",
-    ]
+    cflags = []
+
+    # On Windows, the plugin is built directly into clang, so there's
+    # no need to load it dynamically.
 
     if (is_mac || is_ios) {
-      cflags += [ rebase_path(
-              "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
-              root_build_dir) ]
+      cflags += [
+        "-Xclang",
+        "-load",
+        "-Xclang",
+        rebase_path(
+            "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
+            root_build_dir),
+      ]
     } else if (is_linux) {
-      cflags += [ rebase_path(
-              "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
-              root_build_dir) ]
+      cflags += [
+        "-Xclang",
+        "-load",
+        "-Xclang",
+        rebase_path(
+            "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+            root_build_dir),
+      ]
     }
 
     cflags += [
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 42dc584..c217154 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -165,7 +165,7 @@
     defines += [ "CR_CLANG_REVISION=" +
                  exec_script("//tools/clang/scripts/posix-print-revision.py",
                              [],
-                             "value") ]
+                             "trim string") ]
   }
 
   # Mac-specific compiler flags setup.
@@ -194,16 +194,11 @@
     cflags_objcc = [ "-fobjc-call-cxx-cdtors" ]
 
     cflags_c += [ "-std=c99" ]
-    cflags_cc += [ "-std=gnu++11" ]
 
     ldflags += common_mac_flags
   } else if (is_posix) {
     # Non-Mac Posix compiler flags setup.
     # -----------------------------------
-    if (gcc_version >= 48) {
-      cflags_cc += [ "-std=gnu++11" ]
-    }
-
     if (enable_profiling && !is_debug) {
       # The GYP build spams this define into every compilation unit, as we do
       # here, but it only appears to be used in base and a couple other places.
@@ -246,98 +241,93 @@
         ]
       }
     } else if (current_cpu == "arm") {
-      # Don't set the compiler flags for the WebView build. These will come
-      # from the Android build system.
-      if (!is_android_webview_build) {
+      cflags += [
+        "-march=$arm_arch",
+        "-mfloat-abi=$arm_float_abi",
+      ]
+      if (arm_tune != "") {
+        cflags += [ "-mtune=$arm_tune" ]
+      }
+      if (arm_use_thumb) {
+        cflags += [ "-mthumb" ]
+        if (is_android && !is_clang) {  # Clang doesn't support this option.
+          cflags += [ "-mthumb-interwork" ]
+        }
+      }
+      if (!is_clang) {
+        # Clang doesn't support these flags.
         cflags += [
-          "-march=$arm_arch",
-          "-mfloat-abi=$arm_float_abi",
-        ]
-        if (arm_tune != "") {
-          cflags += [ "-mtune=$arm_tune" ]
-        }
-        if (arm_use_thumb) {
-          cflags += [ "-mthumb" ]
-          if (is_android && !is_clang) {  # Clang doesn't support this option.
-            cflags += [ "-mthumb-interwork" ]
-          }
-        }
-        if (!is_clang) {
-          # Clang doesn't support these flags.
-          cflags += [
-            # The tree-sra optimization (scalar replacement for
-            # aggregates enabling subsequent optimizations) leads to
-            # invalid code generation when using the Android NDK's
-            # compiler (r5-r7). This can be verified using
-            # webkit_unit_tests' WTF.Checked_int8_t test.
-            "-fno-tree-sra",
+          # The tree-sra optimization (scalar replacement for
+          # aggregates enabling subsequent optimizations) leads to
+          # invalid code generation when using the Android NDK's
+          # compiler (r5-r7). This can be verified using
+          # webkit_unit_tests' WTF.Checked_int8_t test.
+          "-fno-tree-sra",
 
-            # The following option is disabled to improve binary
-            # size and performance in gcc 4.9.
-            "-fno-caller-saves",
-          ]
-        }
+          # The following option is disabled to improve binary
+          # size and performance in gcc 4.9.
+          "-fno-caller-saves",
+        ]
       }
     } else if (current_cpu == "mipsel") {
-      # Don't set the compiler flags for the WebView build. These will come
-      # from the Android build system.
-      if (!is_android_webview_build) {
-        if (mips_arch_variant == "r6") {
-          cflags += [
+      if (mips_arch_variant == "r6") {
+        cflags += [
+          "-mips32r6",
+          "-Wa,-mips32r6",
+        ]
+        if (is_android) {
+          ldflags += [
             "-mips32r6",
-            "-Wa,-mips32r6",
-          ]
-          if (is_android) {
-            ldflags += [
-              "-mips32r6",
-              "-Wl,-melf32ltsmip",
-            ]
-          }
-        } else if (mips_arch_variant == "r2") {
-          cflags += [
-            "-mips32r2",
-            "-Wa,-mips32r2",
-          ]
-          if (mips_float_abi == "hard" && mips_fpu_mode != "") {
-            cflags += [ "-m$mips_fpu_mode" ]
-          }
-        } else if (mips_arch_variant == "r1") {
-          cflags += [
-            "-mips32",
-            "-Wa,-mips32",
+            "-Wl,-melf32ltsmip",
           ]
         }
-
-        if (mips_dsp_rev == 1) {
-          cflags += [ "-mdsp" ]
-        } else if (mips_dsp_rev == 2) {
-          cflags += [ "-mdspr2" ]
+      } else if (mips_arch_variant == "r2") {
+        cflags += [
+          "-mips32r2",
+          "-Wa,-mips32r2",
+        ]
+        if (mips_float_abi == "hard" && mips_fpu_mode != "") {
+          cflags += [ "-m$mips_fpu_mode" ]
         }
-
-        cflags += [ "-m${mips_float_abi}-float" ]
+      } else if (mips_arch_variant == "r1") {
+        cflags += [
+          "-mips32",
+          "-Wa,-mips32",
+        ]
       }
+
+      if (mips_dsp_rev == 1) {
+        cflags += [ "-mdsp" ]
+      } else if (mips_dsp_rev == 2) {
+        cflags += [ "-mdspr2" ]
+      }
+
+      cflags += [ "-m${mips_float_abi}-float" ]
     } else if (current_cpu == "mips64el") {
-      # Don't set the compiler flags for the WebView build. These will come
-      # from the Android build system.
-      if (!is_android_webview_build) {
-        if (mips_arch_variant == "r6") {
-          cflags += [
-            "-mips64r6",
-            "-Wa,-mips64r6",
-          ]
-          ldflags += [ "-mips64r6" ]
-        } else if (mips_arch_variant == "r2") {
-          cflags += [
-            "-mips64r2",
-            "-Wa,-mips64r2",
-          ]
-          ldflags += [ "-mips64r2" ]
-        }
+      if (mips_arch_variant == "r6") {
+        cflags += [
+          "-mips64r6",
+          "-Wa,-mips64r6",
+        ]
+        ldflags += [ "-mips64r6" ]
+      } else if (mips_arch_variant == "r2") {
+        cflags += [
+          "-mips64r2",
+          "-Wa,-mips64r2",
+        ]
+        ldflags += [ "-mips64r2" ]
       }
     }
 
     defines += [ "_FILE_OFFSET_BITS=64" ]
 
+    if (!is_android) {
+      defines += [
+        "_LARGEFILE_SOURCE",
+        "_LARGEFILE64_SOURCE",
+      ]
+    }
+
     # Omit unwind support in official builds to save space. We can use breakpad
     # for these builds.
     if (is_chrome_branded && is_official_build) {
@@ -418,7 +408,18 @@
   # ------------------------------------
   if (is_clang) {
     cflags += [ "-fcolor-diagnostics" ]
+  }
+
+  # C++11 compiler flags setup.
+  # ---------------------------
+  if (is_linux || is_android || is_nacl) {
+    # gnu++11 instead of c++11 is needed because some code uses typeof() (a
+    # GNU extension).
+    # TODO(thakis): Eventually switch this to c++11 instead,
+    # http://crbug.com/427584
     cflags_cc += [ "-std=gnu++11" ]
+  } else if (!is_win) {
+    cflags_cc += [ "-std=c++11" ]
   }
 
   # Android-specific flags setup.
@@ -433,15 +434,6 @@
       # Clang doesn't support these flags.
       cflags += [ "-finline-limit=64" ]
     }
-    if (is_android_webview_build) {
-      # Android predefines this as 1; undefine it here so Chromium can redefine
-      # it later to be 2 for chromium code and unset for third party code. This
-      # works because cflags are added before defines.
-      # TODO(brettw) the above comment seems incorrect. We specify defines
-      # before cflags on our compiler command lines.
-      cflags += [ "-U_FORTIFY_SOURCE" ]
-    }
-
     if (is_asan) {
       # Android build relies on -Wl,--gc-sections removing unreachable code.
       # ASan instrumentation for globals inhibits this and results in a library
@@ -451,11 +443,10 @@
     }
 
     defines += [ "ANDROID" ]
-    if (!is_android_webview_build) {
-      # The NDK has these things, but doesn't define the constants
-      # to say that it does. Define them here instead.
-      defines += [ "HAVE_SYS_UIO_H" ]
-    }
+
+    # The NDK has these things, but doesn't define the constants
+    # to say that it does. Define them here instead.
+    defines += [ "HAVE_SYS_UIO_H" ]
 
     # Use gold for Android for most CPU architectures.
     if (current_cpu == "x86" || current_cpu == "x64" || current_cpu == "arm") {
@@ -500,7 +491,7 @@
 }
 
 config("compiler_arm_fpu") {
-  if (current_cpu == "arm" && !is_android_webview_build) {
+  if (current_cpu == "arm") {
     cflags = [ "-mfpu=$arm_fpu" ]
   }
 }
@@ -573,7 +564,7 @@
 
     # TODO(jdduke) Re-enable on mips after resolving linking
     # issues with libc++ (crbug.com/456380).
-    if (cpu_arch != "mipsel" && cpu_arch != "mips64el") {
+    if (current_cpu != "mipsel" && current_cpu != "mips64el") {
       ldflags += [ "-Wl,--warn-shared-textrel" ]
     }
     ldflags += [ "-nostdlib" ]
@@ -684,20 +675,6 @@
       "-Wno-deprecated",
     ]
   }
-
-  if (is_android_webview_build) {
-    # There is a class of warning which:
-    #  1) Android always enables and also treats as errors
-    #  2) Chromium ignores in third party code
-    # So we re-enable those warnings when building Android.
-    cflags += [
-      "-Wno-address",
-      "-Wno-format-security",
-      "-Wno-return-type",
-      "-Wno-sequence-point",
-    ]
-    cflags_cc += [ "-Wno-non-virtual-dtor" ]
-  }
 }
 
 # rtti ------------------------------------------------------------------------
@@ -983,7 +960,7 @@
 
     # TODO(jdduke) Re-enable on mips after resolving linking
     # issues with libc++ (crbug.com/456380).
-    if (cpu_arch != "mipsel" && cpu_arch != "mips64el") {
+    if (current_cpu != "mipsel" && current_cpu != "mips64el") {
       common_optimize_on_ldflags += [
         # Warn in case of text relocations.
         "-Wl,--warn-shared-textrel",
diff --git a/build/config/crypto.gni b/build/config/crypto.gni
index ee23569..7f090b7 100644
--- a/build/config/crypto.gni
+++ b/build/config/crypto.gni
@@ -14,10 +14,13 @@
   use_openssl = is_android || is_mac || is_nacl || is_win
 }
 
-# True when we're using OpenSSL for certificate verification and storage. We
-# only do this when we're using OpenSSL on desktop Linux systems. For other
-# systems (Mac/Win/Android) we use the system certificate features.
-use_openssl_certs = use_openssl && (is_linux || is_android)
+# True when we're using OpenSSL for representing certificates. When targeting
+# Android, the platform certificate library is used for certificate
+# verification. On other targets, this flag also enables OpenSSL for certificate
+# verification, but this configuration is unsupported.
+use_openssl_certs = is_android
 
-# Same meaning as use_openssl_certs but for NSS.
-use_nss_certs = !use_openssl && is_linux
+# True if NSS is used for certificate verification. Note that this is
+# independent from use_openssl. It is possible to use OpenSSL for the crypto
+# library, but NSS for the platform certificate library.
+use_nss_certs = is_linux
diff --git a/build/config/features.gni b/build/config/features.gni
index 783e32d..dd7b081 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -47,6 +47,9 @@
   # TODO(GYP) make mac and android work.
   enable_webrtc = !is_ios && !is_mac && !is_android
 
+  # Enables the Media Router.
+  enable_media_router = !is_ios && !is_android
+
   # Enables proprietary codecs and demuxers; e.g. H264, MOV, AAC, and MP3.
   proprietary_codecs = false
 
@@ -67,13 +70,20 @@
 
   enable_supervised_users = !is_ios
 
-  enable_autofill_dialog = !is_ios && !(is_android && is_android_webview_build)
+  enable_autofill_dialog = !is_ios
 
   enable_google_now = !is_ios && !is_android
 
   enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
 
   enable_remoting = !is_ios && !is_android
+
+  # Enable hole punching for the protected video.
+  enable_video_hole = is_android
+
+  # Enables browser side Content Decryption Modules. Required for embedders
+  # (e.g. Android and ChromeCast) that use a browser side CDM.
+  enable_browser_cdms = is_android
 }
 
 # Additional dependent variables -----------------------------------------------
@@ -96,8 +106,6 @@
 
 enable_pepper_cdms = enable_plugins && (is_linux || is_mac || is_win)
 
-enable_browser_cdms = is_android
-
 # Enable basic printing support and UI.
 enable_basic_printing = !is_chromeos
 
diff --git a/build/config/gcc/gcc_version.gni b/build/config/gcc/gcc_version.gni
index f5c1c1a..6741e45 100644
--- a/build/config/gcc/gcc_version.gni
+++ b/build/config/gcc/gcc_version.gni
@@ -3,12 +3,7 @@
 # found in the LICENSE file.
 
 if (is_android) {
-  import("//build/config/android/config.gni")
-  if (is_android_webview_build) {
-    gcc_version = 48
-  } else {
-    gcc_version = 49
-  }
+  gcc_version = 49
 } else if (current_toolchain == "//build/toolchain/cros:target" ||
            current_toolchain == "//build/toolchain/linux:mipsel") {
   gcc_version = exec_script("../../compiler_version.py",
diff --git a/build/config/linux/gtk/BUILD.gn b/build/config/linux/gtk/BUILD.gn
index 4968e2d..9c9c696 100644
--- a/build/config/linux/gtk/BUILD.gn
+++ b/build/config/linux/gtk/BUILD.gn
@@ -26,9 +26,12 @@
 group("gtk") {
   visibility = [
     "//chrome/browser/ui/libgtk2ui",
+    "//gpu/gles2_conform_support:gles2_conform_test_windowless",
     "//remoting/host",
+    "//remoting/host/it2me:remote_assistance_host",
+    "//remoting/host:remoting_me2me_host_static",
   ]
-  direct_dependent_configs = [ ":gtk_internal_config" ]
+  public_configs = [ ":gtk_internal_config" ]
 }
 
 # Depend on "gtkprint" to get this.
@@ -38,5 +41,5 @@
 
 group("gtkprint") {
   visibility = [ "//chrome/browser/ui/libgtk2ui" ]
-  direct_dependent_configs = [ ":gtkprint_internal_config" ]
+  public_configs = [ ":gtkprint_internal_config" ]
 }
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index 941c77a..057971d 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -15,22 +15,18 @@
   sysroot = target_sysroot
 } else if (is_android) {
   import("//build/config/android/config.gni")
-  if (!is_android_webview_build) {
-    if (current_cpu == "x86") {
-      sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
-    } else if (current_cpu == "arm") {
-      sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
-    } else if (current_cpu == "mipsel") {
-      sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
-    } else if (current_cpu == "x64") {
-      sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
-    } else if (current_cpu == "arm64") {
-      sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
-    } else if (current_cpu == "mips64") {
-      sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
-    } else {
-      sysroot = ""
-    }
+  if (current_cpu == "x86") {
+    sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
+  } else if (current_cpu == "arm") {
+    sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
+  } else if (current_cpu == "mipsel") {
+    sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
+  } else if (current_cpu == "x64") {
+    sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
+  } else if (current_cpu == "arm64") {
+    sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
+  } else if (current_cpu == "mips64") {
+    sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
   } else {
     sysroot = ""
   }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 4ca22f7..8b0910f 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -97,25 +97,36 @@
 
 # Subsystem --------------------------------------------------------------------
 
+# This is appended to the subsystem to specify a minimum version.
+if (current_cpu == "x64") {
+  # The number after the comma is the minimum required OS version.
+  # 5.02 = Windows Server 2003.
+  subsystem_version_suffix = ",5.02"
+} else {
+  # Don't specify a min version on x86.
+  subsystem_version_suffix = ""
+}
+
 config("console") {
-  ldflags = [ "/SUBSYSTEM:CONSOLE" ]
+  ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
 }
 config("windowed") {
-  ldflags = [ "/SUBSYSTEM:WINDOWS" ]
+  ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
 }
 
 # Incremental linking ----------------------------------------------------------
 
 incremental_linking_on_switch = [ "/INCREMENTAL" ]
 incremental_linking_off_switch = [ "/INCREMENTAL:NO" ]
+if (is_debug) {
+  default_incremental_linking_switch = incremental_linking_on_switch
+} else {
+  default_incremental_linking_switch = incremental_linking_off_switch
+}
 
 # Applies incremental linking or not depending on the current configuration.
 config("default_incremental_linking") {
-  if (is_debug) {
-    ldflags = incremental_linking_on_switch
-  } else {
-    ldflags = incremental_linking_off_switch
-  }
+  ldflags = default_incremental_linking_switch
 }
 
 # Explicitly on or off incremental linking
@@ -130,17 +141,13 @@
 # config should be applied to large modules to turn off incremental linking
 # when it won't work.
 config("default_large_module_incremental_linking") {
-  if (!is_debug) {
-    # Default is always off in release build.
-    ldflags = incremental_linking_off_switch
-  } else if ((symbol_level == 0 || symbol_level == 1) &&
-             (current_cpu == "x86" || !is_component_build)) {
-    # When full symbols are on, don't do incremental linking for large modules
-    # on 32-bit or in non-component mode as the toolchain fails due to the size
-    # of the .ilk files.
+  if (symbol_level > 0 && (current_cpu == "x86" || !is_component_build)) {
+    # When symbols are on, things get so large that the tools fail due to the
+    # size of the .ilk files.
     ldflags = incremental_linking_off_switch
   } else {
-    ldflags = incremental_linking_on_switch
+    # Otherwise just do the default incremental linking for this build type.
+    ldflags = default_incremental_linking_switch
   }
 }
 
diff --git a/build/escape_unicode.py b/build/escape_unicode.py
deleted file mode 100755
index 859ba5d..0000000
--- a/build/escape_unicode.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-
-"""Convert any unicode characters found in the input file to C literals."""
-
-import codecs
-import optparse
-import os
-import sys
-
-
-def main(argv):
-  parser = optparse.OptionParser()
-  usage = 'Usage: %prog -o <output_dir> <input_file>'
-  parser.set_usage(usage)
-  parser.add_option('-o', dest='output_dir')
-
-  options, arglist = parser.parse_args(argv)
-
-  if not options.output_dir:
-    print "output_dir required"
-    return 1
-
-  if len(arglist) != 2:
-    print "input_file required"
-    return 1
-
-  in_filename = arglist[1]
-
-  if not in_filename.endswith('.utf8'):
-    print "input_file should end in .utf8"
-    return 1
-
-  out_filename = os.path.join(options.output_dir, os.path.basename(
-      os.path.splitext(in_filename)[0]))
-
-  WriteEscapedFile(in_filename, out_filename)
-  return 0
-
-
-def WriteEscapedFile(in_filename, out_filename):
-  input_data = codecs.open(in_filename, 'r', 'utf8').read()
-  with codecs.open(out_filename, 'w', 'ascii') as out_file:
-    for i, char in enumerate(input_data):
-      if ord(char) > 127:
-        out_file.write(repr(char.encode('utf8'))[1:-1])
-        if input_data[i + 1:i + 2] in '0123456789abcdefABCDEF':
-          out_file.write('""')
-      else:
-        out_file.write(char.encode('ascii'))
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index 8413002..58e7ff5 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -39,12 +39,6 @@
         '../base/base.gyp:base_unittests',
         '../base/base.gyp:build_utf8_validator_tables#host',
         '../base/base.gyp:check_example',
-        '../base/base.gyp:protect_file_posix',
-        '../breakpad/breakpad.gyp:core-2-minidump',
-        '../breakpad/breakpad.gyp:microdump_stackwalk',
-        '../breakpad/breakpad.gyp:minidump_dump',
-        '../breakpad/breakpad.gyp:minidump_stackwalk',
-        '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
         '../cc/cc_tests.gyp:cc_perftests',
         '../cc/cc_tests.gyp:cc_unittests',
         '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
@@ -56,16 +50,18 @@
         '../chrome/chrome.gyp:chromedriver_unittests',
         '../chrome/chrome.gyp:interactive_ui_tests',
         '../chrome/chrome.gyp:load_library_perf_tests',
-        '../chrome/chrome.gyp:service_discovery_sniffer',
+        '../chrome/chrome.gyp:performance_browser_tests',
         '../chrome/chrome.gyp:sync_integration_tests',
         '../chrome/chrome.gyp:sync_performance_tests',
         '../chrome/chrome.gyp:unit_tests',
         '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler',
+        '../cloud_print/cloud_print.gyp:cloud_print_unittests',
         '../components/components.gyp:network_hints_browser',
+        '../components/components.gyp:policy_templates',
         '../components/components.gyp:webui_generator',
+        '../components/components_tests.gyp:components_browsertests',
         '../components/components_tests.gyp:components_perftests',
         '../components/components_tests.gyp:components_unittests',
-        '../components/nacl.gyp:nacl_loader_unittests',
         '../content/content.gyp:content_app_browser',
         '../content/content.gyp:content_app_child',
         '../content/content_shell_and_tests.gyp:content_browsertests',
@@ -92,6 +88,9 @@
         '../gpu/gpu.gyp:gl_tests',
         '../gpu/gpu.gyp:gpu_perftests',
         '../gpu/gpu.gyp:gpu_unittests',
+        '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',  # TODO(GYP) crbug.com/471920
+        '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',  # TODO(GYP) crbug.com/471920
+        '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',  # TODO(GYP) crbug.com/471903 to make this complete.
         '../ipc/ipc.gyp:ipc_perftests',
         '../ipc/ipc.gyp:ipc_tests',
         '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
@@ -121,9 +120,43 @@
         '../net/net.gyp:run_testserver',
         '../net/net.gyp:stress_cache',
         '../net/net.gyp:tld_cleanup',
-        '../ppapi/ppapi_internal.gyp:*',  # TODO(GYP) - list all of the examples explicitly.
-        '../ppapi/ppapi_internal.gyp:ppapi_tests',  # TODO(GYP): Split out the examples and tests
+        '../ppapi/ppapi_internal.gyp:ppapi_example_audio',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_audio_input',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_c_stub',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_cc_stub',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_compositor',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_crxfs',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_enumerate_devices',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_file_chooser',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_flash_topmost',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gamepad',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gles2',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gles2_spinning_cube',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_graphics_2d',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_ime',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_input',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_media_stream_audio',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_media_stream_video',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_mouse_cursor',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_mouse_lock',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_paint_manager',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_post_message',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_printing',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_scaling',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_scroll',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_simple_font',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_threading',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_url_loader',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_url_loader_file',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_vc',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode_dev',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_effects',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_encode',
+        '../ppapi/ppapi_internal.gyp:ppapi_tests',
+        '../ppapi/ppapi_internal.gyp:ppapi_perftests',
         '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+        '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
         '../printing/printing.gyp:printing_unittests',
         '../skia/skia_tests.gyp:skia_unittests',
         '../skia/skia.gyp:filter_fuzz_stub',
@@ -148,9 +181,9 @@
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
+        '../third_party/pdfium/samples/samples.gyp:pdfium_diff',
         '../third_party/pdfium/samples/samples.gyp:pdfium_test',
         '../third_party/smhasher/smhasher.gyp:pmurhash',
-        '../third_party/sqlite/sqlite.gyp:sqlite_shell',
         '../tools/gn/gn.gyp:gn',
         '../tools/gn/gn.gyp:generate_test_gn_data',
         '../tools/gn/gn.gyp:gn_unittests',
@@ -164,7 +197,6 @@
         '../ui/display/display.gyp:display_unittests',
         '../ui/events/events.gyp:events_unittests',
         '../ui/gfx/gfx_tests.gyp:gfx_unittests',
-        '../ui/keyboard/keyboard.gyp:keyboard_unittests',
         '../ui/message_center/message_center.gyp:message_center_unittests',
         '../ui/snapshot/snapshot.gyp:snapshot_unittests',
         '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
@@ -174,28 +206,36 @@
         '../v8/tools/gyp/v8.gyp:postmortem-metadata',
       ],
       'conditions': [
+        ['clang==1', {
+          'dependencies': [
+            '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
+          ],
+        }],
+        ['disable_nacl==0 and disable_nacl_untrusted==0', {
+          'dependencies': [
+            '../components/nacl.gyp:nacl_loader_unittests',
+          ]
+        }],
         ['enable_extensions==1 and OS!="mac"', {
           'dependencies': [
             '../extensions/shell/app_shell.gyp:app_shell',
             '../extensions/shell/app_shell.gyp:app_shell_unittests',
           ],
         }],
-        ['OS!="win"', {
+        ['enable_mdns==1', {
           'dependencies': [
-            '../breakpad/breakpad.gyp:symupload',
+            '../chrome/chrome.gyp:service_discovery_sniffer',
+          ]
+        }],
+        ['remoting==1', {
+          'dependencies': [
+            '../remoting/remoting_all.gyp:remoting_all',
           ],
         }],
-        ['use_x11==1', {
+        ['remoting==1 and chromeos==0', {
           'dependencies': [
-            '../media/media.gyp:player_x11',
-            '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
-          ],
-          'conditions': [
-            ['target_arch!="arm"', {
-              'dependencies': [
-                '../gpu/tools/tools.gyp:compositor_model_bench',
-              ],
-            }],
+            '../remoting/remoting.gyp:remoting_me2me_host',
+            '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
           ],
         }],
         ['toolkit_views==1', {
@@ -211,11 +251,17 @@
             '../ash/ash.gyp:ash_unittests',
           ],
         }],
+        ['use_ash==1 or chromeos== 1', {
+          'dependencies': [
+            '../components/components.gyp:session_manager_component',
+          ]
+        }],
         ['use_aura==1', {
           'dependencies': [
             '../ui/aura/aura.gyp:aura_bench',
             '../ui/aura/aura.gyp:aura_demo',
             '../ui/aura/aura.gyp:aura_unittests',
+            '../ui/keyboard/keyboard.gyp:keyboard_unittests',
             '../ui/wm/wm.gyp:wm_unittests',
           ],
         }],
@@ -224,9 +270,18 @@
             '../ui/ozone/ozone.gyp:ozone',
           ],
         }],
-        ['OS=="win" or OS=="mac" or chromeos==1', {
+
+
+        ['use_x11==1', {
           'dependencies': [
-            '../rlz/rlz.gyp:rlz_lib',
+            '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+          ],
+          'conditions': [
+            ['target_arch!="arm"', {
+              'dependencies': [
+                '../gpu/tools/tools.gyp:compositor_model_bench',
+              ],
+            }],
           ],
         }],
         ['OS=="android"', {
@@ -275,6 +330,7 @@
             '../chrome/chrome.gyp:chromedriver',
             '../chrome/chrome.gyp:chromedriver_unitests',
             '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:performance_browser_tests',
             '../chrome/chrome.gyp:sync_integration_tests',
             '../chrome/chrome.gyp:unit_tests',
             '../extensions/extensions_tests.gyp:extensions_browsertests',
@@ -294,10 +350,38 @@
             '../url/url.gyp:url_unittests',
           ],
         }],
+        ['OS=="android" or OS=="linux"', {
+          'dependencies': [
+            '../net/net.gyp:disk_cache_memory_test',
+          ],
+        }],
+        ['chromeos==1', {
+          'dependencies': [
+            '../chromeos/chromeos.gyp:chromeos_unittests',
+            '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
+          ]
+        }],
+        ['chromeos==1 or OS=="win" or OS=="mac"', {
+          'dependencies': [
+            '../rlz/rlz.gyp:rlz_id',
+            '../rlz/rlz.gyp:rlz_lib',
+            '../rlz/rlz.gyp:rlz_unittests',
+          ],
+        }],
+        ['OS=="android" or OS=="linux" or os_bsd==1', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:core-2-minidump',
+            '../breakpad/breakpad.gyp:microdump_stackwalk',
+            '../breakpad/breakpad.gyp:minidump_dump',
+            '../breakpad/breakpad.gyp:minidump_stackwalk',
+            '../breakpad/breakpad.gyp:symupload',
+            '../third_party/codesighs/codesighs.gyp:nm2tsv',
+          ],
+        }],
         ['OS=="linux"', {
           'dependencies': [
             '../breakpad/breakpad.gyp:breakpad_unittests',
-            '../breakpad/breakpad.gyp:dump_syms',
+            '../breakpad/breakpad.gyp:dump_syms#host',
             '../breakpad/breakpad.gyp:generate_test_dump',
             '../breakpad/breakpad.gyp:minidump-2-core',
             '../dbus/dbus.gyp:dbus_test_server',
@@ -306,6 +390,8 @@
             '../net/net.gyp:disk_cache_memory_test',
             '../net/net.gyp:flip_in_mem_edsm_server',
             '../net/net.gyp:flip_in_mem_edsm_server_unittests',
+            '../net/net.gyp:epoll_quic_client',
+            '../net/net.gyp:epoll_quic_server',
             '../net/net.gyp:hpack_example_generator',
             '../net/net.gyp:hpack_fuzz_mutator',
             '../net/net.gyp:hpack_fuzz_wrapper',
@@ -315,6 +401,7 @@
             '../sandbox/sandbox.gyp:chrome_sandbox',
             '../sandbox/sandbox.gyp:sandbox_linux_unittests',
             '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
+            '../third_party/sqlite/sqlite.gyp:sqlite_shell',
          ],
         }],
         ['OS=="mac"', {
@@ -372,22 +459,38 @@
         }],
         ['OS=="win"', {
           'dependencies': [
-            "//ui/metro_viewer",
+            '../base/base.gyp:pe_image_test',
+            '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests',
+            '../chrome_elf/chrome_elf.gyp:dll_hash_main',
+            '../components/components.gyp:wifi_test',
+            '../net/net.gyp:quic_client',
+            '../net/net.gyp:quic_server',
+            '../sandbox/sandbox.gyp:pocdll',
+            '../sandbox/sandbox.gyp:sandbox_poc',
+            '../sandbox/sandbox.gyp:sbox_integration_tests',
+            '../sandbox/sandbox.gyp:sbox_unittests',
+            '../sandbox/sandbox.gyp:sbox_validation_tests',
+            '../testing/gtest.gyp:gtest_main',
             '../third_party/codesighs/codesighs.gyp:msdump2symdb',
-          ],
-          'dependencies!': [
-            "//crypto:crypto_unittests",  # TODO(GYP)
-            "//net:net_unittests",  # TODO(GYP)
-          ],
-        }, {
-          'dependencies': [
-            '../third_party/codesighs/codesighs.gyp:nm2tsv',
+            '../third_party/codesighs/codesighs.gyp:msmap2tsv',
+            '../third_party/pdfium/samples/samples.gyp:pdfium_diff',
+            '../win8/win8.gyp:metro_viewer',
           ],
         }],
-        ['OS=="android" or OS=="linux"', {
-          'dependencies': [
-            '../net/net.gyp:disk_cache_memory_test',
-          ],
+      ],
+    },
+    {
+      'target_name': 'gyp_only',
+      'type': 'none',
+      'conditions': [
+        ['OS=="linux" or OS=="win"', {
+          'conditions': [
+            ['disable_nacl==0 and disable_nacl_untrusted==0', {
+              'dependencies': [
+                '../mojo/mojo_nacl.gyp:monacl_shell',  # This should not be built in chromium.
+              ]
+            }],
+          ]
         }],
       ],
     },
@@ -395,135 +498,172 @@
       'target_name': 'gyp_remaining',
       'type': 'none',
       'conditions': [
-        ['OS=="linux"', {
+        ['remoting==1', {
           'dependencies': [
-            '../chrome/chrome.gyp:performance_browser_tests',
-            '../cloud_print/cloud_print.gyp:cloud_print_unittests',
-            '../components/components.gyp:policy_templates',
-            '../components/components_tests.gyp:components_browsertests',
-            '../components/components_tests.gyp:components_perftests',
-            '../content/content.gyp:content_app_browser',
-            '../content/content.gyp:content_app_child',
-            '../content/content_shell_and_tests.gyp:content_gl_benchmark',
-            '../content/content_shell_and_tests.gyp:content_gl_tests',
-            '../courgette/courgette.gyp:courgette',
-            '../courgette/courgette.gyp:courgette_fuzz',
-            '../dbus/dbus.gyp:dbus_test_server',
-            '../device/device_tests.gyp:device_unittests',
-            '../gin/gin.gyp:gin_v8_snapshot_fingerprint',
-            '../gin/gin.gyp:gin_shell',
-            '../gpu/gpu.gyp:gl_tests',
-            '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
-            '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
-            '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
-            '../media/cast/cast.gyp:cast_benchmarks',
-            '../media/cast/cast.gyp:generate_barcode_video',
-            '../media/cast/cast.gyp:generate_timecode_audio',
-            '../media/cast/cast.gyp:tap_proxy',
-            '../mojo/mojo_base.gyp:mojo_application_chromium',
-            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
-            '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
-            '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
-            '../skia/skia.gyp:filter_fuzz_stub',
-            '../skia/skia.gyp:image_operations_bench',
-            '../sync/sync.gyp:run_sync_testserver',
-            '../sync/sync.gyp:sync_endtoend_tests',
-            '../sync/tools/sync_tools.gyp:sync_client',
-            '../sync/tools/sync_tools.gyp:sync_listen_notifications',
-            '../testing/gmock.gyp:gmock_main',
-            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
-            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
-            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../remoting/app_remoting_webapp.gyp:ar_sample_app',  # crbug.com/471916
+          ],
+        }],
+        ['test_isolation_mode!="noop"', {
+          'dependencies': [
+            '../base/base.gyp:base_unittests_run',
+            '../cc/cc_tests.gyp:cc_unittests_run',
+            '../chrome/chrome.gyp:browser_tests_run',
+            '../chrome/chrome.gyp:chrome_run',
+            '../chrome/chrome.gyp:interactive_ui_tests_run',
+            '../chrome/chrome.gyp:sync_integration_tests_run',
+            '../chrome/chrome.gyp:unit_tests_run',
+            '../components/components_tests.gyp:components_browsertests_run',
+            '../components/components_tests.gyp:components_unittests_run',
+            '../content/content_shell_and_tests.gyp:content_browsertests_run',
+            '../content/content_shell_and_tests.gyp:content_unittests_run',
+            '../crypto/crypto.gyp:crypto_unittests_run',
+            '../courgette/courgette.gyp:courgette_unittests_run',
+            '../gpu/gpu.gyp:gpu_unittests_run',
+            '../media/cast/cast.gyp:cast_unittests_run',
+            '../media/media.gyp:media_unittests_run',
+            '../net/net.gyp:net_unittests_run',
+            '../sql/sql.gyp:sql_unittests_run',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
+            '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
+            '../ui/app_list/app_list.gyp:app_list_unittests_run',
+            '../ui/events/events.gyp:events_unittests_run',
+            '../ui/message_center/message_center.gyp:message_center_unittests_run',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
+          ],
+        }],
+        ['test_isolation_mode!="noop" and use_ash==1', {
+          'dependencies': [
+            '../ash/ash.gyp:ash_unittests_run',
+          ],
+        }],
+        ['test_isolation_mode!="noop" and OS=="linux"', {
+          'dependencies': [
+            '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
+          ],
+        }],
+        ['use_openssl==1', {
+          'dependencies': [
+            # TODO(GYP): All of these targets still need to be converted.
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ecdsa_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bn_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pqueue_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_digest_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_cipher_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_hkdf_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_constant_time_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_thread_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_base64_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_gcm_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bytestring_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_evp_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_dsa_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_rsa_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_hmac_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_aead_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ssl_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_err_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_lhash_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pbkdf_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_dh_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs12_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_example_mul',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ec_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bio_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs7_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_unittests',
+          ],
+        }],
+        ['chromeos==1', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:video_encode_accelerator_unittest',
+          ],
+        }],
+        ['chromeos==1 and target_arch != "arm"', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:vaapi_jpeg_decoder_unittest',
+          ],
+        }],
+        ['chromeos==1 or OS=="win" or OS=="android"', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest',
+          ],
+        }],
+        ['OS=="linux" or OS=="win"', {
+          'dependencies': [
+            # TODO(GYP): Figure out which of these run on android/mac/win/ios/etc.
+            '../net/net.gyp:net_docs',
+            '../remoting/app_remoting_test.gyp:ar_sample_test_driver',
+
+            # TODO(GYP): in progress - see tfarina.
             '../third_party/webrtc/tools/tools.gyp:frame_analyzer',
             '../third_party/webrtc/tools/tools.gyp:rgba_to_i420_converter',
-            '../tools/gn/gn.gyp:generate_test_gn_data',
-            '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
-            #'../tools/telemetry/telemetry.gyp:bitmaptools', TODO(GYP) should this be #host ?
-            '../ui/compositor/compositor.gyp:compositor_unittests',
-            '../ui/message_center/message_center.gyp:message_center_unittests',
-            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
-            '../v8/tools/gyp/v8.gyp:v8_snapshot',
-            '../v8/tools/gyp/v8.gyp:postmortem-metadata',
-
-            # TODO(GYP) - list all of the examples explicitly.
-            '../ppapi/ppapi_internal.gyp:*',
           ],
-          'conditions': [
-            ['disable_nacl==0 and disable_nacl_untrusted==0', {
-              'dependencies': [
-                '../components/nacl.gyp:nacl_loader_unittests',
-                '../mojo/mojo_nacl.gyp:monacl_shell',  # TODO(GYP) This will be deleted; don't port
-                '../remoting/remoting.gyp:remoting_key_tester',
-              ]
-            }],
-            ['chromeos== 1 or use_ash==1', {
-              'dependencies': [
-                '../components/components.gyp:session_manager_component',
-              ],
-            }],
-            ['use_x11==1', {
-              'dependencies': [
-                '../gpu/tools/tools.gyp:compositor_model_bench',
-                '../media/media.gyp:player_x11',
-              ],
-            }],
-            ['remoting==1', {
-              'dependencies': [
-                '../remoting/app_remoting_webapp.gyp:ar_sample_app',
-                '../remoting/remoting.gyp:remoting_host',
-                '../remoting/remoting.gyp:remoting_it2me_native_messaging_host',
-                '../remoting/remoting.gyp:remoting_key_tester',
-                '../remoting/remoting.gyp:remoting_me2me_host',
-                '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
-                '../remoting/remoting.gyp:remoting_native_messaging_manifests',
-                '../remoting/remoting.gyp:remoting_perftests',
-                '../remoting/remoting.gyp:remoting_start_host',
-                '../remoting/remoting.gyp:remoting_unittests',
-              ],
-            }],
-            ['toolkit_views==1', {
-              'dependencies': [
-                '../ui/app_list/app_list.gyp:app_list_demo',
-              ],
-            }],
-            ['test_isolation_mode!="noop"', {
-              'dependencies': [
-                '../base/base.gyp:base_unittests_run',
-                '../cc/cc_tests.gyp:cc_unittests_run',
-                '../chrome/chrome.gyp:browser_tests_run',
-                '../chrome/chrome.gyp:chrome_run',
-                '../chrome/chrome.gyp:interactive_ui_tests_run',
-                '../chrome/chrome.gyp:sync_integration_tests_run',
-                '../chrome/chrome.gyp:unit_tests_run',
-                '../components/components_tests.gyp:components_browsertests_run',
-                '../components/components_tests.gyp:components_unittests_run',
-                '../content/content_shell_and_tests.gyp:content_browsertests_run',
-                '../content/content_shell_and_tests.gyp:content_unittests_run',
-                '../crypto/crypto.gyp:crypto_unittests_run',
-                '../courgette/courgette.gyp:courgette_unittests_run',
-                '../gpu/gpu.gyp:gpu_unittests_run',
-                '../media/cast/cast.gyp:cast_unittests_run',
-                '../media/media.gyp:media_unittests_run',
-                '../net/net.gyp:net_unittests_run',
-                '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
-                '../sql/sql.gyp:sql_unittests_run',
-                '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
-                '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
-                '../ui/app_list/app_list.gyp:app_list_unittests_run',
-                '../ui/events/events.gyp:events_unittests_run',
-                '../ui/message_center/message_center.gyp:message_center_unittests_run',
-                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
-              ],
-              'conditions': [
-                ['use_ash==1', {
-                  'dependencies': [
-                    '../ash/ash.gyp:ash_unittests_run',
-                  ],
-                }],
-              ],
-            }],
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            # TODO(GYP): All of these targets still need to be converted.
+            '../base/base.gyp:debug_message',
+            '../chrome/chrome.gyp:app_installer',
+            '../chrome/chrome.gyp:app_installer_unittests',
+            '../chrome/chrome.gyp:app_shim',
+            '../chrome/chrome.gyp:crash_service',
+            '../chrome/chrome.gyp:gcapi_dll',
+            '../chrome/chrome.gyp:gcapi_test',
+            '../chrome/chrome.gyp:installer_util_unittests',
+            '../chrome/chrome.gyp:pack_policy_templates',
+            '../chrome/chrome.gyp:sb_sigutil',
+            '../chrome/chrome.gyp:setup',
+            '../chrome/chrome.gyp:setup_unittests',
+            '../chrome/installer/mini_installer.gyp:mini_installer',
+            '../chrome/tools/crash_service/caps/caps.gyp:caps',
+            '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device',
+            '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device_unittests',
+            '../cloud_print/service/service.gyp:cloud_print_service',
+            '../cloud_print/service/service.gyp:cloud_print_service_config',
+            '../cloud_print/service/service.gyp:cloud_print_service_setup',
+            '../cloud_print/virtual_driver/win/install/virtual_driver_install.gyp:virtual_driver_setup',
+            '../cloud_print/virtual_driver/win/virtual_driver.gyp:gcp_portmon',
+            '../content/content_shell_and_tests.gyp:content_shell_crash_service',
+            '../content/content_shell_and_tests.gyp:layout_test_helper',
+            '../gpu/gpu.gyp:angle_end2end_tests',
+            '../gpu/gpu.gyp:angle_perftests',
+            '../net/net.gyp:net_docs',
+            '../ppapi/ppapi_internal.gyp:ppapi_perftests',
+            '../remoting/app_remoting_test.gyp:ar_sample_test_driver',
+            '../remoting/remoting.gyp:remoting_breakpad_tester',
+            '../remoting/remoting.gyp:remoting_console',
+            '../remoting/remoting.gyp:remoting_desktop',
+            '../rlz/rlz.gyp:rlz',
+            '../tools/win/static_initializers/static_initializers.gyp:static_initializers',
           ],
         }],
+        ['OS=="win" and win_use_allocator_shim==1', {
+          'dependencies': [
+            '../base/allocator/allocator.gyp:allocator_unittests',
+          ]
+        }],
+        ['OS=="win" and target_arch=="ia32"', {
+          'dependencies': [
+            # TODO(GYP): All of these targets need to be ported over.
+            '../base/base.gyp:base_win64',
+            '../base/base.gyp:base_i18n_nacl_win64',
+            '../chrome/chrome.gyp:crash_service_win64',
+            '../chrome/chrome.gyp:launcher_support64',
+            '../components/components.gyp:breakpad_win64',
+            '../courgette/courgette.gyp:courgette64',
+            '../crypto/crypto.gyp:crypto_nacl_win64',
+            '../ipc/ipc.gyp:ipc_win64',
+            '../sandbox/sandbox.gyp:sandbox_win64',
+            '../cloud_print/virtual_driver/win/virtual_driver64.gyp:gcp_portmon64',
+            '../cloud_print/virtual_driver/win/virtual_driver64.gyp:virtual_driver_lib64',
+          ],
+        }],
+        ['OS=="win" and target_arch=="ia32" and configuration_policy==1', {
+          'dependencies': [
+            # TODO(GYP): All of these targets need to be ported over.
+            '../components/components.gyp:policy_win64',
+          ]
+        }],
       ],
     },
     {
@@ -533,7 +673,6 @@
       'type': 'none',
       'dependencies': [
         'All',
-        'aura_builder',
         'blink_tests',
         'chromium_builder_asan',
         'chromium_builder_chromedriver',
@@ -543,6 +682,22 @@
         'chromium_gpu_builder',
         'chromium_gpu_debug_builder',
       ],
+      'conditions': [
+        ['use_aura==1', {
+          'dependencies': [
+            'aura_builder',
+          ]
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            'chromium_builder',
+            'chromium_builder_dbg_drmemory_win',
+            'chromium_builder_nacl_sdk',
+            'chromium_builder_lkgr_drmemory_win',
+            'chromium_builder_dbg_tsan_win',
+          ],
+        }],
+      ],
     },
   ]
 }
diff --git a/build/grit_action.gypi b/build/grit_action.gypi
index 462fb4c..b24f0f8 100644
--- a/build/grit_action.gypi
+++ b/build/grit_action.gypi
@@ -50,11 +50,12 @@
   ],
   'inputs': [
     '<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
-        '--inputs <(grit_grd_file) -f "<(grit_resource_ids)")',
+        '<@(grit_whitelist_flag) --inputs <(grit_grd_file) '
+        '-f "<(grit_resource_ids)")',
   ],
   'outputs': [
     '<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
-        '--outputs \'<(grit_out_dir)\' '
+        '<@(grit_whitelist_flag) --outputs \'<(grit_out_dir)\' '
         '<(grit_grd_file) -f "<(grit_resource_ids)")',
   ],
   'action': ['<@(grit_cmd)',
diff --git a/build/gyp_chromium b/build/gyp_chromium
index 45f3206..4ed15ba 100755
--- a/build/gyp_chromium
+++ b/build/gyp_chromium
@@ -30,9 +30,6 @@
 # Add paths so that pymod_do_main(...) can import files.
 sys.path.insert(1, os.path.join(chrome_src, 'android_webview', 'tools'))
 sys.path.insert(1, os.path.join(chrome_src, 'build', 'android', 'gyp'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
 sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build'))
 sys.path.insert(1, os.path.join(chrome_src, 'chromecast', 'tools', 'build'))
 sys.path.insert(1, os.path.join(chrome_src, 'native_client', 'build'))
@@ -42,6 +39,9 @@
 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'liblouis'))
 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit',
     'Source', 'build', 'scripts'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
 
 # On Windows, Psyco shortens warm runs of build/gyp_chromium by about
 # 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
diff --git a/build/gyp_helper.py b/build/gyp_helper.py
index 9be2b9e..c840f2d 100644
--- a/build/gyp_helper.py
+++ b/build/gyp_helper.py
@@ -25,10 +25,12 @@
   supported_vars = (
       'CC',
       'CC_wrapper',
+      'CC.host_wrapper',
       'CHROMIUM_GYP_FILE',
       'CHROMIUM_GYP_SYNTAX_CHECK',
       'CXX',
       'CXX_wrapper',
+      'CXX.host_wrapper',
       'GYP_DEFINES',
       'GYP_GENERATOR_FLAGS',
       'GYP_CROSSCOMPILE',
diff --git a/build/host_jar.gypi b/build/host_jar.gypi
index 6ccc1bd..9c35177 100644
--- a/build/host_jar.gypi
+++ b/build/host_jar.gypi
@@ -3,7 +3,9 @@
 # found in the LICENSE file.
 
 # This file is meant to be included into a target to provide a rule to build
-# a JAR file for use on a host in a consistent manner.
+# a JAR file for use on a host in a consistent manner. If a main class is
+# specified, this file will also generate an executable to run the jar in the
+# output folder's /bin/ directory.
 #
 # To use this, create a gyp target with the following form:
 # {
@@ -69,9 +71,9 @@
             'java_sources!': ['<!@(find <@(excluded_src_paths) -name "*.java")']
           }],
           ['"<(jar_excluded_classes)" != ""', {
-            'extra_options': ['--excluded-classes=<(jar_excluded_classes)']
+            'extra_options': ['--jar-excluded-classes=<(jar_excluded_classes)']
           }],
-          ['">(main_class)" != ""', {
+          ['main_class != ""', {
             'extra_options': ['--main-class=>(main_class)']
           }]
         ],
@@ -97,6 +99,33 @@
         '^@(java_sources)',
       ],
     },
+  ],
+  'conditions': [
+    ['main_class != ""', {
+      'actions': [
+        {
+          'action_name': 'create_java_binary_script_<(_target_name)',
+          'message': 'Creating java binary script <(_target_name)',
+          'variables': {
+            'output': '<(PRODUCT_DIR)/bin/<(_target_name)',
+          },
+          'inputs': [
+            '<(DEPTH)/build/android/gyp/create_java_binary_script.py',
+            '<(jar_path)',
+          ],
+          'outputs': [
+            '<(output)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/gyp/create_java_binary_script.py',
+            '--classpath=>(input_jars_paths)',
+            '--jar-path=<(jar_path)',
+            '--output=<(output)',
+            '--main-class=>(main_class)',
+          ]
+        }
+      ]
+    }]
   ]
 }
 
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index 53d9712..6473794 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -155,6 +155,12 @@
           linux-libc-dev-armhf-cross
           g++-arm-linux-gnueabihf"
 
+# Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056
+if [ "x$lsb_release" = "xtrusty" ]; then
+  arm_list+=" g++-4.8-multilib-arm-linux-gnueabihf
+              gcc-4.8-multilib-arm-linux-gnueabihf"
+fi
+
 # Packages to build NaCl, its toolchains, and its ports.
 naclports_list="ant autoconf bison cmake gawk intltool xutils-dev xsltproc"
 nacl_list="g++-mingw-w64-i686 lib32z1-dev
@@ -360,7 +366,7 @@
     sudo dpkg --add-architecture i386
   fi
 fi
-#sudo apt-get update
+sudo apt-get update
 
 # We initially run "apt-get" with the --reinstall option and parse its output.
 # This way, we can find all the packages that need to be newly installed
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 28407eb..18239b7 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -17,10 +17,12 @@
 IDR_DEFAULT_FAVICON_32
 IDR_DEFAULT_FAVICON_64
 IDR_DIR_HEADER_HTML
+IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL
 IDR_DISTILLER_CSS
 IDR_DISTILLER_JS
 IDR_DOM_DISTILLER_VIEWER_HTML
 IDR_DOM_DISTILLER_VIEWER_JS
+IDR_EXTRACT_PAGE_FEATURES_JS
 IDR_FLAGS_FAVICON
 IDR_FLAGS_HTML
 IDR_FLAGS_JS
@@ -98,7 +100,8 @@
 IDR_TOOLBAR_SHADOW_FULL_BLEED
 IDR_TRANSLATE_JS
 IDR_UBER_UTILS_JS
-IDR_WEBUI_I18N_TEMPLATE2_JS
+IDR_WEBUI_I18N_TEMPLATE_JS
+IDR_WEBUI_I18N_TEMPLATE_POLYMER_JS
 IDR_WEBUI_JSTEMPLATE_JS
 IDR_WEBUI_JS_LOAD_TIME_DATA
 IDS_ABOUT_MAC
@@ -304,6 +307,9 @@
 IDS_DELETE
 IDS_DISABLE_TOUCH_ADJUSTMENT_DESCRIPTION
 IDS_DISABLE_TOUCH_ADJUSTMENT_NAME
+IDS_DOM_DISTILLER_QUALITY_ANSWER_NO
+IDS_DOM_DISTILLER_QUALITY_ANSWER_YES
+IDS_DOM_DISTILLER_QUALITY_QUESTION
 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT
 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE
 IDS_DOM_DISTILLER_VIEWER_LOADING_STRING
@@ -348,6 +354,7 @@
 IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT
 IDS_ERRORPAGES_DETAILS_GONE
 IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED
+IDS_ERRORPAGES_DETAILS_ICANN_NAME_COLLISION
 IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR
 IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED
 IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED
@@ -426,6 +433,7 @@
 IDS_ERRORPAGES_SUMMARY_FORBIDDEN
 IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT
 IDS_ERRORPAGES_SUMMARY_GONE
+IDS_ERRORPAGES_SUMMARY_ICANN_NAME_COLLISION
 IDS_ERRORPAGES_SUMMARY_INTERNAL_SERVER_ERROR
 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED
 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_INSTRUCTIONS_TEMPLATE
@@ -514,8 +522,6 @@
 IDS_FLAGS_ENABLE
 IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_DESCRIPTION
 IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_NAME
-IDS_FLAGS_ENABLE_CARRIER_SWITCHING
-IDS_FLAGS_ENABLE_CARRIER_SWITCHING_DESCRIPTION
 IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH
 IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH_DESCRIPTION
 IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_DESCRIPTION
@@ -530,6 +536,8 @@
 IDS_FLAGS_ENABLE_EXPERIMENTAL_CANVAS_FEATURES_NAME
 IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_DESCRIPTION
 IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_NAME
+IDS_FLAGS_ENABLE_ICON_NTP_DESCRIPTION
+IDS_FLAGS_ENABLE_ICON_NTP_NAME
 IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_DESCRIPTION
 IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_NAME
 IDS_FLAGS_ENABLE_NACL_DEBUG_DESCRIPTION
@@ -762,8 +770,6 @@
 IDS_NUMBERED_PROFILE_NAME
 IDS_OK
 IDS_OMNIBOX_EMPTY_HINT
-IDS_OMNIBOX_EMPTY_HINT_NO_DEFAULT_SEARCH_PROVIDER
-IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER
 IDS_ONE_CLICK_SIGNIN_CONFIRM_EMAIL_DIALOG_CANCEL_BUTTON
 IDS_OPEN_TABS_NOTYETSYNCED
 IDS_OPEN_TABS_PROMOCOMPUTER
@@ -852,8 +858,11 @@
 IDS_POLICY_INVALID_BOOKMARK
 IDS_POLICY_INVALID_PROXY_MODE_ERROR
 IDS_POLICY_INVALID_SEARCH_URL_ERROR
+IDS_POLICY_LABEL_ASSET_ID
 IDS_POLICY_LABEL_CLIENT_ID
+IDS_POLICY_LABEL_DIRECTORY_API_ID
 IDS_POLICY_LABEL_DOMAIN
+IDS_POLICY_LABEL_LOCATION
 IDS_POLICY_LABEL_REFRESH_INTERVAL
 IDS_POLICY_LABEL_STATUS
 IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH
@@ -863,6 +872,7 @@
 IDS_POLICY_LEVEL_RECOMMENDED
 IDS_POLICY_LIST_ENTRY_ERROR
 IDS_POLICY_NEVER_FETCHED
+IDS_POLICY_NOT_SPECIFIED
 IDS_POLICY_NOT_SPECIFIED_ERROR
 IDS_POLICY_NO_POLICIES_SET
 IDS_POLICY_OK
@@ -979,6 +989,7 @@
 IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE_V2
 IDS_SAFE_BROWSING_PRIVACY_POLICY_URL
 IDS_SAVE
+IDS_SEARCH_BOX_EMPTY_HINT
 IDS_SECURE_CONNECTION_EV
 IDS_SESSION_CRASHED_VIEW_MESSAGE
 IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON
@@ -1078,138 +1089,28 @@
 IDS_SYNC_UPGRADE_CLIENT
 IDS_SYSTEM_FLAGS_OWNER_ONLY
 IDS_TERMS_HTML
-IDS_TIME_DAYS_1ST_DEFAULT
-IDS_TIME_DAYS_1ST_FEW
-IDS_TIME_DAYS_1ST_MANY
-IDS_TIME_DAYS_1ST_SINGULAR
-IDS_TIME_DAYS_1ST_TWO
-IDS_TIME_DAYS_1ST_ZERO
-IDS_TIME_DAYS_DEFAULT
-IDS_TIME_DAYS_FEW
-IDS_TIME_DAYS_MANY
-IDS_TIME_DAYS_SINGULAR
-IDS_TIME_DAYS_TWO
-IDS_TIME_DAYS_ZERO
-IDS_TIME_ELAPSED_DAYS_DEFAULT
-IDS_TIME_ELAPSED_DAYS_FEW
-IDS_TIME_ELAPSED_DAYS_MANY
-IDS_TIME_ELAPSED_DAYS_SINGULAR
-IDS_TIME_ELAPSED_DAYS_TWO
-IDS_TIME_ELAPSED_DAYS_ZERO
-IDS_TIME_ELAPSED_HOURS_DEFAULT
-IDS_TIME_ELAPSED_HOURS_FEW
-IDS_TIME_ELAPSED_HOURS_MANY
-IDS_TIME_ELAPSED_HOURS_SINGULAR
-IDS_TIME_ELAPSED_HOURS_TWO
-IDS_TIME_ELAPSED_HOURS_ZERO
-IDS_TIME_ELAPSED_MINS_DEFAULT
-IDS_TIME_ELAPSED_MINS_FEW
-IDS_TIME_ELAPSED_MINS_MANY
-IDS_TIME_ELAPSED_MINS_SINGULAR
-IDS_TIME_ELAPSED_MINS_TWO
-IDS_TIME_ELAPSED_MINS_ZERO
-IDS_TIME_ELAPSED_SECS_DEFAULT
-IDS_TIME_ELAPSED_SECS_FEW
-IDS_TIME_ELAPSED_SECS_MANY
-IDS_TIME_ELAPSED_SECS_SINGULAR
-IDS_TIME_ELAPSED_SECS_TWO
-IDS_TIME_ELAPSED_SECS_ZERO
-IDS_TIME_HOURS_1ST_DEFAULT
-IDS_TIME_HOURS_1ST_FEW
-IDS_TIME_HOURS_1ST_MANY
-IDS_TIME_HOURS_1ST_SINGULAR
-IDS_TIME_HOURS_1ST_TWO
-IDS_TIME_HOURS_1ST_ZERO
-IDS_TIME_HOURS_2ND_DEFAULT
-IDS_TIME_HOURS_2ND_FEW
-IDS_TIME_HOURS_2ND_MANY
-IDS_TIME_HOURS_2ND_SINGULAR
-IDS_TIME_HOURS_2ND_TWO
-IDS_TIME_HOURS_2ND_ZERO
-IDS_TIME_HOURS_DEFAULT
-IDS_TIME_HOURS_FEW
-IDS_TIME_HOURS_MANY
-IDS_TIME_HOURS_SINGULAR
-IDS_TIME_HOURS_TWO
-IDS_TIME_HOURS_ZERO
-IDS_TIME_LONG_MINS_1ST_DEFAULT
-IDS_TIME_LONG_MINS_1ST_FEW
-IDS_TIME_LONG_MINS_1ST_MANY
-IDS_TIME_LONG_MINS_1ST_SINGULAR
-IDS_TIME_LONG_MINS_1ST_TWO
-IDS_TIME_LONG_MINS_1ST_ZERO
-IDS_TIME_LONG_MINS_2ND_DEFAULT
-IDS_TIME_LONG_MINS_2ND_FEW
-IDS_TIME_LONG_MINS_2ND_MANY
-IDS_TIME_LONG_MINS_2ND_SINGULAR
-IDS_TIME_LONG_MINS_2ND_TWO
-IDS_TIME_LONG_MINS_2ND_ZERO
-IDS_TIME_LONG_MINS_DEFAULT
-IDS_TIME_LONG_MINS_FEW
-IDS_TIME_LONG_MINS_MANY
-IDS_TIME_LONG_MINS_SINGULAR
-IDS_TIME_LONG_MINS_TWO
-IDS_TIME_LONG_MINS_ZERO
-IDS_TIME_LONG_SECS_2ND_DEFAULT
-IDS_TIME_LONG_SECS_2ND_FEW
-IDS_TIME_LONG_SECS_2ND_MANY
-IDS_TIME_LONG_SECS_2ND_SINGULAR
-IDS_TIME_LONG_SECS_2ND_TWO
-IDS_TIME_LONG_SECS_2ND_ZERO
-IDS_TIME_LONG_SECS_DEFAULT
-IDS_TIME_LONG_SECS_FEW
-IDS_TIME_LONG_SECS_MANY
-IDS_TIME_LONG_SECS_SINGULAR
-IDS_TIME_LONG_SECS_TWO
-IDS_TIME_LONG_SECS_ZERO
-IDS_TIME_MINS_DEFAULT
-IDS_TIME_MINS_FEW
-IDS_TIME_MINS_MANY
-IDS_TIME_MINS_SINGULAR
-IDS_TIME_MINS_TWO
-IDS_TIME_MINS_ZERO
-IDS_TIME_REMAINING_DAYS_DEFAULT
-IDS_TIME_REMAINING_DAYS_FEW
-IDS_TIME_REMAINING_DAYS_MANY
-IDS_TIME_REMAINING_DAYS_SINGULAR
-IDS_TIME_REMAINING_DAYS_TWO
-IDS_TIME_REMAINING_DAYS_ZERO
-IDS_TIME_REMAINING_HOURS_DEFAULT
-IDS_TIME_REMAINING_HOURS_FEW
-IDS_TIME_REMAINING_HOURS_MANY
-IDS_TIME_REMAINING_HOURS_SINGULAR
-IDS_TIME_REMAINING_HOURS_TWO
-IDS_TIME_REMAINING_HOURS_ZERO
-IDS_TIME_REMAINING_LONG_MINS_DEFAULT
-IDS_TIME_REMAINING_LONG_MINS_FEW
-IDS_TIME_REMAINING_LONG_MINS_MANY
-IDS_TIME_REMAINING_LONG_MINS_SINGULAR
-IDS_TIME_REMAINING_LONG_MINS_TWO
-IDS_TIME_REMAINING_LONG_MINS_ZERO
-IDS_TIME_REMAINING_LONG_SECS_DEFAULT
-IDS_TIME_REMAINING_LONG_SECS_FEW
-IDS_TIME_REMAINING_LONG_SECS_MANY
-IDS_TIME_REMAINING_LONG_SECS_SINGULAR
-IDS_TIME_REMAINING_LONG_SECS_TWO
-IDS_TIME_REMAINING_LONG_SECS_ZERO
-IDS_TIME_REMAINING_MINS_DEFAULT
-IDS_TIME_REMAINING_MINS_FEW
-IDS_TIME_REMAINING_MINS_MANY
-IDS_TIME_REMAINING_MINS_SINGULAR
-IDS_TIME_REMAINING_MINS_TWO
-IDS_TIME_REMAINING_MINS_ZERO
-IDS_TIME_REMAINING_SECS_DEFAULT
-IDS_TIME_REMAINING_SECS_FEW
-IDS_TIME_REMAINING_SECS_MANY
-IDS_TIME_REMAINING_SECS_SINGULAR
-IDS_TIME_REMAINING_SECS_TWO
-IDS_TIME_REMAINING_SECS_ZERO
-IDS_TIME_SECS_DEFAULT
-IDS_TIME_SECS_FEW
-IDS_TIME_SECS_MANY
-IDS_TIME_SECS_SINGULAR
-IDS_TIME_SECS_TWO
-IDS_TIME_SECS_ZERO
+IDS_TIME_DAYS
+IDS_TIME_DAYS_1ST
+IDS_TIME_ELAPSED_DAYS
+IDS_TIME_ELAPSED_HOURS
+IDS_TIME_ELAPSED_MINS
+IDS_TIME_ELAPSED_SECS
+IDS_TIME_HOURS
+IDS_TIME_HOURS_1ST
+IDS_TIME_HOURS_2ND
+IDS_TIME_LONG_MINS
+IDS_TIME_LONG_MINS_1ST
+IDS_TIME_LONG_MINS_2ND
+IDS_TIME_LONG_SECS
+IDS_TIME_LONG_SECS_2ND
+IDS_TIME_MINS
+IDS_TIME_REMAINING_DAYS
+IDS_TIME_REMAINING_HOURS
+IDS_TIME_REMAINING_LONG_MINS
+IDS_TIME_REMAINING_LONG_SECS
+IDS_TIME_REMAINING_MINS
+IDS_TIME_REMAINING_SECS
+IDS_TIME_SECS
 IDS_TOOLTIP_STAR
 IDS_TOUCH_EVENTS_DESCRIPTION
 IDS_TOUCH_EVENTS_NAME
diff --git a/build/isolate.gypi b/build/isolate.gypi
index 5fa1e67..7b050e2 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -61,9 +61,6 @@
         # Variables should use the -V FOO=<(FOO) form so frequent values,
         # like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help' for
         # more details.
-        #
-        # This list needs to be kept in sync with the cmd line options
-        # in src/build/android/pylib/gtest/setup.py.
 
         # Path variables are used to replace file paths when loading a .isolate
         # file
@@ -74,12 +71,17 @@
         # the .isolate file but are not considered relative paths.
         '--extra-variable', 'version_full=<(version_full)',
 
+        # Note: This list must match DefaultConfigVariables()
+        # in build/android/pylib/utils/isolator.py
         '--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
         '--config-variable', 'OS=<(OS)',
         '--config-variable', 'asan=<(asan)',
+        '--config-variable', 'branding=<(branding)',
         '--config-variable', 'chromeos=<(chromeos)',
         '--config-variable', 'component=<(component)',
         '--config-variable', 'disable_nacl=<(disable_nacl)',
+        '--config-variable', 'enable_pepper_cdms=<(enable_pepper_cdms)',
+        '--config-variable', 'enable_plugins=<(enable_plugins)',
         '--config-variable', 'fastbuild=<(fastbuild)',
         '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
         # TODO(kbr): move this to chrome_tests.gypi:gles2_conform_tests_run
@@ -93,6 +95,8 @@
         '--config-variable', 'tsan=<(tsan)',
         '--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
         '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
+        '--config-variable',
+        'use_prebuilt_instrumented_libraries=<(use_prebuilt_instrumented_libraries)',
         '--config-variable', 'use_openssl=<(use_openssl)',
         '--config-variable', 'use_ozone=<(use_ozone)',
         '--config-variable', 'use_x11=<(use_x11)',
diff --git a/build/jar_file_jni_generator.gypi b/build/jar_file_jni_generator.gypi
index 6f5d2f1..3d95b28 100644
--- a/build/jar_file_jni_generator.gypi
+++ b/build/jar_file_jni_generator.gypi
@@ -64,14 +64,4 @@
   # This target exports a hard dependency because it generates header
   # files.
   'hard_dependency': 1,
-  'conditions': [
-    ['android_webview_build==1', {
-      'variables': {
-        'native_exports%': '--native_exports',
-      },
-      'dependencies': [
-        '<(DEPTH)/build/android/android_exports.gyp:android_exports',
-      ],
-    }],
-  ],
 }
diff --git a/build/java.gypi b/build/java.gypi
index 061dff2..730fa22 100644
--- a/build/java.gypi
+++ b/build/java.gypi
@@ -77,6 +77,8 @@
     'lint_result': '<(intermediate_dir)/lint_result.xml',
     'lint_config': '<(intermediate_dir)/lint_config.xml',
     'never_lint%': 0,
+    'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp',
+    'run_findbugs%': 0,
     'proguard_config%': '',
     'proguard_preprocess%': '0',
     'variables': {
@@ -217,6 +219,31 @@
         },
       ],
     }],
+    ['run_findbugs == 1', {
+      'actions': [
+        {
+          'action_name': 'findbugs_<(_target_name)',
+          'message': 'Running findbugs on <(_target_name)',
+          'inputs': [
+            '<(DEPTH)/build/android/findbugs_diff.py',
+            '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+            '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+            '>@(input_jars_paths)',
+            '<(jar_final_path)',
+            '<(compile_stamp)',
+          ],
+          'outputs': [
+            '<(findbugs_stamp)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/findbugs_diff.py',
+            '--auxclasspath-gyp', '>(input_jars_paths)',
+            '--stamp', '<(findbugs_stamp)',
+            '<(jar_final_path)',
+          ],
+        },
+      ],
+    }],
   ],
   'actions': [
     {
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index c5e7ae3..56aefdf 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -103,6 +103,8 @@
     'lint_result': '<(intermediate_dir)/lint_result.xml',
     'lint_config': '<(intermediate_dir)/lint_config.xml',
     'never_lint%': 0,
+    'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp',
+    'run_findbugs%': 0,
     'java_in_dir_suffix%': '/src',
     'instr_stamp': '<(intermediate_dir)/instr.stamp',
     'jar_stamp': '<(intermediate_dir)/jar.stamp',
@@ -558,6 +560,32 @@
         '<(DEPTH)/tools/android/android_tools.gyp:android_tools',
       ]
     }],
+    ['run_findbugs == 1', {
+      'actions': [
+        {
+          'action_name': 'findbugs_<(_target_name)',
+          'message': 'Running findbugs on <(_target_name)',
+          'inputs': [
+            '<(DEPTH)/build/android/findbugs_diff.py',
+            '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+            '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+            '>@(input_jars_paths)',
+            '<(jar_path)',
+            '<(compile_stamp)',
+          ],
+          'outputs': [
+            '<(findbugs_stamp)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/findbugs_diff.py',
+            '--auxclasspath-gyp', '>(input_jars_paths)',
+            '--stamp', '<(findbugs_stamp)',
+            '<(jar_path)',
+          ],
+        },
+      ],
+    },
+    ]
   ],
   'dependencies': [
     '<(DEPTH)/tools/android/md5sum/md5sum.gyp:md5sum',
diff --git a/build/jni_generator.gypi b/build/jni_generator.gypi
index c2c71e7..7a9e333 100644
--- a/build/jni_generator.gypi
+++ b/build/jni_generator.gypi
@@ -83,15 +83,5 @@
   # This target exports a hard dependency because it generates header
   # files.
   'hard_dependency': 1,
-  'conditions': [
-    ['android_webview_build==1', {
-      'variables': {
-        'native_exports%': '--native_exports',
-      },
-      'dependencies': [
-        '<(DEPTH)/build/android/android_exports.gyp:android_exports',
-      ],
-    }],
-  ],
 }
 
diff --git a/build/linux/install-arm-sysroot.py b/build/linux/install-arm-sysroot.py
deleted file mode 100755
index 495fc75..0000000
--- a/build/linux/install-arm-sysroot.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 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 sys
-
-msg = '''\
-ERROR: This script has merged with install-debian.wheezy.sysroot.py.
-Please use that instead (with --arch=arm).
-'''
-sys.stderr.write(msg)
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 5333798..476476e 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -1124,6 +1124,7 @@
                      'spd_set_synthesis_voice',
                      'spd_list_modules',
                      'spd_set_output_module',
+                     'spd_set_language',
           ],
           'message': 'Generating libspeechd library loader',
           'process_outputs_as_sources': 1,
@@ -1180,8 +1181,7 @@
               'dependencies': [
                 '../../third_party/boringssl/boringssl.gyp:boringssl',
               ],
-            }],
-            ['use_openssl==0', {
+            }, {
               'dependencies': [
                 '../../net/third_party/nss/ssl.gyp:libssl',
               ],
@@ -1191,6 +1191,13 @@
                   # before other includes, as we are shadowing system headers.
                   '<(DEPTH)/net/third_party/nss/ssl',
                 ],
+              },
+            }],
+            # Link in the system NSS if it is used for either the internal
+            # crypto library (use_openssl==0) or platform certificate
+            # library (use_nss_certs==1).
+            ['use_openssl==0 or use_nss_certs==1', {
+              'direct_dependent_settings': {
                 'cflags': [
                   '<!@(<(pkg-config) --cflags nss)',
                 ],
@@ -1203,15 +1210,17 @@
                   '<!@(<(pkg-config) --libs-only-l nss | sed -e "s/-lssl3//")',
                 ],
               },
-            }],
-            ['use_openssl==0 and clang==1', {
-              'direct_dependent_settings': {
-                'cflags': [
-                  # There is a broken header guard in /usr/include/nss/secmod.h:
-                  # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
-                  '-Wno-header-guard',
-                ],
-              },
+              'conditions': [
+                ['clang==1', {
+                  'direct_dependent_settings': {
+                    'cflags': [
+                      # There is a broken header guard in /usr/include/nss/secmod.h:
+                      # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
+                      '-Wno-header-guard',
+                    ],
+                  },
+                }],
+              ],
             }],
           ]
         }],
diff --git a/build/linux/unbundle/libvpx.gyp b/build/linux/unbundle/libvpx.gyp
index cdcf6fa..75671c5 100644
--- a/build/linux/unbundle/libvpx.gyp
+++ b/build/linux/unbundle/libvpx.gyp
@@ -14,16 +14,17 @@
       'variables': {
         'headers_root_path': 'source/libvpx',
         'header_filenames': [
-          'vpx/vpx_codec_impl_bottom.h',
-          'vpx/vpx_image.h',
-          'vpx/vpx_decoder.h',
           'vpx/vp8.h',
-          'vpx/vpx_codec.h',
-          'vpx/vpx_codec_impl_top.h',
           'vpx/vp8cx.h',
-          'vpx/vpx_integer.h',
           'vpx/vp8dx.h',
+          'vpx/vpx_codec.h',
+          'vpx/vpx_codec_impl_bottom.h',
+          'vpx/vpx_codec_impl_top.h',
+          'vpx/vpx_decoder.h',
           'vpx/vpx_encoder.h',
+          'vpx/vpx_frame_buffer.h',
+          'vpx/vpx_image.h',
+          'vpx/vpx_integer.h',
         ],
       },
       'includes': [
diff --git a/build/protoc_java.gypi b/build/protoc_java.gypi
index 9ed597b..6fd80d8 100644
--- a/build/protoc_java.gypi
+++ b/build/protoc_java.gypi
@@ -50,6 +50,7 @@
     # Adding the |stamp_file| to |additional_input_paths| makes the actions in
     # the include of java.gypi depend on the genproto_java action.
     'additional_input_paths': ['<(stamp_file)'],
+    'run_findbugs': 0,
   },
   'actions': [
     {
diff --git a/build/sanitizers/asan_suppressions.cc b/build/sanitizers/asan_suppressions.cc
new file mode 100644
index 0000000..df94bc8
--- /dev/null
+++ b/build/sanitizers/asan_suppressions.cc
@@ -0,0 +1,23 @@
+// 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 contains the default suppressions for AddressSanitizer.
+// It should only be used under very limited circumstances such as suppressing
+// a report caused by an interceptor call in a system-installed library.
+
+#if defined(ADDRESS_SANITIZER)
+
+// Please make sure the code below declares a single string variable
+// kASanDefaultSuppressions which contains ASan suppressions delimited by
+// newlines.
+char kASanDefaultSuppressions[] =
+// http://crbug.com/178677
+"interceptor_via_lib:libsqlite3.so\n"
+
+// PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
+
+// End of suppressions.
+;  // Please keep this semicolon.
+
+#endif  // ADDRESS_SANITIZER
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc
index 33090fb..a659a22 100644
--- a/build/sanitizers/sanitizer_options.cc
+++ b/build/sanitizers/sanitizer_options.cc
@@ -36,8 +36,6 @@
 
 #if defined(ADDRESS_SANITIZER)
 // Default options for AddressSanitizer in various configurations:
-//   strict_memcmp=1 - disable the strict memcmp() checking
-//     (http://crbug.com/178677 and http://crbug.com/178404).
 //   malloc_context_size=5 - limit the size of stack traces collected by ASan
 //     for each malloc/free by 5 frames. These stack traces tend to accumulate
 //     very fast in applications using JIT (v8 in Chrome's case), see
@@ -52,8 +50,6 @@
 //     they reside in shared memory). This option is going to be deprecated in
 //     upstream AddressSanitizer and must not be used anywhere except the
 //     official builds.
-//   replace_intrin=0 - do not intercept memcpy(), memmove() and memset() to
-//     work around http://crbug.com/162461 (ASan report in OpenCL on Mac).
 //   check_printf=1 - check the memory accesses to printf (and other formatted
 //     output routines) arguments.
 //   use_sigaltstack=1 - handle signals on an alternate signal stack. Useful
@@ -66,32 +62,28 @@
 //     so the slow unwinder may not work properly.
 //   detect_stack_use_after_return=1 - use fake stack to delay the reuse of
 //     stack allocations and detect stack-use-after-return errors.
-//   detect_container_overflow=0 - do not detect overflows in containers
-//     until crbug.com/459632 is fixed.
 #if defined(OS_LINUX)
 #if defined(GOOGLE_CHROME_BUILD)
 // Default AddressSanitizer options for the official build. These do not affect
 // tests on buildbots (which don't set GOOGLE_CHROME_BUILD) or non-official
 // Chromium builds.
 const char kAsanDefaultOptions[] =
-    "legacy_pthread_cond=1 malloc_context_size=5 strict_memcmp=0 "
+    "legacy_pthread_cond=1 malloc_context_size=5 "
     "symbolize=false check_printf=1 use_sigaltstack=1 detect_leaks=0 "
-    "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
-    "detect_container_overflow=0 ";
+    "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1";
 #else
 // Default AddressSanitizer options for buildbots and non-official builds.
 const char *kAsanDefaultOptions =
-    "strict_memcmp=0 symbolize=false check_printf=1 use_sigaltstack=1 "
+    "symbolize=false check_printf=1 use_sigaltstack=1 "
     "detect_leaks=0 strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
-    "detect_stack_use_after_return=1 detect_container_overflow=0 ";
+    "detect_stack_use_after_return=1 ";
 #endif  // GOOGLE_CHROME_BUILD
 
 #elif defined(OS_MACOSX)
 const char *kAsanDefaultOptions =
-    "strict_memcmp=0 replace_intrin=0 check_printf=1 use_sigaltstack=1 "
+    "check_printf=1 use_sigaltstack=1 "
     "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
-    "detect_stack_use_after_return=1 detect_odr_violation=0 "
-    "detect_container_overflow=0 ";
+    "detect_stack_use_after_return=1 detect_odr_violation=0 ";
 static const char kNaClDefaultOptions[] = "handle_segv=0";
 static const char kNaClFlag[] = "--type=nacl-loader";
 #endif  // OS_LINUX
@@ -112,6 +104,12 @@
 #endif
   return kAsanDefaultOptions;
 }
+
+extern "C" char kASanDefaultSuppressions[];
+
+SANITIZER_HOOK_ATTRIBUTE const char *__asan_default_suppressions() {
+  return kASanDefaultSuppressions;
+}
 #endif  // OS_LINUX || OS_MACOSX
 #endif  // ADDRESS_SANITIZER
 
diff --git a/build/sanitizers/sanitizers.gyp b/build/sanitizers/sanitizers.gyp
index 4126d22..91dab8a 100644
--- a/build/sanitizers/sanitizers.gyp
+++ b/build/sanitizers/sanitizers.gyp
@@ -41,6 +41,11 @@
             'lsan_suppressions.cc',
           ],
         }],
+        ['asan==1', {
+          'sources': [
+            'asan_suppressions.cc',
+          ],
+        }],
       ],
       'cflags/': [
         ['exclude', '-fsanitize='],
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 76d2e1e..352b41f 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -63,6 +63,7 @@
 
 // http://crbug.com/158922
 "race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"
+"race:third_party/libvpx/source/libvpx/vp9/encoder/*\n"
 
 // http://crbug.com/189177
 "race:thread_manager\n"
@@ -100,9 +101,6 @@
 // http://crbug.com/246968
 "race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"
 
-// http://crbug.com/246970
-"race:webrtc::EventPosix::StartTimer\n"
-
 // http://crbug.com/246974
 "race:content::GpuWatchdogThread::CheckArmed\n"
 
@@ -124,12 +122,12 @@
 "race:base::PowerMonitor::RemoveObserver\n"
 "race:base::PowerMonitor::IsOnBatteryPower\n"
 
+// http://crbug.com/258935
+"race:base::Thread::StopSoon\n"
+
 // http://crbug.com/268941
 "race:tracked_objects::ThreadData::tls_index_\n"
 
-// http://crbug.com/270037
-"race:gLibCleanupFunctions\n"
-
 // http://crbug.com/272095
 "race:base::g_top_manager\n"
 
@@ -241,9 +239,6 @@
 // http://crbug.com/363999
 "race:v8::internal::EnterDebugger::*EnterDebugger\n"
 
-// http://crbug.com/364006
-"race:gfx::ImageFamily::~ImageFamily\n"
-
 // https://code.google.com/p/v8/issues/detail?id=3143
 "race:v8::internal::FLAG_track_double_fields\n"
 
@@ -290,9 +285,6 @@
 // http://crbug.com/425057
 "deadlock:webrtc::ViEChannelManagerScoped::ViEChannelManagerScoped\n"
 
-// https://crbug.com/433993
-"deadlock:content::WebRtcAudioDeviceImpl\n"
-
 // http://crbug.com/417193
 // Suppressing both AudioContext.{cpp,h}.
 "race:modules/webaudio/AudioContext\n"
@@ -303,6 +295,9 @@
 // https://crbug.com/430533
 "race:TileTaskGraphRunner::Run\n"
 
+// https://crbug.com/437044
+"race:SkEventTracer\n"
+
 // https://crbug.com/448203
 "race:blink::RemoteFrame::detach\n"
 
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index 92a088a..099b892 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -9,7 +9,7 @@
 }
 
 # This is the GN version of
-# //build/android/cpufeatures.gypi:cpufeatures
+# //build/android/ndk.gyp:cpu_features
 source_set("cpu_features") {
   sources = [
     "ndk/sources/android/cpufeatures/cpu-features.c",
@@ -65,6 +65,13 @@
   jar_path = "$android_sdk_root/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar"
 }
 
+android_java_prebuilt("android_support_v7_recyclerview_java") {
+  deps = [
+    ":android_support_v7_appcompat_java",
+  ]
+  jar_path = "$android_sdk_root/extras/android/support/v7/recyclerview/libs/android-support-v7-recyclerview.jar"
+}
+
 android_resources("google_play_services_default_resources") {
   v14_verify_only = true
   resource_dirs = [ "$android_sdk_root/extras/google/google_play_services/libproject/google-play-services_lib/res" ]
diff --git a/build/secondary/third_party/leveldatabase/BUILD.gn b/build/secondary/third_party/leveldatabase/BUILD.gn
deleted file mode 100644
index 067af30..0000000
--- a/build/secondary/third_party/leveldatabase/BUILD.gn
+++ /dev/null
@@ -1,338 +0,0 @@
-# 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.
-
-# Snappy is a compression library we use.
-# TODO(brettw) It's not clear why this needs to be parameterized.
-
-import("//testing/test.gni")
-
-use_snappy = true
-
-defines = [ "LEVELDB_PLATFORM_CHROMIUM=1" ]
-
-config("leveldatabase_config") {
-  include_dirs = [
-    ".",
-    "src",
-    "src/include",
-  ]
-}
-
-static_library("leveldatabase") {
-  sources = [
-    "env_chromium.cc",
-    "env_chromium.h",
-    "env_idb.h",
-    "port/port_chromium.cc",
-    "port/port_chromium.h",
-    "src/db/builder.cc",
-    "src/db/builder.h",
-    "src/db/db_impl.cc",
-    "src/db/db_impl.h",
-    "src/db/db_iter.cc",
-    "src/db/db_iter.h",
-    "src/db/dbformat.cc",
-    "src/db/dbformat.h",
-    "src/db/filename.cc",
-    "src/db/filename.h",
-    "src/db/log_format.h",
-    "src/db/log_reader.cc",
-    "src/db/log_reader.h",
-    "src/db/log_writer.cc",
-    "src/db/log_writer.h",
-    "src/db/memtable.cc",
-    "src/db/memtable.h",
-    "src/db/repair.cc",
-    "src/db/skiplist.h",
-    "src/db/snapshot.h",
-    "src/db/table_cache.cc",
-    "src/db/table_cache.h",
-    "src/db/version_edit.cc",
-    "src/db/version_edit.h",
-    "src/db/version_set.cc",
-    "src/db/version_set.h",
-    "src/db/write_batch.cc",
-    "src/db/write_batch_internal.h",
-    "src/helpers/memenv/memenv.cc",
-    "src/helpers/memenv/memenv.h",
-    "src/include/leveldb/cache.h",
-    "src/include/leveldb/comparator.h",
-    "src/include/leveldb/db.h",
-    "src/include/leveldb/env.h",
-    "src/include/leveldb/filter_policy.h",
-    "src/include/leveldb/iterator.h",
-    "src/include/leveldb/options.h",
-    "src/include/leveldb/slice.h",
-    "src/include/leveldb/status.h",
-    "src/include/leveldb/table.h",
-    "src/include/leveldb/table_builder.h",
-    "src/include/leveldb/write_batch.h",
-    "src/port/port.h",
-    "src/port/port_example.h",
-
-    #"src/port/port_posix.cc",  # We use the chromium port instead of this.
-    #"src/port/port_posix.h",
-    "src/table/block.cc",
-    "src/table/block.h",
-    "src/table/block_builder.cc",
-    "src/table/block_builder.h",
-    "src/table/filter_block.cc",
-    "src/table/filter_block.h",
-    "src/table/format.cc",
-    "src/table/format.h",
-    "src/table/iterator.cc",
-    "src/table/iterator_wrapper.h",
-    "src/table/merger.cc",
-    "src/table/merger.h",
-    "src/table/table.cc",
-    "src/table/table_builder.cc",
-    "src/table/two_level_iterator.cc",
-    "src/table/two_level_iterator.h",
-    "src/util/arena.cc",
-    "src/util/arena.h",
-    "src/util/bloom.cc",
-    "src/util/cache.cc",
-    "src/util/coding.cc",
-    "src/util/coding.h",
-    "src/util/comparator.cc",
-    "src/util/crc32c.cc",
-    "src/util/crc32c.h",
-    "src/util/env.cc",
-    "src/util/filter_policy.cc",
-    "src/util/hash.cc",
-    "src/util/hash.h",
-    "src/util/logging.cc",
-    "src/util/logging.h",
-    "src/util/mutexlock.h",
-    "src/util/options.cc",
-    "src/util/random.h",
-    "src/util/status.cc",
-  ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  public_configs = [ ":leveldatabase_config" ]
-
-  deps = [
-    "//base",
-    "//base/third_party/dynamic_annotations",
-    "//third_party/re2",
-  ]
-
-  if (use_snappy) {
-    defines += [ "USE_SNAPPY=1" ]
-    deps += [ "//third_party/snappy" ]
-  }
-}
-
-if (!is_android) {
-  test("env_chromium_unittests") {
-    sources = [
-      "env_chromium_unittest.cc",
-    ]
-    deps = [
-      ":leveldatabase",
-      "//base/test:test_support",
-      "//testing/gtest",
-    ]
-  }
-
-  static_library("leveldb_testutil") {
-    sources = [
-      "src/util/histogram.cc",
-      "src/util/histogram.h",
-      "src/util/testharness.cc",
-      "src/util/testharness.h",
-      "src/util/testutil.cc",
-      "src/util/testutil.h",
-    ]
-
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-
-    public_deps = [
-      ":leveldatabase",
-    ]
-    deps = [
-      "//base",
-    ]
-  }
-
-  test("leveldb_arena_test") {
-    sources = [
-      "src/util/arena_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_bloom_test") {
-    sources = [
-      "src/util/bloom_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_cache_test") {
-    sources = [
-      "src/util/cache_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_corruption_test") {
-    sources = [
-      "src/db/corruption_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_crc32c_test") {
-    sources = [
-      "src/util/crc32c_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_db_bench") {
-    sources = [
-      "src/db/db_bench.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_db_test") {
-    sources = [
-      "src/db/db_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_dbformat_test") {
-    sources = [
-      "src/db/dbformat_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_env_test") {
-    sources = [
-      "src/util/env_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_filename_test") {
-    sources = [
-      "src/db/filename_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_filter_block_test") {
-    sources = [
-      "src/table/filter_block_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_log_test") {
-    sources = [
-      "src/db/log_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_skiplist_test") {
-    sources = [
-      "src/db/skiplist_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_table_test") {
-    sources = [
-      "src/table/table_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_version_edit_test") {
-    sources = [
-      "src/db/version_edit_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_write_batch_test") {
-    sources = [
-      "src/db/write_batch_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-}
diff --git a/build/secondary/third_party/sfntly/BUILD.gn b/build/secondary/third_party/sfntly/BUILD.gn
deleted file mode 100644
index 111f1cd..0000000
--- a/build/secondary/third_party/sfntly/BUILD.gn
+++ /dev/null
@@ -1,131 +0,0 @@
-# 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.
-
-static_library("sfntly") {
-  sources = [
-    "cpp/src/sample/chromium/font_subsetter.cc",
-    "cpp/src/sample/chromium/font_subsetter.h",
-    "cpp/src/sample/chromium/subsetter_impl.cc",
-    "cpp/src/sample/chromium/subsetter_impl.h",
-    "cpp/src/sfntly/data/byte_array.cc",
-    "cpp/src/sfntly/data/byte_array.h",
-    "cpp/src/sfntly/data/font_data.cc",
-    "cpp/src/sfntly/data/font_data.h",
-    "cpp/src/sfntly/data/font_input_stream.cc",
-    "cpp/src/sfntly/data/font_input_stream.h",
-    "cpp/src/sfntly/data/font_output_stream.cc",
-    "cpp/src/sfntly/data/font_output_stream.h",
-    "cpp/src/sfntly/data/growable_memory_byte_array.cc",
-    "cpp/src/sfntly/data/growable_memory_byte_array.h",
-    "cpp/src/sfntly/data/memory_byte_array.cc",
-    "cpp/src/sfntly/data/memory_byte_array.h",
-    "cpp/src/sfntly/data/readable_font_data.cc",
-    "cpp/src/sfntly/data/readable_font_data.h",
-    "cpp/src/sfntly/data/writable_font_data.cc",
-    "cpp/src/sfntly/data/writable_font_data.h",
-    "cpp/src/sfntly/font.cc",
-    "cpp/src/sfntly/font.h",
-    "cpp/src/sfntly/font_factory.cc",
-    "cpp/src/sfntly/font_factory.h",
-    "cpp/src/sfntly/math/fixed1616.h",
-    "cpp/src/sfntly/math/font_math.h",
-    "cpp/src/sfntly/port/atomic.h",
-    "cpp/src/sfntly/port/config.h",
-    "cpp/src/sfntly/port/endian.h",
-    "cpp/src/sfntly/port/exception_type.h",
-    "cpp/src/sfntly/port/file_input_stream.cc",
-    "cpp/src/sfntly/port/file_input_stream.h",
-    "cpp/src/sfntly/port/input_stream.h",
-    "cpp/src/sfntly/port/lock.cc",
-    "cpp/src/sfntly/port/lock.h",
-    "cpp/src/sfntly/port/memory_input_stream.cc",
-    "cpp/src/sfntly/port/memory_input_stream.h",
-    "cpp/src/sfntly/port/memory_output_stream.cc",
-    "cpp/src/sfntly/port/memory_output_stream.h",
-    "cpp/src/sfntly/port/output_stream.h",
-    "cpp/src/sfntly/port/refcount.h",
-    "cpp/src/sfntly/port/type.h",
-    "cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/big_glyph_metrics.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_size_table.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_size_table.h",
-    "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/ebdt_table.cc",
-    "cpp/src/sfntly/table/bitmap/ebdt_table.h",
-    "cpp/src/sfntly/table/bitmap/eblc_table.cc",
-    "cpp/src/sfntly/table/bitmap/eblc_table.h",
-    "cpp/src/sfntly/table/bitmap/ebsc_table.cc",
-    "cpp/src/sfntly/table/bitmap/ebsc_table.h",
-    "cpp/src/sfntly/table/bitmap/glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/glyph_metrics.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format1.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format2.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format3.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format4.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format5.h",
-    "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/small_glyph_metrics.h",
-    "cpp/src/sfntly/table/byte_array_table_builder.cc",
-    "cpp/src/sfntly/table/byte_array_table_builder.h",
-    "cpp/src/sfntly/table/core/cmap_table.cc",
-    "cpp/src/sfntly/table/core/cmap_table.h",
-    "cpp/src/sfntly/table/core/font_header_table.cc",
-    "cpp/src/sfntly/table/core/font_header_table.h",
-    "cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_device_metrics_table.h",
-    "cpp/src/sfntly/table/core/horizontal_header_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_header_table.h",
-    "cpp/src/sfntly/table/core/horizontal_metrics_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_metrics_table.h",
-    "cpp/src/sfntly/table/core/maximum_profile_table.cc",
-    "cpp/src/sfntly/table/core/maximum_profile_table.h",
-    "cpp/src/sfntly/table/core/name_table.cc",
-    "cpp/src/sfntly/table/core/name_table.h",
-    "cpp/src/sfntly/table/core/os2_table.cc",
-    "cpp/src/sfntly/table/core/os2_table.h",
-    "cpp/src/sfntly/table/font_data_table.cc",
-    "cpp/src/sfntly/table/font_data_table.h",
-    "cpp/src/sfntly/table/generic_table_builder.cc",
-    "cpp/src/sfntly/table/generic_table_builder.h",
-    "cpp/src/sfntly/table/header.cc",
-    "cpp/src/sfntly/table/header.h",
-    "cpp/src/sfntly/table/subtable.cc",
-    "cpp/src/sfntly/table/subtable.h",
-    "cpp/src/sfntly/table/subtable_container_table.h",
-    "cpp/src/sfntly/table/table.cc",
-    "cpp/src/sfntly/table/table.h",
-    "cpp/src/sfntly/table/table_based_table_builder.cc",
-    "cpp/src/sfntly/table/table_based_table_builder.h",
-    "cpp/src/sfntly/table/truetype/glyph_table.cc",
-    "cpp/src/sfntly/table/truetype/glyph_table.h",
-    "cpp/src/sfntly/table/truetype/loca_table.cc",
-    "cpp/src/sfntly/table/truetype/loca_table.h",
-    "cpp/src/sfntly/tag.cc",
-    "cpp/src/sfntly/tag.h",
-  ]
-
-  defines = [ "SFNTLY_NO_EXCEPTION" ]
-  include_dirs = [ "cpp/src" ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  deps = [
-    "//third_party/icu:icuuc",
-  ]
-}
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni
index 5d3b1e4..09a04c1 100644
--- a/build/secondary/tools/grit/grit_rule.gni
+++ b/build/secondary/tools/grit/grit_rule.gni
@@ -146,7 +146,7 @@
 if (use_nss_certs) {
   grit_defines += [
     "-D",
-    "use_nss",
+    "use_nss_certs",
   ]
 }
 
@@ -204,6 +204,12 @@
     "enable_extensions",
   ]
 }
+if (enable_media_router) {
+  grit_defines += [
+    "-D",
+    "enable_media_router",
+  ]
+}
 if (enable_plugins) {
   grit_defines += [
     "-D",
@@ -299,11 +305,14 @@
   assert(defined(invoker.source),
          "\"source\" must be defined for the grit template $target_name")
 
+  grit_inputs = [ invoker.source ]
+
   if (defined(invoker.resource_ids)) {
     resource_ids = invoker.resource_ids
   } else {
     resource_ids = grit_resource_id_file
   }
+  grit_inputs += [ resource_ids ]  # Script depends on ID file.
 
   if (defined(invoker.output_dir)) {
     output_dir = invoker.output_dir
@@ -331,8 +340,6 @@
     grit_flags = []  # These are optional so default to empty list.
   }
 
-  grit_inputs = [ invoker.source ]
-
   assert_files_flags = []
 
   # We want to make sure the declared outputs actually match what Grit is
@@ -371,20 +378,8 @@
     script = "//tools/grit/grit.py"
     inputs = grit_inputs
 
-    # TODO(knn): Remove this once grit has rolled to recognize the flag.
-    depend_on_stamp =
-        defined(invoker.depend_on_stamp) && invoker.depend_on_stamp
-    if (depend_on_stamp) {
-      # Need this for migrating existing targets without clobbering.
-      depfile = "$output_dir/${grit_output_name}_stamp.d"
-      outputs = [
-        "${depfile}.stamp",
-      ]
-    } else {
-      depfile = "$output_dir/${grit_output_name}.d"
-      outputs = []
-    }
-    outputs += grit_outputs
+    depfile = "$output_dir/${grit_output_name}_stamp.d"
+    outputs = [ "${depfile}.stamp" ] + grit_outputs
 
     args = [
       "-i",
@@ -398,18 +393,15 @@
       ]
     }
     args += [
-      "-o",
-      rebased_output_dir,
-      "--depdir",
-      ".",
-      "--depfile",
-      rebase_path(depfile, root_build_dir),
-      "--write-only-new=1",
-    ]
-    if (depend_on_stamp) {
-      args += [ "--depend-on-stamp" ]
-    }
-    args += grit_defines
+              "-o",
+              rebased_output_dir,
+              "--depdir",
+              ".",
+              "--depfile",
+              rebase_path(depfile, root_build_dir),
+              "--write-only-new=1",
+              "--depend-on-stamp",
+            ] + grit_defines
 
     # Add extra defines with -D flags.
     if (defined(invoker.defines)) {
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 5f49f68..0192faa 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -211,12 +211,6 @@
       target_os = target_os
       target_cpu = target_cpu
 
-      # TODO(dpranke): These values are here for backwards compatibility and
-      # should be deleted when all of the builders and configs have been
-      # updated.
-      cpu_arch = current_cpu
-      os = current_os
-
       if (defined(invoker.is_clang)) {
         is_clang = invoker.is_clang
       }
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 18ee8b8..a4b8651 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -195,9 +195,6 @@
 
     toolchain_args() {
       current_os = invoker.toolchain_os
-
-      # TODO(dpranke): os is here for backwards compatibility.
-      os = current_os
     }
   }
 }
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index e9461a4..05406c3 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -101,7 +101,7 @@
       outputs = [
         "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
       ]
-      rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
+      rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
     }
 
     tool("rc") {
@@ -201,9 +201,6 @@
     # passed to the build. They are ignored when this is the default toolchain.
     toolchain_args() {
       current_cpu = invoker.current_cpu
-
-      # TODO(dpranke): cpu_arch is here for backwards compatibility.
-      cpu_arch = current_cpu
     }
   }
 }
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
index d1c33e8..1a7f519 100755
--- a/build/util/lastchange.py
+++ b/build/util/lastchange.py
@@ -115,6 +115,7 @@
       for line in reversed(output.splitlines()):
         if line.startswith('Cr-Commit-Position:'):
           pos = line.rsplit()[-1].strip()
+          break
   if not pos:
     return VersionInfo('git', hsh)
   return VersionInfo('git', '%s-%s' % (hsh, pos))