diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index bf96dea..b9dca9d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -691,17 +691,11 @@
     private MediaMetadataCompat createMetadata() {
         MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder();
 
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE,
-                    mMediaNotificationInfo.metadata.getTitle());
-            metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE,
-                    mMediaNotificationInfo.origin);
-        } else {
-            metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_TITLE,
-                    mMediaNotificationInfo.metadata.getTitle());
-            metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST,
-                    mMediaNotificationInfo.origin);
-        }
+        metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_TITLE,
+                mMediaNotificationInfo.metadata.getTitle());
+        metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST,
+                mMediaNotificationInfo.origin);
+
         if (!TextUtils.isEmpty(mMediaNotificationInfo.metadata.getArtist())) {
             metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST,
                     mMediaNotificationInfo.metadata.getArtist());
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 2ed9ea5..d10d5ca 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2744,6 +2744,23 @@
     <message name="IDS_SETTINGS_STORAGE_DELETE_ALL_BUTTON_TITLE" desc="In storage manager confirmation dialog, label for the button to delete offline files.">
       Delete files
     </message>
+
+    <!-- Power -->
+    <message name="IDS_SETTINGS_POWER_SOURCE_LABEL" desc="The label for the power source dropdown in the Power overlay.">
+      Power source
+    </message>
+    <message name="IDS_SETTINGS_POWER_SOURCE_BATTERY" desc="The text referring to the battery as the power source.">
+      Battery
+    </message>
+    <message name="IDS_SETTINGS_POWER_SOURCE_AC_ADAPTER" desc="The text referring to a dedicated charger like an AC adapter as the power source.">
+      AC adapter
+    </message>
+    <message name="IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER" desc="The text referring to a low-power charger like a USB charger as the power source.">
+      Low-power charger
+    </message>
+    <message name="IDS_SETTINGS_POWER_SOURCE_CALCULATING" desc="The description in the 'Power' overlay when the power status is being determined.">
+      Checking...
+    </message>
   </if>
 
   <!-- System Page -->
diff --git a/chrome/browser/resources/settings/device_page/device_page.html b/chrome/browser/resources/settings/device_page/device_page.html
index feb35dc..e12ef3b6 100644
--- a/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chrome/browser/resources/settings/device_page/device_page.html
@@ -1,4 +1,5 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
@@ -19,7 +20,7 @@
 
 <dom-module id="settings-device-page">
   <template>
-    <style include="settings-shared"></style>
+    <style include="settings-shared md-select"></style>
     <settings-animated-pages id="pages" section="device">
       <neon-animatable id="main" route-path="default">
         <div id="pointersRow" class="settings-box first"
@@ -57,6 +58,35 @@
           <div class="middle">$i18n{storageTitle}</div>
           <button class="subpage-arrow" is="paper-icon-button-light"></button>
         </div>
+        <template is="dom-if" if="[[enablePowerSettings_]]">
+          <div id="powerRow" class="settings-box two-line">
+            <iron-icon icon="[[batteryIcon_]]"></iron-icon>
+            <div class="middle">
+              <div>[[powerLabel_]]</div>
+              <div class="secondary">[[batteryStatus_.statusText]]</div>
+            </div>
+            <div class="md-select-wrapper"
+                hidden$="[[!showPowerDropdown_]]">
+              <select id="powerSource" class="md-select"
+                  on-change="onPowerSourceChange_">
+                <option value=""
+                    selected$="[[isEqual_('', selectedPowerSourceId_)]]">
+                  $i18n{powerSourceBattery}
+                </option>
+                <template is="dom-repeat" items="[[powerSources_]]">
+                  <option value="[[item.id]]"
+                      selected$="[[isEqual_(item.id, selectedPowerSourceId_)]]">
+                    [[item.description]]
+                  </option>
+                </template>
+              </select>
+              <span class="md-select-underline"></span>
+            </div>
+            <div hidden$="[[showPowerDropdown_]]">
+              [[powerSourceName_]]
+            </div>
+          </div>
+        </template>
       </neon-animatable>
       <template is="dom-if" route-path="/pointer-overlay">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/device_page/device_page.js b/chrome/browser/resources/settings/device_page/device_page.js
index 18f39843..5ec0105a 100644
--- a/chrome/browser/resources/settings/device_page/device_page.js
+++ b/chrome/browser/resources/settings/device_page/device_page.js
@@ -39,6 +39,62 @@
       },
       readOnly: true,
     },
+
+    /**
+     * Whether power status and settings should be fetched and displayed.
+     * @private
+     */
+    enablePowerSettings_: {
+      type: Boolean,
+      value: function() {
+        return loadTimeData.getBoolean('enablePowerSettings');
+      },
+      readOnly: true,
+    },
+
+    /** @private {string} ID of the selected power source, or ''. */
+    selectedPowerSourceId_: String,
+
+    /** @private {!settings.BatteryStatus|undefined} */
+    batteryStatus_: Object,
+
+    /** @private {boolean} Whether a low-power (USB) charger is being used. */
+    lowPowerCharger_: Boolean,
+
+    /**
+     * List of available dual-role power sources, if enablePowerSettings_ is on.
+     * @private {!Array<!settings.PowerSource>|undefined}
+     */
+    powerSources_: Array,
+
+    /** @private */
+    batteryIcon_: {
+      type: String,
+      computed: 'computeBatteryIcon_(batteryStatus_, lowPowerCharger_)',
+      value: 'settings:battery-unknown',
+    },
+
+    /** @private */
+    powerLabel_: {
+      type: String,
+      computed: 'computePowerLabel_(powerSources_, batteryStatus_.calculating)',
+    },
+
+    /** @private */
+    showPowerDropdown_: {
+      type: Boolean,
+      computed: 'computeShowPowerDropdown_(powerSources_)',
+      value: false,
+    },
+
+    /**
+     * The name of the dedicated charging device being used, if present.
+     * @private {string}
+     */
+    powerSourceName_: {
+      type: String,
+      computed: 'computePowerSourceName_(powerSources_, lowPowerCharger_)',
+    },
   },
 
   observers: [
@@ -46,16 +102,20 @@
   ],
 
   /** @override */
-  ready: function() {
-    settings.DevicePageBrowserProxyImpl.getInstance().initializePointers();
-  },
-
-  /** @override */
   attached: function() {
     this.addWebUIListener(
         'has-mouse-changed', this.set.bind(this, 'hasMouse_'));
     this.addWebUIListener(
         'has-touchpad-changed', this.set.bind(this, 'hasTouchpad_'));
+    settings.DevicePageBrowserProxyImpl.getInstance().initializePointers();
+
+    if (this.enablePowerSettings_) {
+      this.addWebUIListener(
+          'battery-status-changed', this.set.bind(this, 'batteryStatus_'));
+      this.addWebUIListener(
+          'power-sources-changed', this.powerSourcesChanged_.bind(this));
+      settings.DevicePageBrowserProxyImpl.getInstance().updatePowerStatus();
+    }
   },
 
   /**
@@ -85,6 +145,89 @@
   },
 
   /**
+   * @param {*} lhs
+   * @param {*} rhs
+   * @return {boolean}
+   */
+  isEqual_: function(lhs, rhs) {
+    return lhs === rhs;
+  },
+
+  /**
+   * @param {!settings.BatteryStatus} batteryStatus
+   * @param {boolean} lowPowerCharger
+   * @return {string}
+   */
+  computeBatteryIcon_: function(batteryStatus, lowPowerCharger) {
+    var iconPrefix = 'settings:battery-';
+
+    if (batteryStatus.calculating)
+      return iconPrefix + 'unknown';
+
+    if (lowPowerCharger)
+      return iconPrefix + 'unreliable';
+
+    if (!batteryStatus.charging && batteryStatus.percent < 5)
+      return iconPrefix + 'alert';
+
+    // Compute the rest of the icon: iconPrefix + '[charging-]<percent>'.
+    if (batteryStatus.charging)
+      iconPrefix += 'charging-';
+
+    // Show the highest level icon that doesn't go over the actual percentage.
+    if (batteryStatus.percent < 30)
+      return iconPrefix + '20';
+    if (batteryStatus.percent < 50)
+      return iconPrefix + '30';
+    if (batteryStatus.percent < 60)
+      return iconPrefix + '50';
+    if (batteryStatus.percent < 80)
+      return iconPrefix + '60';
+    if (batteryStatus.percent < 90)
+      return iconPrefix + '80';
+    if (batteryStatus.percent < 100)
+      return iconPrefix + '90';
+    return iconPrefix + 'full';
+  },
+
+  /**
+   * @param {!Array<!settings.PowerSource>|undefined} powerSources
+   * @param {boolean} calculating
+   * @return {string} The primary label for the power row.
+   * @private
+   */
+  computePowerLabel_: function(powerSources, calculating) {
+    return this.i18n(calculating ? 'calculatingPower' :
+        powerSources.length ? 'powerSourceLabel' : 'powerSourceBattery');
+  },
+
+  /**
+   * @param {!Array<!settings.PowerSource>} powerSources
+   * @return {boolean} True if at least one power source is attached and all of
+   *     them are dual-role (no dedicated chargers).
+   * @private
+   */
+  computeShowPowerDropdown_: function(powerSources) {
+    return powerSources.length > 0 && powerSources.every(function(source) {
+      return source.type == settings.PowerDeviceType.DUAL_ROLE_USB;
+    });
+  },
+
+  /**
+   * @param {!Array<!settings.PowerSource>} powerSources
+   * @param {boolean} lowPowerCharger
+   * @return {string} Description of the power source.
+   * @private
+   */
+  computePowerSourceName_(powerSources, lowPowerCharger) {
+    if (lowPowerCharger)
+      return this.i18n('powerSourceLowPowerCharger');
+    if (powerSources.length)
+      return this.i18n('powerSourceAcAdapter');
+    return '';
+  },
+
+  /**
    * Handler for tapping the mouse and touchpad settings menu item.
    * @private
    */
@@ -124,6 +267,11 @@
     settings.navigateTo(settings.Route.STORAGE);
   },
 
+  onPowerSourceChange_: function() {
+    settings.DevicePageBrowserProxyImpl.getInstance().setPowerSource(
+        this.$$('#powerSource').value);
+  },
+
   /** @protected */
   currentRouteChanged: function() {
     this.checkPointerSubpage_();
@@ -140,6 +288,19 @@
   },
 
   /**
+   * @param {!Array<settings.PowerSource>} sources External power sources.
+   * @param {string} selectedId The ID of the currently used power source.
+   * @param {boolean} lowPowerCharger Whether the currently used power source
+   *     is a low-powered USB charger.
+   * @private
+   */
+  powerSourcesChanged_: function(sources, selectedId, lowPowerCharger) {
+    this.powerSources_ = sources;
+    this.selectedPowerSourceId_ = selectedId;
+    this.lowPowerCharger_ = lowPowerCharger;
+  },
+
+  /**
    * Leaves the pointer subpage if all pointing devices are detached.
    * @private
    */
diff --git a/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js b/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
index 4a3f62c2a..0f7ed4db 100644
--- a/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
+++ b/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
@@ -3,6 +3,36 @@
 // found in the LICENSE file.
 
 /** @fileoverview A helper object used for testing the Device page. */
+cr.exportPath('settings');
+
+/**
+ * Mirrors DeviceType from ash/common/system/chromeos/power/power_status.h.
+ * @enum {number}
+ */
+settings.PowerDeviceType = {
+  DEDICATED_CHARGER: 0,
+  DUAL_ROLE_USB: 1,
+};
+
+/**
+ * @typedef {{
+ *   id: string,
+ *   type: settings.PowerDeviceType,
+ *   description: string
+ * }}
+ */
+settings.PowerSource;
+
+/**
+ * @typedef {{
+ *   charging: boolean,
+ *   calculating: boolean,
+ *   percent: number,
+ *   statusText: string,
+ * }}
+ */
+settings.BatteryStatus;
+
 cr.define('settings', function() {
   /** @interface */
   function DevicePageBrowserProxy() {}
@@ -23,6 +53,16 @@
 
     /** Shows the Ash keyboard shortcuts overlay. */
     showKeyboardShortcutsOverlay: function() {},
+
+    /** Requests a power status update. */
+    updatePowerStatus: function() {},
+
+    /**
+     * Sets the ID of the power source to use.
+     * @param {string} powerSourceId ID of the power source. '' denotes the
+     *     battery (no external power source).
+     */
+    setPowerSource: function(powerSourceId) {},
   };
 
   /**
@@ -55,6 +95,16 @@
     showKeyboardShortcutsOverlay: function() {
       chrome.send('showKeyboardShortcutsOverlay');
     },
+
+    /** @override */
+    updatePowerStatus: function() {
+      chrome.send('updatePowerStatus');
+    },
+
+    /** @override */
+    setPowerSource: function(powerSourceId) {
+      chrome.send('setPowerSource', [powerSourceId]);
+    },
   };
 
   return {
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 5041e948..e88824d9 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -18,6 +18,12 @@
         <path fill="none" d="M1 1h22v22H1z"></path>
       </g>
 
+      <!-- Battery shell from Polymer plus unreliable badge from Ash. -->
+      <g id="battery-unreliable">
+        <path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"></path>
+        <path fill="#fff" d="M10.755 11.99c-.99.01-1.25.5-1.25.5v-.985S9.775 11 10.76 11c.985 0 1.5.975 2.525.975S14.5 11.5 14.5 11.5v.99s-.19.525-1.22.525-1.535-1.04-2.53-1.025z"></path>
+      </g>
+
       <!--
       These icons are copied from Polymer's iron-icons and kept in sorted order.
       See http://goo.gl/Y1OdAq for instructions on adding additional icons.
@@ -31,7 +37,22 @@
       <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g>
       <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path></g>
 <if expr="chromeos">
+      <g id="battery-20"><path d="M7 17v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17H7z"></path><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h10V5.33z"></path></g>
+      <g id="battery-30"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V15h10V5.33z"></path><path d="M7 15v5.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V15H7z"></path></g>
+      <g id="battery-50"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V13h10V5.33z"></path><path d="M7 13v7.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13H7z"></path></g>
+      <g id="battery-60"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h10V5.33z"></path><path d="M7 11v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11H7z"></path></g>
+      <g id="battery-80"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h10V5.33z"></path><path d="M7 9v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9H7z"></path></g>
+      <g id="battery-90"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h10V5.33z"></path><path d="M7 8v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8H7z"></path></g>
+      <g id="battery-alert"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM13 18h-2v-2h2v2zm0-4h-2V9h2v5z"></path></g>
+      <g id="battery-charging-20"><path d="M11 20v-3H7v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17h-4.4L11 20z"></path><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h4v-2.5H9L13 7v5.5h2L12.6 17H17V5.33C17 4.6 16.4 4 15.67 4z"></path></g>
+      <g id="battery-charging-30"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v9.17h2L13 7v5.5h2l-1.07 2H17V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M11 20v-5.5H7v6.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V14.5h-3.07L11 20z"></path></g>
+      <g id="battery-charging-50"><path d="M14.47 13.5L11 20v-5.5H9l.53-1H7v7.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13.5h-2.53z"></path><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v8.17h2.53L13 7v5.5h2l-.53 1H17V5.33C17 4.6 16.4 4 15.67 4z"></path></g>
+      <g id="battery-charging-60"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h3.87L13 7v4h4V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M13 12.5h2L11 20v-5.5H9l1.87-3.5H7v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11h-4v1.5z"></path></g>
+      <g id="battery-charging-80"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h4.93L13 7v2h4V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M13 12.5h2L11 20v-5.5H9L11.93 9H7v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9h-4v3.5z"></path></g>
+      <g id="battery-charging-90"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h5.47L13 7v1h4V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M13 12.5h2L11 20v-5.5H9L12.47 8H7v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8h-4v4.5z"></path></g>
       <g id="battery-charging-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM11 20v-5.5H9L13 7v5.5h2L11 20z"></path></g>
+      <g id="battery-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"></path></g>
+      <g id="battery-unknown"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zm-2.72 13.95h-1.9v-1.9h1.9v1.9zm1.35-5.26s-.38.42-.67.71c-.48.48-.83 1.15-.83 1.6h-1.6c0-.83.46-1.52.93-2l.93-.94c.27-.27.44-.65.44-1.06 0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5H9c0-1.66 1.34-3 3-3s3 1.34 3 3c0 .66-.27 1.26-.7 1.69z"></path></g>
       <g id="bluetooth"><path d="M17.71 7.71L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88z"></path></g>
       <g id="bluetooth-connected"><path d="M7 12l-2-2-2 2 2 2 2-2zm10.71-4.29L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88zM19 10l-2 2 2 2 2-2-2-2z"></path></g>
       <g id="bluetooth-disabled"><path d="M13 5.83l1.88 1.88-1.6 1.6 1.41 1.41 3.02-3.02L12 2h-1v5.03l2 2v-3.2zM5.41 4L4 5.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l4.29-4.29 2.3 2.29L20 18.59 5.41 4zM13 18.17v-3.76l1.88 1.88L13 18.17z"></path></g>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index db7302c..7488e79 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1094,6 +1094,8 @@
       "webui/settings/chromeos/device_keyboard_handler.h",
       "webui/settings/chromeos/device_pointer_handler.cc",
       "webui/settings/chromeos/device_pointer_handler.h",
+      "webui/settings/chromeos/device_power_handler.cc",
+      "webui/settings/chromeos/device_power_handler.h",
       "webui/settings/chromeos/device_storage_handler.cc",
       "webui/settings/chromeos/device_storage_handler.h",
       "webui/settings/chromeos/easy_unlock_settings_handler.cc",
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
new file mode 100644
index 0000000..4d4340d
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -0,0 +1,140 @@
+// Copyright 2017 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.
+
+#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
+
+#include <memory>
+#include <utility>
+
+#include "ash/resources/grit/ash_resources.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_ui.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/time_format.h"
+#include "ui/base/webui/web_ui_util.h"
+
+namespace chromeos {
+namespace settings {
+namespace {
+
+base::string16 GetBatteryTimeText(base::TimeDelta time_left) {
+  int hour = 0;
+  int min = 0;
+  ash::PowerStatus::SplitTimeIntoHoursAndMinutes(time_left, &hour, &min);
+
+  base::string16 time_text;
+  if (hour == 0 || min == 0) {
+    // Display only one unit ("2 hours" or "10 minutes").
+    return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
+                                  ui::TimeFormat::LENGTH_LONG, time_left);
+  }
+
+  return ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION,
+                                  ui::TimeFormat::LENGTH_LONG,
+                                  -1,  // force hour and minute output
+                                  time_left);
+}
+
+}  // namespace
+
+PowerHandler::PowerHandler() {
+  power_status_ = ash::PowerStatus::Get();
+}
+
+PowerHandler::~PowerHandler() {}
+
+void PowerHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "updatePowerStatus", base::Bind(&PowerHandler::HandleUpdatePowerStatus,
+                                      base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setPowerSource",
+      base::Bind(&PowerHandler::HandleSetPowerSource, base::Unretained(this)));
+}
+
+void PowerHandler::OnJavascriptAllowed() {
+  power_status_->AddObserver(this);
+}
+
+void PowerHandler::OnJavascriptDisallowed() {
+  power_status_->RemoveObserver(this);
+}
+
+void PowerHandler::OnPowerStatusChanged() {
+  SendBatteryStatus();
+  SendPowerSources();
+}
+
+void PowerHandler::HandleUpdatePowerStatus(const base::ListValue* args) {
+  AllowJavascript();
+  power_status_->RequestStatusUpdate();
+}
+
+void PowerHandler::HandleSetPowerSource(const base::ListValue* args) {
+  AllowJavascript();
+
+  std::string id;
+  CHECK(args->GetString(0, &id));
+  power_status_->SetPowerSource(id);
+}
+
+void PowerHandler::SendBatteryStatus() {
+  bool charging = power_status_->IsBatteryCharging();
+  bool calculating = power_status_->IsBatteryTimeBeingCalculated();
+  int percent = power_status_->GetRoundedBatteryPercent();
+  base::TimeDelta time_left;
+  bool show_time = false;
+
+  if (!calculating) {
+    time_left = charging ? power_status_->GetBatteryTimeToFull()
+                         : power_status_->GetBatteryTimeToEmpty();
+    show_time = ash::PowerStatus::ShouldDisplayBatteryTime(time_left);
+  }
+
+  base::string16 status_text;
+  if (show_time) {
+    status_text = l10n_util::GetStringFUTF16(
+        charging ? IDS_OPTIONS_BATTERY_STATUS_CHARGING
+                 : IDS_OPTIONS_BATTERY_STATUS,
+        base::IntToString16(percent), GetBatteryTimeText(time_left));
+  } else {
+    status_text = l10n_util::GetStringFUTF16(IDS_OPTIONS_BATTERY_STATUS_SHORT,
+                                             base::IntToString16(percent));
+  }
+
+  base::DictionaryValue battery_dict;
+  battery_dict.SetBoolean("charging", charging);
+  battery_dict.SetBoolean("calculating", calculating);
+  battery_dict.SetInteger("percent", percent);
+  battery_dict.SetString("statusText", status_text);
+
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::StringValue("battery-status-changed"),
+                         battery_dict);
+}
+
+void PowerHandler::SendPowerSources() {
+  base::ListValue sources_list;
+  for (const auto& source : power_status_->GetPowerSources()) {
+    std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+    dict->SetString("id", source.id);
+    dict->SetInteger("type", source.type);
+    dict->SetString("description",
+                    l10n_util::GetStringUTF16(source.description_id));
+    sources_list.Append(std::move(dict));
+  }
+
+  CallJavascriptFunction(
+      "cr.webUIListenerCallback", base::StringValue("power-sources-changed"),
+      sources_list, base::StringValue(power_status_->GetCurrentPowerSourceID()),
+      base::FundamentalValue(power_status_->IsUsbChargerConnected()));
+}
+
+}  // namespace settings
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
new file mode 100644
index 0000000..09e6b07
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -0,0 +1,56 @@
+// Copyright 2017 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_
+
+#include "ash/common/system/chromeos/power/power_status.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace chromeos {
+namespace settings {
+
+// Chrome OS battery status and power settings handler.
+class PowerHandler : public ::settings::SettingsPageUIHandler,
+                     public ash::PowerStatus::Observer {
+ public:
+  PowerHandler();
+  ~PowerHandler() override;
+
+  // SettingsPageUIHandler implementation.
+  void RegisterMessages() override;
+  void OnJavascriptAllowed() override;
+  void OnJavascriptDisallowed() override;
+
+  // ash::PowerStatus::Observer implementation.
+  void OnPowerStatusChanged() override;
+
+ private:
+  // Handler to request updating the power status.
+  void HandleUpdatePowerStatus(const base::ListValue* args);
+
+  // Handler to change the power source.
+  void HandleSetPowerSource(const base::ListValue* args);
+
+  // Updates the UI with the current battery status.
+  void SendBatteryStatus();
+
+  // Updates the UI with a list of available dual-role power sources.
+  void SendPowerSources();
+
+  ash::PowerStatus* power_status_;
+
+  DISALLOW_COPY_AND_ASSIGN(PowerHandler);
+};
+
+}  // namespace settings
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 074aba8..e184acb4 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -32,7 +32,6 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/l10n/l10n_util.h"
 
-
 #if defined(OS_CHROMEOS)
 #include "ash/common/system/chromeos/devicetype_utils.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -653,6 +652,15 @@
   AddLocalizedStringsBulk(html_source, storage_strings,
                           arraysize(storage_strings));
 
+  LocalizedString power_strings[] = {
+      {"powerSourceLabel", IDS_SETTINGS_POWER_SOURCE_LABEL},
+      {"powerSourceBattery", IDS_SETTINGS_POWER_SOURCE_BATTERY},
+      {"powerSourceAcAdapter", IDS_SETTINGS_POWER_SOURCE_AC_ADAPTER},
+      {"powerSourceLowPowerCharger",
+       IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER},
+      {"calculatingPower", IDS_SETTINGS_POWER_SOURCE_CALCULATING}};
+  AddLocalizedStringsBulk(html_source, power_strings, arraysize(power_strings));
+
   html_source->AddString("naturalScrollLearnMoreLink",
                          base::ASCIIToUTF16(chrome::kNaturalScrollHelpURL));
 }
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index d378f57..910ca3b 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -44,8 +44,10 @@
 
 #if defined(OS_CHROMEOS)
 #include "ash/common/system/chromeos/palette/palette_utils.h"
+#include "ash/common/system/chromeos/power/power_status.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+#include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h"
@@ -53,9 +55,11 @@
 #include "chrome/browser/ui/webui/settings/chromeos/date_time_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h"
+#include "chrome/common/chrome_switches.h"
 #else  // !defined(OS_CHROMEOS)
 #include "chrome/browser/ui/webui/settings/settings_default_browser_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_manage_profile_handler.h"
@@ -153,6 +157,18 @@
       "androidAppsAllowed",
       arc::ArcSessionManager::IsAllowedForProfile(profile) &&
           !arc::ArcSessionManager::IsOptInVerificationDisabled());
+
+  // TODO(mash): Support Chrome power settings in Mash. crbug.com/644348
+  bool enable_power_settings =
+      !chrome::IsRunningInMash() &&
+      (switches::PowerOverlayEnabled() ||
+       (ash::PowerStatus::Get()->IsBatteryPresent() &&
+        ash::PowerStatus::Get()->SupportsDualRoleDevices()));
+  html_source->AddBoolean("enablePowerSettings", enable_power_settings);
+  if (enable_power_settings) {
+    AddSettingsPageUIHandler(
+        base::MakeUnique<chromeos::settings::PowerHandler>());
+  }
 #endif
 
   AddSettingsPageUIHandler(
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 254e8314..4a1f66e 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -719,6 +719,10 @@
 TEST_F('CrSettingsDevicePageTest', 'PointersTest', function() {
   mocha.grep(assert(device_page_tests.TestNames.Pointers)).run();
 });
+
+TEST_F('CrSettingsDevicePageTest', 'PowerTest', function() {
+  mocha.grep(assert(device_page_tests.TestNames.Power)).run();
+});
 GEN('#endif');
 
 /**
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js
index 477d274..224583cd 100644
--- a/chrome/test/data/webui/settings/device_page_tests.js
+++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -9,6 +9,7 @@
     Display: 'display',
     Keyboard: 'keyboard',
     Pointers: 'pointers',
+    Power: 'power',
   };
 
   /**
@@ -17,6 +18,7 @@
    */
   function TestDevicePageBrowserProxy() {
     this.keyboardShortcutsOverlayShown_ = 0;
+    this.updatePowerStatusCalled_ = 0;
   }
 
   TestDevicePageBrowserProxy.prototype = {
@@ -42,6 +44,16 @@
     showKeyboardShortcutsOverlay: function() {
       this.keyboardShortcutsOverlayShown_++;
     },
+
+    /** @override */
+    updatePowerStatus: function() {
+      this.updatePowerStatusCalled_++;
+    },
+
+    /** @override */
+    setPowerSource: function(powerSourceId) {
+      this.powerSourceId_ = powerSourceId;
+    },
   };
 
   function getFakePrefs() {
@@ -525,6 +537,168 @@
         expectTrue(displayPage.isMirrored_(displayPage.displays));
       });
     });
+
+    suite(assert(TestNames.Power), function() {
+      /**
+       * Sets power sources using a deep copy of |sources|.
+       * @param {Array<settings.PowerSource>} sources
+       * @param {string} powerSourceId
+       * @param {bool} isLowPowerCharger
+       */
+      function setPowerSources(sources, powerSourceId, isLowPowerCharger) {
+        var sourcesCopy = sources.map(function(source) {
+          return Object.assign({}, source);
+        });
+        cr.webUIListenerCallback('power-sources-changed',
+            sourcesCopy, powerSourceId, isLowPowerCharger);
+      }
+
+      suite('no power settings', function() {
+        test('power row hidden', function() {
+          assertEquals(null, devicePage.$$('#powerRow'));
+          assertEquals(0,
+              settings.DevicePageBrowserProxyImpl.getInstance()
+              .updatePowerStatusCalled_);
+        });
+      });
+
+      suite('power settings', function() {
+        var powerRow;
+        var powerSourceWrapper;
+        var powerSourceSelect;
+
+        suiteSetup(function() {
+          // Always show power settings.
+          loadTimeData.overrideValues({
+            enablePowerSettings: true,
+          });
+        });
+
+        setup(function() {
+          powerRow = assert(devicePage.$$('#powerRow'));
+          powerSourceWrapper =
+              assert(powerRow.querySelector('.md-select-wrapper'));
+          powerSourceSelect = assert(devicePage.$$('#powerSource'));
+          assertEquals(1,
+              settings.DevicePageBrowserProxyImpl.getInstance()
+              .updatePowerStatusCalled_);
+        });
+
+        test('battery status', function() {
+          var icon = powerRow.querySelector('iron-icon');
+          assertEquals('settings:battery-unknown', icon.icon);
+
+          // Start at 50%.
+          var batteryStatus = {
+            charging: false,
+            calculating: false,
+            percent: 50,
+            statusText: '5 hours left',
+          };
+          cr.webUIListenerCallback(
+              'battery-status-changed', Object.assign({}, batteryStatus));
+          setPowerSources([], '', false);
+          assertEquals(icon.icon, 'settings:battery-50');
+
+          // Update to charging.
+          var powerSource = {
+            id: '1',
+            type: settings.PowerDeviceType.DEDICATED_CHARGER,
+            description: 'AC adapter',
+          };
+          batteryStatus.charging = true;
+          batteryStatus.percent = 65;
+          cr.webUIListenerCallback(
+              'battery-status-changed', Object.assign({}, batteryStatus));
+          setPowerSources([powerSource], powerSource.id, false);
+          assertEquals(icon.icon, 'settings:battery-charging-60');
+
+          // Update with a low-power charger.
+          setPowerSources([powerSource], powerSource.id, true);
+          assertEquals(icon.icon, 'settings:battery-unreliable');
+
+          // Update with no charger and a critical battery level.
+          batteryStatus.charging = false;
+          batteryStatus.percent = 2;
+          cr.webUIListenerCallback(
+              'battery-status-changed', Object.assign({}, batteryStatus));
+          setPowerSources([], '', false);
+          assertEquals(icon.icon, 'settings:battery-alert');
+        });
+
+        test('power sources', function() {
+          var batteryStatus = {
+            charging: false,
+            calculating: false,
+            percent: 50,
+            statusText: '5 hours left',
+          };
+          cr.webUIListenerCallback(
+              'battery-status-changed', Object.assign({}, batteryStatus));
+          setPowerSources([], '', false);
+          Polymer.dom.flush();
+
+          // Power sources dropdown is hidden.
+          assertTrue(powerSourceWrapper.hidden);
+
+          // Attach a dual-role USB device.
+          var powerSource = {
+            id: '2',
+            type: settings.PowerDeviceType.DUAL_ROLE_USB,
+            description: 'USB-C device',
+          };
+          setPowerSources([powerSource], '', false);
+          Polymer.dom.flush();
+
+          // "Battery" should be selected.
+          assertFalse(powerSourceWrapper.hidden);
+          assertEquals('', powerSourceSelect.value);
+
+          // Select the power source.
+          setPowerSources([powerSource], powerSource.id, true);
+          Polymer.dom.flush();
+          assertFalse(powerSourceWrapper.hidden);
+          assertEquals(powerSource.id, powerSourceSelect.value);
+
+          // Send another power source; the first should still be selected.
+          var otherPowerSource = Object.assign({}, powerSource);
+          otherPowerSource.id = '3';
+          setPowerSources(
+              [otherPowerSource, powerSource], powerSource.id, true);
+          Polymer.dom.flush();
+          assertFalse(powerSourceWrapper.hidden);
+          assertEquals(powerSource.id, powerSourceSelect.value);
+        });
+
+        test('choose power source', function() {
+          var batteryStatus = {
+            charging: false,
+            calculating: false,
+            percent: 50,
+            statusText: '5 hours left',
+          };
+          cr.webUIListenerCallback(
+              'battery-status-changed', Object.assign({}, batteryStatus));
+
+          // Attach a dual-role USB device.
+          var powerSource = {
+            id: '3',
+            type: settings.PowerDeviceType.DUAL_ROLE_USB,
+            description: 'USB-C device',
+          };
+          setPowerSources([powerSource], '', false);
+          Polymer.dom.flush();
+
+          // Select the device.
+          powerSourceSelect.value = powerSourceSelect.children[1].value;
+          powerSourceSelect.dispatchEvent(new CustomEvent('change'));
+          Polymer.dom.flush();
+          expectEquals(
+              powerSource.id,
+              settings.DevicePageBrowserProxyImpl.getInstance().powerSourceId_);
+        });
+      });
+    });
   });
 
   return {