diff --git a/core/core.services.yml b/core/core.services.yml
index a573e2c1bb..f35d565cbe 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1721,3 +1721,6 @@ services:
     arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '%tempstore.expire%']
     tags:
       - { name: backend_overridable }
+  pager.manager:
+    class: Drupal\Core\Pager\PagerManager
+    arguments: ['@request_stack']
diff --git a/core/includes/pager.inc b/core/includes/pager.inc
index 62e8278ed2..a38fe3847a 100644
--- a/core/includes/pager.inc
+++ b/core/includes/pager.inc
@@ -5,8 +5,6 @@
  * Functions to aid in presenting database results as a set of pages.
  */
 
-use Drupal\Component\Utility\UrlHelper;
-
 /**
  * Returns the current page being requested for display within a pager.
  *
@@ -23,15 +21,17 @@
  *   even though the default pager implementation adjusts for this and still
  *   displays the third page of search results at that URL.
  *
+ * @deprecated in 8.7.x for removal before Drupal 9.0.0. Use
+ *   \Drupal::service('pager.manager')->findPage() instead.
+ *
+ * @see https://www.drupal.org/node/2779457
  * @see pager_default_initialize()
  */
 function pager_find_page($element = 0) {
-  $page = \Drupal::request()->query->get('page', '');
-  $page_array = explode(',', $page);
-  if (!isset($page_array[$element])) {
-    $page_array[$element] = 0;
-  }
-  return (int) $page_array[$element];
+  /* @var $pager_manager \Drupal\Core\Pager\PagerManager */
+  $pager_manager = \Drupal::service('pager.manager');
+  @trigger_error(__FUNCTION__ . ' is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service(\'pager.manager\')->findPage() instead. See https://www.drupal.org/node/2779457', E_USER_DEPRECATED);
+  return $pager_manager->findPage($element);
 }
 
 /**
@@ -123,18 +123,17 @@ function pager_find_page($element = 0) {
  *   that does not correspond to the actual range of the result set was
  *   requested, this function will return the closest page actually within the
  *   result set.
+ *
+ * @deprecated in 8.7.x for removal before Drupal 9.0.0. Use
+ *   \Drupal::service('pager.manager')->defaultInitialize() instead.
+ *
+ * @see https://www.drupal.org/node/2779457
  */
 function pager_default_initialize($total, $limit, $element = 0) {
-  global $pager_page_array, $pager_total, $pager_total_items, $pager_limits;
-
-  $page = pager_find_page($element);
-
-  // We calculate the total of pages as ceil(items / limit).
-  $pager_total_items[$element] = $total;
-  $pager_total[$element] = ceil($pager_total_items[$element] / $limit);
-  $pager_page_array[$element] = max(0, min($page, ((int) $pager_total[$element]) - 1));
-  $pager_limits[$element] = $limit;
-  return $pager_page_array[$element];
+  /* @var $pager_manager \Drupal\Core\Pager\PagerManager */
+  $pager_manager = \Drupal::service('pager.manager');
+  @trigger_error(__FUNCTION__ . ' is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service(\'pager.manager\')->defaultInitialize() instead. See https://www.drupal.org/node/2779457', E_USER_DEPRECATED);
+  return $pager_manager->defaultInitialize($total, $limit, $element);
 }
 
 /**
@@ -143,13 +142,17 @@ function pager_default_initialize($total, $limit, $element = 0) {
  * @return array
  *   A URL query parameter array that consists of all components of the current
  *   page request except for those pertaining to paging.
+ *
+ * @deprecated in 8.7.x for removal before Drupal 9.0.0. Use
+ *   \Drupal::service('pager.manager')->getQueryParameters() instead.
+ *
+ * @see https://www.drupal.org/node/2779457
  */
 function pager_get_query_parameters() {
-  $query = &drupal_static(__FUNCTION__);
-  if (!isset($query)) {
-    $query = UrlHelper::filterQueryParameters(\Drupal::request()->query->all(), ['page']);
-  }
-  return $query;
+  /* @var $pager_manager \Drupal\Core\Pager\PagerManager */
+  $pager_manager = \Drupal::service('pager.manager');
+  @trigger_error(__FUNCTION__ . ' is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service(\'pager.manager\')->getQueryParameters() instead. See https://www.drupal.org/node/2779457', E_USER_DEPRECATED);
+  return $pager_manager->getQueryParameters();
 }
 
 /**
@@ -307,25 +310,15 @@ function template_preprocess_pager(&$variables) {
  *
  * @return array
  *   The altered $query parameter array.
+ *
+ * @deprecated in 8.7.x for removal before Drupal 9.0.0. Use
+ *   \Drupal::service('pager.manager')->queryAddPage() instead.
+ *
+ * @see https://www.drupal.org/node/2779457
  */
 function pager_query_add_page(array $query, $element, $index) {
-  global $pager_page_array;
-
-  // Build the 'page' query parameter. This is built based on the current
-  // page of each pager element (or NULL if the pager is not set), with the
-  // exception of the requested page index for the current element.
-  $max_element = max(array_keys($pager_page_array));
-  $element_pages = [];
-  for ($i = 0; $i <= $max_element; $i++) {
-    $element_pages[] = ($i == $element) ? $index : (isset($pager_page_array[$i]) ? $pager_page_array[$i] : NULL);
-  }
-  $query['page'] = implode(',', $element_pages);
-
-  // Merge the query parameters passed to this function with the parameters
-  // from the current request. In case of collision, the parameters passed into
-  // this function take precedence.
-  if ($current_request_query = pager_get_query_parameters()) {
-    $query = array_merge($current_request_query, $query);
-  }
-  return $query;
+  /* @var $pager_manager \Drupal\Core\Pager\PagerManager */
+  $pager_manager = \Drupal::service('pager.manager');
+  @trigger_error(__FUNCTION__ . ' is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service(\'pager.manager\')->queryAddPage() instead. See https://www.drupal.org/node/2779457', E_USER_DEPRECATED);
+  return $pager_manager->queryAddPage($query, $element, $index);
 }
diff --git a/core/lib/Drupal/Core/Pager/PagerManager.php b/core/lib/Drupal/Core/Pager/PagerManager.php
new file mode 100644
index 0000000000..00cd2978ad
--- /dev/null
+++ b/core/lib/Drupal/Core/Pager/PagerManager.php
@@ -0,0 +1,220 @@
+<?php
+
+namespace Drupal\Core\Pager;
+
+use Drupal\Component\Utility\UrlHelper;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * This is a service for pager information.
+ *
+ * This class does not deal with pager render elements.
+ *
+ * Since there can be multiple pagers per requested page, each one is
+ * represented by an 'element' ID. It represents the index of the pager element
+ * within the 'page' query. The pager element is an integer telling us the
+ * current page number for that pager. (Page numbering is zero-based.)
+ *
+ * This class generally replaces the functions in core/includes/pager.inc. Those
+ * functions use globals to store data which they all use. Since we require
+ * backwards compatibility with this behavior, this class presents a public API
+ * for using pager information, which is implemented using the same globals as a
+ * 'backend.'
+ *
+ * @todo Re-implement the parts of this class that use globals in Drupal 9.
+ */
+class PagerManager implements PagerManagerInterface {
+
+  /**
+   * The HTTP request stack.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * Used to cache the query parameters computation.
+   *
+   * @var string
+   */
+  protected $queryParameters;
+
+  /**
+   * Construct a PagerManager object.
+   *
+   * @param \Symfony\Component\HttpFoundation\RequestStack $stack
+   *   The current HTTP request stack.
+   */
+  public function __construct(RequestStack $stack) {
+    $this->requestStack = $stack;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultInitialize($total, $limit, $element = 0) {
+    $page = $this->findPage($element);
+
+    $this->setTotalItems($element, $total);
+    $this->setTotal($element, ceil($this->getTotalItems($element) / $limit));
+    $this->setPagerPage($element, max(0, min($page, ((int) $this->getTotal($element)) - 1)));
+    $this->setLimit($element, $limit);
+
+    return $this->getPagerPage($element);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function findPage($element = 0) {
+    $page = $this->requestStack->getCurrentRequest()->query->get('page', '');
+    $page_array = explode(',', $page);
+    if (!isset($page_array[$element])) {
+      $page_array[$element] = 0;
+    }
+    return (int) $page_array[$element];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQueryParameters() {
+    if (empty($this->queryParameters)) {
+      $this->queryParameters = UrlHelper::filterQueryParameters(
+        $this->requestStack->getCurrentRequest()->query->all(), ['page']
+      );
+    }
+    return $this->queryParameters;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function queryAddPage(array $query, $element, $index) {
+    // Build the 'page' query parameter. This is built based on the current
+    // page of each pager element (or NULL if the pager is not set), with the
+    // exception of the requested page index for the current element.
+    $element_pages = [];
+    $max = $this->getMaxPagerPage();
+    for ($i = 0; $i <= $max; $i++) {
+      $element_pages[] = ($i == $element) ? $index : $this->getPagerPage($i);
+    }
+    $query['page'] = implode(',', $element_pages);
+
+    // Merge the query parameters passed to this function with the parameters
+    // from the current request. In case of collision, the parameters passed
+    // into this function take precedence.
+    if ($current_request_query = $this->getQueryParameters()) {
+      $query = array_merge($current_request_query, $query);
+    }
+    return $query;
+  }
+
+  /**
+   * Get the pager page for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   *
+   * @return int|null
+   *   Page number if present, NULL if not present. Counting starts at 0,
+   *   meaning the first page is number 0.
+   */
+  protected function getPagerPage($element) {
+    global $pager_page_array;
+    return isset($pager_page_array[$element]) ? $pager_page_array[$element] : NULL;
+  }
+
+  /**
+   * Gets the extent of the pager page element IDs.
+   *
+   * @return int
+   *   The maximum element ID available, -1 if there are no elements.
+   */
+  protected function getMaxPagerPage() {
+    global $pager_page_array;
+    return empty($pager_page_array) ? -1 : max(array_keys($pager_page_array));
+  }
+
+  /**
+   * Get the total items available for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   *
+   * @return int
+   *   The total items available to page through for the given pager element.
+   */
+  protected function getTotalItems($element) {
+    global $pager_total_items;
+    return $pager_total_items[$element];
+  }
+
+  /**
+   * Get the total for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   *
+   * @return int
+   *   Total for the element.
+   */
+  protected function getTotal($element) {
+    global $pager_total;
+    return $pager_total[$element];
+  }
+
+  /**
+   * Set the total number of items to be paged for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   * @param int $total
+   *   The total number value.
+   */
+  protected function setTotalItems($element, $total) {
+    global $pager_total_items;
+    $pager_total_items[$element] = $total;
+  }
+
+  /**
+   * Set the total for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   * @param int $total
+   *   The total.
+   */
+  protected function setTotal($element, $total) {
+    global $pager_total;
+    $pager_total[$element] = $total;
+  }
+
+  /**
+   * Set the current page for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   * @param int $page
+   *   The new current page.
+   */
+  protected function setPagerPage($element, $page) {
+    global $pager_page_array;
+    $pager_page_array[$element] = $page;
+  }
+
+  /**
+   * Set the number of items displayed per page, for the given pager element.
+   *
+   * @param int $element
+   *   The pager element.
+   * @param int $limit
+   *   The number of items that will be displayed per page, for the given
+   *   element.
+   */
+  protected function setLimit($element, $limit) {
+    global $pager_limits;
+    $pager_limits[$element] = $limit;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Pager/PagerManagerInterface.php b/core/lib/Drupal/Core/Pager/PagerManagerInterface.php
new file mode 100644
index 0000000000..ff6d9e2233
--- /dev/null
+++ b/core/lib/Drupal/Core/Pager/PagerManagerInterface.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace Drupal\Core\Pager;
+
+/**
+ * This is a service for pager information.
+ *
+ * This class does not deal with pager render elements.
+ *
+ * Since there can be multiple pagers per requested page, each one is
+ * represented by an 'element' ID. This is an integer. It represents the index
+ * of the pager element within the 'page' query. The pager element is an
+ * integer telling us the current page number for that pager.
+ *
+ * This class generally replaces the functions in core/includes/pager.inc. Those
+ * functions use globals to store data which they all use. Since we require
+ * backwards compatibility with this behavior, this class presents a public API
+ * for using pager information, which is implemented using the same globals as a
+ * 'backend.'
+ *
+ * @todo Re-implement the parts of this class that use globals in Drupal 9.
+ */
+interface PagerManagerInterface {
+
+  /**
+   * Initializes a pager.
+   *
+   * This function sets up the necessary variables so that the render system
+   * will correctly process #type 'pager' render arrays to output pagers that
+   * correspond to the items being displayed.
+   *
+   * If the items being displayed result from a database query performed using
+   * Drupal's database API, and if you have control over the construction of the
+   * database query, you do not need to call this function directly; instead,
+   * you can extend the query object with the 'PagerSelectExtender' extender
+   * before executing it. For example:
+   * @code
+   *   $query = db_select('some_table')
+   *     ->extend('Drupal\Core\Database\Query\PagerSelectExtender');
+   * @endcode
+   *
+   * However, if you are using a different method for generating the items to be
+   * paged through, then you should call this function in preparation.
+   *
+   * The following example shows how this function can be used in a controller
+   * that invokes an external datastore with an SQL-like syntax:
+   * @code
+   *   // First find the total number of items and initialize the pager.
+   *   $where = "status = 1";
+   *   $total = mymodule_select("SELECT COUNT(*) FROM data " . $where)->result();
+   *   $num_per_page = \Drupal::config('mymodule.settings')->get('num_per_page');
+   *   $page = \Drupal::service('pager.manager')->defaultInitialize($total, $num_per_page);
+   *
+   *   // Next, retrieve the items for the current page and put them into a
+   *   // render array.
+   *   $offset = $num_per_page * $page;
+   *   $result = mymodule_select("SELECT * FROM data " . $where . " LIMIT %d, %d", $offset, $num_per_page)->fetchAll();
+   *   $render = [];
+   *   $render[] = [
+   *     '#theme' => 'mymodule_results',
+   *     '#result' => $result,
+   *   ];
+   *
+   *   // Finally, add the pager to the render array, and return.
+   *   $render[] = ['#type' => 'pager'];
+   *   return $render;
+   * @endcode
+   *
+   * A second example involves a controller that invokes an external search
+   * service where the total number of matching results is provided as part of
+   * the returned set (so that we do not need a separate query in order to
+   * obtain this information). Here, we call pager_find_page() to calculate the
+   * desired offset before the search is invoked:
+   * @code
+   *   $pager_manager = \Drupal::service('pager.manager');
+   *   // Perform the query, using the requested offset from pager_find_page().
+   *   // This comes from a URL parameter, so here we are assuming that the URL
+   *   // parameter corresponds to an actual page of results that will exist
+   *   // within the set.
+   *   $page = $pager_manager->findPage();
+   *   $num_per_page = \Drupal::config('mymodule.settings')->get('num_per_page');
+   *   $offset = $num_per_page * $page;
+   *   $result = mymodule_remote_search($keywords, $offset, $num_per_page);
+   *
+   *   // Now that we have the total number of results, initialize the pager.
+   *   $pager_manager->defaultInitialize($result->total, $num_per_page);
+   *
+   *   // Create a render array with the search results.
+   *   $render = [];
+   *   $render[] = [
+   *     '#theme' => 'search_results',
+   *     '#results' => $result->data,
+   *     '#type' => 'remote',
+   *   ];
+   *
+   *   // Finally, add the pager to the render array, and return.
+   *   $render[] = ['#type' => 'pager'];
+   *   return $render;
+   * @endcode
+   *
+   * @param int $total
+   *   The total number of items to be paged.
+   * @param int $limit
+   *   The number of items the calling code will display per page.
+   * @param int $element
+   *   (optional) An integer to distinguish between multiple pagers on one page.
+   *
+   * @return int
+   *   The number of the current page, within the pager represented by $element.
+   *   This is determined from the URL query parameter
+   *   \Drupal::request()->query->get('page), or 0 by default. However, if a
+   *   page that does not correspond to the actual range of the result set was
+   *   requested, this function will return the closest page actually within the
+   *   result set.
+   */
+  public function defaultInitialize($total, $limit, $element = 0);
+
+  /**
+   * Returns the current page being requested for display within a pager.
+   *
+   * @param int $element
+   *   (optional) An integer to distinguish between multiple pagers on one page.
+   *
+   * @return int
+   *   The number of the current requested page, within the pager represented by
+   *   $element. This is determined from the URL query parameter
+   *   \Drupal::request()->query->get('page'), or 0 by default. Note that this
+   *   number may differ from the actual page being displayed. For example, if a
+   *   search for "example text" brings up three pages of results, but a user
+   *   visits search/node/example+text?page=10, this function will return 10,
+   *   even though the default pager implementation adjusts for this and still
+   *   displays the third page of search results at that URL.
+   */
+  public function findPage($element = 0);
+
+  /**
+   * Compose a URL query parameter array for pager links.
+   *
+   * @return array
+   *   A URL query parameter array that consists of all components of the
+   *   current page request except for those pertaining to paging.
+   */
+  public function getQueryParameters();
+
+  /**
+   * Gets the URL query parameter array of a pager link.
+   *
+   * Adds to or adjusts the 'page' URL query parameter so that if you follow the
+   * link, you'll get page $index for pager $element on the page.
+   *
+   * The 'page' URL query parameter is a comma-delimited string, where each
+   * value is the target content page for the corresponding pager $element. For
+   * instance, if we have 5 pagers on a single page, and we want to have a link
+   * to a page that should display the 6th content page for the 3rd pager, and
+   * the 1st content page for all the other pagers, then the URL query will look
+   * like this: ?page=0,0,5,0,0 (page numbering starts at zero).
+   *
+   * @param array $query
+   *   An associative array of URL query parameters to add to.
+   * @param int $element
+   *   An integer to distinguish between multiple pagers on one page.
+   * @param int $index
+   *   The index of the target page, for the given element, in the pager array.
+   *
+   * @return array
+   *   The altered $query parameter array.
+   */
+  public function queryAddPage(array $query, $element, $index);
+
+}
diff --git a/core/modules/system/tests/src/Functional/Pager/PagerTest.php b/core/modules/system/tests/src/Functional/Pager/PagerTest.php
index e0d5c54344..369390a1d6 100644
--- a/core/modules/system/tests/src/Functional/Pager/PagerTest.php
+++ b/core/modules/system/tests/src/Functional/Pager/PagerTest.php
@@ -10,6 +10,7 @@
  * Tests pager functionality.
  *
  * @group Pager
+ * @group legacy
  */
 class PagerTest extends BrowserTestBase {
 
@@ -48,6 +49,9 @@ protected function setUp() {
 
   /**
    * Tests markup and CSS classes of pager links.
+   *
+   * @expectedDeprecation pager_query_add_page is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;queryAddPage() instead. See https://www.drupal.org/node/2779457
+   * @expectedDeprecation pager_default_initialize is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;defaultInitialize() instead. See https://www.drupal.org/node/2779457
    */
   public function testActiveClass() {
     // Verify first page.
@@ -70,6 +74,10 @@ public function testActiveClass() {
 
   /**
    * Test proper functioning of the query parameters and the pager cache context.
+   *
+   * @expectedDeprecation pager_find_page is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;findPage() instead. See https://www.drupal.org/node/2779457
+   * @expectedDeprecation pager_default_initialize is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;defaultInitialize() instead. See https://www.drupal.org/node/2779457
+   * @expectedDeprecation pager_get_query_parameters is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;getQueryParameters() instead. See https://www.drupal.org/node/2779457
    */
   public function testPagerQueryParametersAndCacheContext() {
     // First page.
@@ -99,6 +107,9 @@ public function testPagerQueryParametersAndCacheContext() {
 
   /**
    * Test proper functioning of multiple pagers.
+   *
+   * @expectedDeprecation pager_query_add_page is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;queryAddPage() instead. See https://www.drupal.org/node/2779457
+   * @expectedDeprecation pager_default_initialize is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;defaultInitialize() instead. See https://www.drupal.org/node/2779457
    */
   public function testMultiplePagers() {
     // First page.
@@ -182,6 +193,9 @@ public function testMultiplePagers() {
 
   /**
    * Test proper functioning of the ellipsis.
+   *
+   * @expectedDeprecation pager_query_add_page is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;queryAddPage() instead. See https://www.drupal.org/node/2779457
+   * @expectedDeprecation pager_default_initialize is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')-&gt;defaultInitialize() instead. See https://www.drupal.org/node/2779457
    */
   public function testPagerEllipsis() {
     // Insert 100 extra log messages to get 9 pages.
diff --git a/core/modules/system/tests/src/Kernel/Pager/PagerDeprecationTest.php b/core/modules/system/tests/src/Kernel/Pager/PagerDeprecationTest.php
new file mode 100644
index 0000000000..8c5dcd24c3
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/Pager/PagerDeprecationTest.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Drupal\Tests\system\Kernel\Pager;
+
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Ensure that deprecated pager functions trigger deprecation errors.
+ *
+ * @group Pager
+ * @group legacy
+ */
+class PagerDeprecationTest extends KernelTestBase {
+
+  /**
+   * @expectedDeprecation pager_find_page is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')->findPage() instead. See https://www.drupal.org/node/2779457
+   */
+  public function testFindPage() {
+    $this->assertInternalType('int', pager_find_page());
+  }
+
+  /**
+   * @expectedDeprecation pager_default_initialize is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')->defaultInitialize() instead. See https://www.drupal.org/node/2779457
+   */
+  public function testDefaultInitialize() {
+    $this->assertInternalType('int', pager_default_initialize(1, 1));
+  }
+
+  /**
+   * @expectedDeprecation pager_get_query_parameters is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')->getQueryParameters() instead. See https://www.drupal.org/node/2779457
+   */
+  public function testGetQueryParameters() {
+    $this->assertInternalType('array', pager_get_query_parameters());
+  }
+
+  /**
+   * @expectedDeprecation pager_query_add_page is deprecated in 8.7.x for removal before Drupal 9.0.0. Use \Drupal::service('pager.manager')->queryAddPage() instead. See https://www.drupal.org/node/2779457
+   */
+  public function testQueryAddPage() {
+    $this->assertArrayHasKey('page', pager_query_add_page([], 1, 1));
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php b/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php
new file mode 100644
index 0000000000..f22f969446
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Pager;
+
+use Drupal\Core\Pager\PagerManager;
+use Drupal\KernelTests\KernelTestBase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @group Pager
+ *
+ * @coversDefaultClass \Drupal\Core\Pager\PagerManager
+ */
+class PagerManagerTest extends KernelTestBase {
+
+  /**
+   * @covers ::defaultInitialize
+   */
+  public function testDefaultInitializeGlobals() {
+    $pager_globals = [
+      'pager_page_array',
+      'pager_total_items',
+      'pager_total',
+      'pager_limits',
+    ];
+    foreach ($pager_globals as $pager_global) {
+      $this->assertFalse(isset($GLOBALS[$pager_global]));
+    }
+
+    $pm = new PagerManager($this->container->get('request_stack'));
+    $pm->defaultInitialize(5, 1);
+
+    foreach ($pager_globals as $pager_global) {
+      $this->assertTrue(isset($GLOBALS[$pager_global]));
+    }
+  }
+
+  /**
+   * @covers ::findPage
+   */
+  public function testFindPage() {
+    $request = Request::create('http://example.com', 'GET', ['page' => '0,10']);
+
+    /* @var $request_stack \Symfony\Component\HttpFoundation\RequestStack */
+    $request_stack = $this->container->get('request_stack');
+    $request_stack->push($request);
+
+    $pm = new PagerManager($request_stack);
+
+    $this->assertEquals(10, $pm->findPage(1));
+  }
+
+  /**
+   * @covers ::getQueryParameters
+   */
+  public function testGetQueryParameters() {
+    $test_parameters = [
+      'other' => 'arbitrary',
+    ];
+    $request = Request::create('http://example.com', 'GET', array_merge(['page' => '0,10'], $test_parameters));
+
+    /* @var $request_stack \Symfony\Component\HttpFoundation\RequestStack */
+    $request_stack = $this->container->get('request_stack');
+    $request_stack->push($request);
+
+    $pm = new PagerManager($request_stack);
+
+    $this->assertEquals($test_parameters, $pm->getQueryParameters());
+  }
+
+  /**
+   * @covers ::queryAddPage
+   */
+  public function testQueryAddPage() {
+    $element = 2;
+    $index = 5;
+    $test_parameters = [
+      'other' => 'arbitrary',
+    ];
+    $request = Request::create('http://example.com', 'GET', $test_parameters);
+
+    /* @var $request_stack \Symfony\Component\HttpFoundation\RequestStack */
+    $request_stack = $this->container->get('request_stack');
+    $request_stack->push($request);
+
+    $pm = new PagerManager($request_stack);
+    $pm->defaultInitialize(30, 10, $element);
+
+    $query = $pm->queryAddPage($request->query->all(), $element, $index);
+
+    $this->assertArrayHasKey('other', $query);
+
+    $this->assertEquals(",,$index", $query['page']);
+  }
+
+}
