diff --git a/core/lib/Drupal/Core/Session/AccountInterface.php b/core/lib/Drupal/Core/Session/AccountInterface.php
index b56fe9b..17df07d 100644
--- a/core/lib/Drupal/Core/Session/AccountInterface.php
+++ b/core/lib/Drupal/Core/Session/AccountInterface.php
@@ -112,7 +112,17 @@ public function getPreferredLangcode($default = NULL);
   public function getPreferredAdminLangcode($default = NULL);
 
   /**
-   * Returns the username of this account.
+   * Returns the unique username of this account.
+   *
+   * @return string
+   *   An unsanitized string with the unique username. The code receiving this
+   *   result must ensure that \Drupal\Component\Utility\String::checkPlain()
+   *   is called on it before it is printed to the page.
+   */
+  public function getUsername();
+
+  /**
+   * Returns the display name of this account.
    *
    * By default, the passed-in object's 'name' property is used if it exists, or
    * else, the site-defined value for the 'anonymous' variable. However, a module
@@ -121,13 +131,13 @@ public function getPreferredAdminLangcode($default = NULL);
    *
    * @see hook_user_format_name_alter()
    *
-   * @return
-   *   An unsanitized string with the username to display. The code receiving
+   * @return string
+   *   An unsanitized string with the user name to display. The code receiving
    *   this result must ensure that \Drupal\Component\Utility\String::checkPlain()
    *   is called on it before it is
    *   printed to the page.
    */
-  public function getUsername();
+  public function getDisplayName();
 
   /**
    * Returns the e-mail address of this account.
diff --git a/core/lib/Drupal/Core/Session/AccountProxy.php b/core/lib/Drupal/Core/Session/AccountProxy.php
index 9f00218..7ac446b 100644
--- a/core/lib/Drupal/Core/Session/AccountProxy.php
+++ b/core/lib/Drupal/Core/Session/AccountProxy.php
@@ -166,6 +166,13 @@ public function getUsername() {
   /**
    * {@inheritdoc}
    */
+  public function getDisplayName() {
+    return $this->getAccount()->getDisplayName();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getEmail() {
     return $this->getAccount()->getEmail();
   }
diff --git a/core/lib/Drupal/Core/Session/UserSession.php b/core/lib/Drupal/Core/Session/UserSession.php
index 704fc79..884fd4e 100644
--- a/core/lib/Drupal/Core/Session/UserSession.php
+++ b/core/lib/Drupal/Core/Session/UserSession.php
@@ -217,6 +217,14 @@ function getPreferredAdminLangcode($default = NULL) {
    * {@inheritdoc}
    */
   public function getUsername() {
+    $name = $this->name ?: '';
+    return $name;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDisplayName() {
     $name = $this->name ?: \Drupal::config('user.settings')->get('anonymous');
     \Drupal::moduleHandler()->alter('user_format_name', $name, $this);
     return $name;
diff --git a/core/modules/contact/src/Controller/ContactController.php b/core/modules/contact/src/Controller/ContactController.php
index 4c7a58e..f4a4bad 100644
--- a/core/modules/contact/src/Controller/ContactController.php
+++ b/core/modules/contact/src/Controller/ContactController.php
@@ -116,7 +116,7 @@ public function contactPersonalPage(UserInterface $user) {
     ));
 
     $form = $this->entityFormBuilder()->getForm($message);
-    $form['#title'] = $this->t('Contact @username', array('@username' => $user->getUsername()));
+    $form['#title'] = $this->t('Contact @username', array('@username' => $user->getDisplayName()));
     return $form;
   }
 
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 1b9b8f8..e5eda4c 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -635,7 +635,7 @@ function template_preprocess_forums(&$variables) {
         }
         $forum_submitted = array('#theme' => 'forum_submitted', '#topic' => (object) array(
           'uid' => $topic->getOwnerId(),
-          'name' => $topic->getOwner()->getUsername(),
+          'name' => $topic->getOwner()->getDisplayName(),
           'created' => $topic->getCreatedTime(),
         ));
         $variables['topics'][$id]->submitted = drupal_render($forum_submitted);
diff --git a/core/modules/node/src/Plugin/views/row/Rss.php b/core/modules/node/src/Plugin/views/row/Rss.php
index 2df6281..d57bba5 100644
--- a/core/modules/node/src/Plugin/views/row/Rss.php
+++ b/core/modules/node/src/Plugin/views/row/Rss.php
@@ -119,7 +119,7 @@ public function render($row) {
       ),
       array(
         'key' => 'dc:creator',
-        'value' => $node->getOwner()->getUsername(),
+        'value' => $node->getOwner()->getDisplayName(),
       ),
       array(
         'key' => 'guid',
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 8ea735b..1ca0b4f 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -362,7 +362,7 @@ function rdf_preprocess_user(&$variables) {
         '#attributes' => array(
           'about' => $account->url(),
           'property' => $name_mapping['properties'],
-          'content' => $account->getUsername(),
+          'content' => $account->getDisplayName(),
           'lang' => '',
         ),
       );
diff --git a/core/modules/shortcut/shortcut.admin.inc b/core/modules/shortcut/shortcut.admin.inc
index 2444eec..24e087d 100644
--- a/core/modules/shortcut/shortcut.admin.inc
+++ b/core/modules/shortcut/shortcut.admin.inc
@@ -143,7 +143,7 @@ function shortcut_set_switch_submit($form, &$form_state) {
     ));
     $set->save();
     $replacements = array(
-      '%user' => $account->getUsername(),
+      '%user' => $account->getDisplayName(),
       '%set_name' => $set->label(),
       '@switch-url' => url(current_path()),
     );
@@ -166,7 +166,7 @@ function shortcut_set_switch_submit($form, &$form_state) {
     // Switch to a different shortcut set.
     $set = ShortcutSet::load($form_state['values']['set']);
     $replacements = array(
-      '%user' => $account->getUsername(),
+      '%user' => $account->getDisplayName(),
       '%set_name' => $set->label(),
     );
     drupal_set_message($account->id() == $user->id() ? t('You are now using the %set_name shortcut set.', $replacements) : t('%user is now using the %set_name shortcut set.', $replacements));
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 25eb641..ae2f90d 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -422,7 +422,15 @@ public function isAnonymous() {
    * {@inheritdoc}
    */
   public function getUsername() {
-    $name = $this->get('name')->value ?: \Drupal::config('user.settings')->get('anonymous');
+    $name = $this->get('name')->value ?: '';
+    return $name;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDisplayName() {
+    $name = $this->getUsername() ?: \Drupal::config('user.settings')->get('anonymous');
     \Drupal::moduleHandler()->alter('user_format_name', $name, $this);
     return $name;
   }
diff --git a/core/modules/user/src/Plugin/Search/UserSearch.php b/core/modules/user/src/Plugin/Search/UserSearch.php
index ce456b7..fe28da2 100644
--- a/core/modules/user/src/Plugin/Search/UserSearch.php
+++ b/core/modules/user/src/Plugin/Search/UserSearch.php
@@ -139,7 +139,7 @@ public function execute() {
 
     foreach ($accounts as $account) {
       $result = array(
-        'title' => $account->getUsername(),
+        'title' => $account->getDisplayName(),
         'link' => url('user/' . $account->id(), array('absolute' => TRUE)),
       );
       if ($this->currentUser->hasPermission('administer users')) {
diff --git a/core/modules/user/src/Tests/UserEditedOwnAccountTest.php b/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
index 2437aec..c8d2d0b 100644
--- a/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
+++ b/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
@@ -14,6 +14,13 @@
  */
 class UserEditedOwnAccountTest extends WebTestBase {
 
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('user_form_test');
+
   public static function getInfo() {
     return array(
       'name' => 'User edited own account',
diff --git a/core/modules/user/src/Tests/UserEntityCallbacksTest.php b/core/modules/user/src/Tests/UserEntityCallbacksTest.php
index 2b90534..bd8db2d 100644
--- a/core/modules/user/src/Tests/UserEntityCallbacksTest.php
+++ b/core/modules/user/src/Tests/UserEntityCallbacksTest.php
@@ -19,13 +19,18 @@ class UserEntityCallbacksTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('user');
+  public static $modules = array('user', 'user_name_test');
 
   /**
    * @var \Drupal\user\UserInterface
    */
   protected $account;
 
+  /**
+   * @var \Drupal\user\UserInterface
+   */
+  protected $anonymous;
+
   public static function getInfo() {
     return array(
       'name' => 'User entity callback tests',
@@ -51,6 +56,13 @@ function testLabelCallback() {
     $name = $this->randomName();
     \Drupal::config('user.settings')->set('anonymous', $name)->save();
     $this->assertEqual($this->anonymous->label(), $name, 'The variable anonymous should be used for name of uid 0');
+    $this->assertEqual($this->anonymous->getUserName(), '', 'The raw anonymous user name should be empty string');
+
+    // Set to test the altered username.
+    \Drupal::state()->set('user_name_test_altered_name', 'altered');
+
+    $this->assertEqual($this->account->getDisplayName(), $this->account->name->value . 'altered', 'The user display name should be altered.');
+    $this->assertEqual($this->account->getUsername(), $this->account->name->value, 'The user name should not be altered.');
   }
 
   /**
diff --git a/core/modules/user/src/UserAutocomplete.php b/core/modules/user/src/UserAutocomplete.php
index c831c78..fb18067 100644
--- a/core/modules/user/src/UserAutocomplete.php
+++ b/core/modules/user/src/UserAutocomplete.php
@@ -91,7 +91,7 @@ public function getMatches($string, $include_anonymous = FALSE) {
 
       $controller = $this->entityManager->getStorage('user');
       foreach ($controller->loadMultiple($uids) as $account) {
-        $matches[] = array('value' => $account->getUsername(), 'label' => String::checkPlain($account->getUsername()));
+        $matches[] = array('value' => $account->getUsername(), 'label' => String::checkPlain($account->getDisplayName()));
       }
     }
 
diff --git a/core/modules/user/tests/modules/user_name_test/user_name_test.info.yml b/core/modules/user/tests/modules/user_name_test/user_name_test.info.yml
new file mode 100644
index 0000000..8a5e1cc
--- /dev/null
+++ b/core/modules/user/tests/modules/user_name_test/user_name_test.info.yml
@@ -0,0 +1,7 @@
+name: 'User name tests'
+type: module
+description: 'Support module for user name testing.'
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/user/tests/modules/user_name_test/user_name_test.module b/core/modules/user/tests/modules/user_name_test/user_name_test.module
new file mode 100644
index 0000000..3603465
--- /dev/null
+++ b/core/modules/user/tests/modules/user_name_test/user_name_test.module
@@ -0,0 +1,12 @@
+<?php
+/**
+ * @file
+ * User name tests bootstrap file.
+ */
+
+/**
+ * Implements hook_user_format_name_alter().
+ */
+function user_name_test_user_format_name_alter(&$name, $account) {
+  $name .= \Drupal::state()->get('user_name_test_altered_name');
+}
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 4b28c81..0770b38 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -589,7 +589,7 @@ function user_preprocess_block(&$variables) {
  *   Use \Drupal\Core\Session\Interface::getUsername().
  */
 function user_format_name(AccountInterface $account) {
-  return $account->getUsername();
+  return $account->getDisplayName();
 }
 
 /**
@@ -638,7 +638,7 @@ function template_preprocess_username(&$variables) {
   // unsanitized version, in case other preprocess functions want to implement
   // their own shortening logic or add markup. If they do so, they must ensure
   // that $variables['name'] is safe for printing.
-  $name = $variables['name_raw'] = $account->getUsername();
+  $name = $variables['name_raw'] = $account->getDisplayName();
   if (drupal_strlen($name) > 20) {
     $name = drupal_substr($name, 0, 15) . '...';
     $variables['truncated'] = TRUE;
@@ -964,8 +964,8 @@ function _user_cancel($edit, $account, $method) {
       }
       $account->block();
       $account->save();
-      drupal_set_message(t('%name has been disabled.', array('%name' => $account->getUsername())));
-      watchdog('user', 'Blocked user: %name %email.', array('%name' => $account->getUsername(), '%email' => '<' . $account->getEmail() . '>'), WATCHDOG_NOTICE);
+      drupal_set_message(t('%name has been disabled.', array('%name' => $account->getDisplayName())));
+      watchdog('user', 'Blocked user: %name %email.', array('%name' => $account->getDisplayName(), '%email' => '<' . $account->getEmail() . '>'), WATCHDOG_NOTICE);
       break;
 
     case 'user_cancel_reassign':
@@ -975,8 +975,8 @@ function _user_cancel($edit, $account, $method) {
         _user_mail_notify('status_canceled', $account);
       }
       $account->delete();
-      drupal_set_message(t('%name has been deleted.', array('%name' => $account->getUsername())));
-      watchdog('user', 'Deleted user: %name %email.', array('%name' => $account->getUsername(), '%email' => '<' . $account->getEmail() . '>'), WATCHDOG_NOTICE);
+      drupal_set_message(t('%name has been deleted.', array('%name' => $account->getDisplayName())));
+      watchdog('user', 'Deleted user: %name %email.', array('%name' => $account->getDisplayName(), '%email' => '<' . $account->getEmail() . '>'), WATCHDOG_NOTICE);
       break;
   }
 
@@ -1652,7 +1652,7 @@ function user_toolbar() {
     '#type' => 'toolbar_item',
     'tab' => array(
       '#type' => 'link',
-      '#title' => $user->getUsername(),
+      '#title' => $user->getDisplayName(),
       '#href' => 'user',
       '#attributes' => array(
         'title' => t('My account'),
@@ -1686,7 +1686,7 @@ function user_toolbar() {
 function user_logout() {
   $user = \Drupal::currentUser();
 
-  watchdog('user', 'Session closed for %name.', array('%name' => $user->getUsername()));
+  watchdog('user', 'Session closed for %name.', array('%name' => $user->getDisplayName()));
 
   \Drupal::moduleHandler()->invokeAll('user_logout', array($user));
 
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index 964323c..2ed76c7 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -26,14 +26,14 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
   if ($user->isAuthenticated()) {
     // The existing user is already logged in.
     if ($user->id() == $uid) {
-      drupal_set_message(t('You are logged in as %user. <a href="!user_edit">Change your password.</a>', array('%user' => $user->getUsername(), '!user_edit' => url("user/" . $user->id() . "/edit"))));
+      drupal_set_message(t('You are logged in as %user. <a href="!user_edit">Change your password.</a>', array('%user' => $user->getDisplayName(), '!user_edit' => url("user/" . $user->id() . "/edit"))));
     }
     // A different user is already logged in on the computer.
     else {
       $reset_link_account = user_load($uid);
       if (!empty($reset_link_account)) {
         drupal_set_message(t('Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please <a href="!logout">logout</a> and try using the link again.',
-          array('%other_user' => $user->getUsername(), '%resetting_user' => $reset_link_account->getUsername(), '!logout' => url('user/logout'))));
+          array('%other_user' => $user->getDisplayName(), '%resetting_user' => $reset_link_account->getDisplayName(), '!logout' => url('user/logout'))));
       } else {
         // Invalid one-time link specifies an unknown user.
         drupal_set_message(t('The one-time login link you clicked is invalid.'));
@@ -60,7 +60,7 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
           // user_login_finalize() also updates the login timestamp of the
           // user, which invalidates further use of the one-time login link.
           user_login_finalize($account);
-          watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->getUsername(), '%timestamp' => $timestamp));
+          watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->getDisplayName(), '%timestamp' => $timestamp));
           drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
           // Let the user's password be changed without the current password check.
           $token = Crypt::randomBytesBase64(55);
@@ -73,10 +73,10 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
         else {
           if (!$account->getLastLoginTime()) {
             // No expiration for first time login.
-            $form['message'] = array('#markup' => t('<p>This is a one-time login for %user_name.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $account->getUsername())));
+            $form['message'] = array('#markup' => t('<p>This is a one-time login for %user_name.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $account->getDisplayName())));
           }
           else {
-            $form['message'] = array('#markup' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $account->getUsername(), '%expiration_date' => format_date($timestamp + $timeout))));
+            $form['message'] = array('#markup' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $account->getDisplayName(), '%expiration_date' => format_date($timestamp + $timeout))));
           }
           $form['help'] = array('#markup' => '<p>' . t('This login can be used only once.') . '</p>');
           $form['actions'] = array('#type' => 'actions');
